Commit 292906fb23

Veikka Tuominen <git@vexu.eu>
2022-08-01 16:45:47
Sema: fix reify Fn alignment and args
1 parent 4831c1c
Changed files (2)
src
test
behavior
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;
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);
+    }
+}