authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-01 17:45:47+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-02 18:33:03+03:00
log292906fb2378bd37e02abf09e2be7f86ee657fac
treed8466e1f381b4e6782b080e945c5dfc7679ed802
parent4831c1c65f51ccfdb48c8d16bdf77435e0256070

Sema: fix reify Fn alignment and args


2 files changed, 56 insertions(+), 19 deletions(-)

src/Sema.zig+16-2
......@@ -16429,10 +16429,24 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1642916429 return sema.fail(block, src, "varargs functions must have C calling convention", .{});
1643016430 }
1643116431
16432 const alignment = @intCast(u29, alignment_val.toUnsignedInt(target)); // TODO: Validate this value.
16432 const alignment = alignment: {
16433 if (!try sema.intFitsInType(block, src, alignment_val, Type.u32, null)) {
16434 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
16435 }
16436 const alignment = @intCast(u29, alignment_val.toUnsignedInt(target));
16437 if (alignment == target_util.defaultFunctionAlignment(target)) {
16438 break :alignment 0;
16439 } else {
16440 break :alignment alignment;
16441 }
16442 };
1643316443 var buf: Value.ToTypeBuffer = undefined;
1643416444
16435 const args: []Value = if (args_val.castTag(.aggregate)) |some| some.data else &.{};
16445 const args_slice_val = args_val.castTag(.slice).?.data;
16446 const args_decl_index = args_slice_val.ptr.pointerDecl().?;
16447 try sema.ensureDeclAnalyzed(args_decl_index);
16448 const args_decl = mod.declPtr(args_decl_index);
16449 const args: []Value = if (args_decl.val.castTag(.aggregate)) |some| some.data else &.{};
1643616450 var param_types = try sema.arena.alloc(Type, args.len);
1643716451 var comptime_params = try sema.arena.alloc(bool, args.len);
1643816452 var noalias_bits: u32 = 0;
test/behavior/type.zig+40-17
......@@ -247,26 +247,17 @@ fn add(a: i32, b: i32) i32 {
247247}
248248
249249test "Type.ErrorSet" {
250 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
252
250253 try testing.expect(@Type(.{ .ErrorSet = null }) == anyerror);
251254
252255 // error sets don't compare equal so just check if they compile
253 _ = @Type(@typeInfo(error{}));
254 _ = @Type(@typeInfo(error{A}));
255 _ = @Type(@typeInfo(error{ A, B, C }));
256 _ = @Type(.{
257 .ErrorSet = &[_]Type.Error{
258 .{ .name = "A" },
259 .{ .name = "B" },
260 .{ .name = "C" },
261 },
262 });
263 _ = @Type(.{
264 .ErrorSet = &.{
265 .{ .name = "C" },
266 .{ .name = "B" },
267 .{ .name = "A" },
268 },
269 });
256 inline for (.{ error{}, error{A}, error{ A, B, C } }) |T| {
257 const info = @typeInfo(T);
258 const T2 = @Type(info);
259 try testing.expect(T == T2);
260 }
270261}
271262
272263test "Type.Struct" {
......@@ -517,3 +508,35 @@ test "Type.Union from regular enum" {
517508 _ = T;
518509 _ = @typeInfo(T).Union;
519510}
511
512test "Type.Fn" {
513 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
514 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
515
516 const some_opaque = opaque {};
517 const some_ptr = *some_opaque;
518 const T = fn (c_int, some_ptr) callconv(.C) void;
519
520 {
521 const fn_info = std.builtin.Type{ .Fn = .{
522 .calling_convention = .C,
523 .alignment = 0,
524 .is_generic = false,
525 .is_var_args = false,
526 .return_type = void,
527 .args = &.{
528 .{ .is_generic = false, .is_noalias = false, .arg_type = c_int },
529 .{ .is_generic = false, .is_noalias = false, .arg_type = some_ptr },
530 },
531 } };
532
533 const fn_type = @Type(fn_info);
534 try std.testing.expectEqual(T, fn_type);
535 }
536
537 {
538 const fn_info = @typeInfo(T);
539 const fn_type = @Type(fn_info);
540 try std.testing.expectEqual(T, fn_type);
541 }
542}