From 292906fb2378bd37e02abf09e2be7f86ee657fac Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 1 Aug 2022 17:45:47 +0300 Subject: [PATCH] Sema: fix reify Fn alignment and args --- src/Sema.zig | 18 +++++++++++-- test/behavior/type.zig | 57 +++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 71ab59d7f9..67f04daf83 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16429,10 +16429,24 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I return sema.fail(block, src, "varargs functions must have C calling convention", .{}); } - const alignment = @intCast(u29, alignment_val.toUnsignedInt(target)); // TODO: Validate this value. + const alignment = alignment: { + if (!try sema.intFitsInType(block, src, alignment_val, Type.u32, null)) { + return sema.fail(block, src, "alignment must fit in 'u32'", .{}); + } + const alignment = @intCast(u29, alignment_val.toUnsignedInt(target)); + if (alignment == target_util.defaultFunctionAlignment(target)) { + break :alignment 0; + } else { + break :alignment alignment; + } + }; var buf: Value.ToTypeBuffer = undefined; - const args: []Value = if (args_val.castTag(.aggregate)) |some| some.data else &.{}; + const args_slice_val = args_val.castTag(.slice).?.data; + const args_decl_index = args_slice_val.ptr.pointerDecl().?; + try sema.ensureDeclAnalyzed(args_decl_index); + const args_decl = mod.declPtr(args_decl_index); + const args: []Value = if (args_decl.val.castTag(.aggregate)) |some| some.data else &.{}; var param_types = try sema.arena.alloc(Type, args.len); var comptime_params = try sema.arena.alloc(bool, args.len); var noalias_bits: u32 = 0; diff --git a/test/behavior/type.zig b/test/behavior/type.zig index 16a79a5122..4aec553527 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -247,26 +247,17 @@ fn add(a: i32, b: i32) i32 { } test "Type.ErrorSet" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + try testing.expect(@Type(.{ .ErrorSet = null }) == anyerror); // error sets don't compare equal so just check if they compile - _ = @Type(@typeInfo(error{})); - _ = @Type(@typeInfo(error{A})); - _ = @Type(@typeInfo(error{ A, B, C })); - _ = @Type(.{ - .ErrorSet = &[_]Type.Error{ - .{ .name = "A" }, - .{ .name = "B" }, - .{ .name = "C" }, - }, - }); - _ = @Type(.{ - .ErrorSet = &.{ - .{ .name = "C" }, - .{ .name = "B" }, - .{ .name = "A" }, - }, - }); + inline for (.{ error{}, error{A}, error{ A, B, C } }) |T| { + const info = @typeInfo(T); + const T2 = @Type(info); + try testing.expect(T == T2); + } } test "Type.Struct" { @@ -517,3 +508,35 @@ test "Type.Union from regular enum" { _ = T; _ = @typeInfo(T).Union; } + +test "Type.Fn" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + + const some_opaque = opaque {}; + const some_ptr = *some_opaque; + const T = fn (c_int, some_ptr) callconv(.C) void; + + { + const fn_info = std.builtin.Type{ .Fn = .{ + .calling_convention = .C, + .alignment = 0, + .is_generic = false, + .is_var_args = false, + .return_type = void, + .args = &.{ + .{ .is_generic = false, .is_noalias = false, .arg_type = c_int }, + .{ .is_generic = false, .is_noalias = false, .arg_type = some_ptr }, + }, + } }; + + const fn_type = @Type(fn_info); + try std.testing.expectEqual(T, fn_type); + } + + { + const fn_info = @typeInfo(T); + const fn_type = @Type(fn_info); + try std.testing.expectEqual(T, fn_type); + } +}