authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-22 20:30:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-22 20:30:20-07:00
loge08b6149ab8fb80ad8fa4983ad3aca8ef3303a9f
treef4e943be0e2c2f456fe46106cd6d6842a1b7d3ff
parente8b99428737c401afeb118fa277da362e903b3ca

Sema: fix alignment of type-inferred locals


5 files changed, 70 insertions(+), 28 deletions(-)

src/Sema.zig+36-12
......@@ -1415,10 +1415,6 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
14151415 const ptr = sema.resolveInst(bin_inst.rhs);
14161416
14171417 const addr_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);
1418 const ptr_ty = try Type.ptr(sema.arena, .{
1419 .pointee_type = pointee_ty,
1420 .@"addrspace" = addr_space,
1421 });
14221418
14231419 if (Air.refToIndex(ptr)) |ptr_inst| {
14241420 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
......@@ -1438,6 +1434,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
14381434 try inferred_alloc.stored_inst_list.append(sema.arena, operand);
14391435
14401436 try sema.requireRuntimeBlock(block, src);
1437 const ptr_ty = try Type.ptr(sema.arena, .{
1438 .pointee_type = pointee_ty,
1439 .@"align" = inferred_alloc.alignment,
1440 .@"addrspace" = addr_space,
1441 });
14411442 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
14421443 return bitcasted_ptr;
14431444 },
......@@ -1447,19 +1448,30 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
14471448 // The alloc will turn into a Decl.
14481449 var anon_decl = try block.startAnonDecl();
14491450 defer anon_decl.deinit();
1450 iac.data = try anon_decl.finish(
1451 iac.data.decl = try anon_decl.finish(
14511452 try pointee_ty.copy(anon_decl.arena()),
14521453 Value.undef,
14531454 );
1455 const ptr_ty = try Type.ptr(sema.arena, .{
1456 .pointee_type = pointee_ty,
1457 .@"align" = iac.data.alignment,
1458 .@"addrspace" = addr_space,
1459 });
14541460 return sema.addConstant(
14551461 ptr_ty,
14561462 try Value.Tag.decl_ref_mut.create(sema.arena, .{
1457 .decl = iac.data,
1463 .decl = iac.data.decl,
14581464 .runtime_index = block.runtime_index,
14591465 }),
14601466 );
14611467 },
1462 .decl_ref_mut => return sema.addConstant(ptr_ty, ptr_val),
1468 .decl_ref_mut => {
1469 const ptr_ty = try Type.ptr(sema.arena, .{
1470 .pointee_type = pointee_ty,
1471 .@"addrspace" = addr_space,
1472 });
1473 return sema.addConstant(ptr_ty, ptr_val);
1474 },
14631475 else => {},
14641476 }
14651477 }
......@@ -1491,6 +1503,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
14911503 sema.air_instructions.len -= 1;
14921504 }
14931505
1506 const ptr_ty = try Type.ptr(sema.arena, .{
1507 .pointee_type = pointee_ty,
1508 .@"addrspace" = addr_space,
1509 });
1510
14941511 var new_ptr = ptr;
14951512
14961513 while (true) {
......@@ -2183,7 +2200,10 @@ fn zirAllocExtended(
21832200 } else {
21842201 return sema.addConstant(
21852202 inferred_alloc_ty,
2186 try Value.Tag.inferred_alloc_comptime.create(sema.arena, undefined),
2203 try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
2204 .decl = undefined,
2205 .alignment = alignment,
2206 }),
21872207 );
21882208 }
21892209 }
......@@ -2208,7 +2228,7 @@ fn zirAllocExtended(
22082228 // to the block even though it is currently a `.constant`.
22092229 const result = try sema.addConstant(
22102230 inferred_alloc_ty,
2211 try Value.Tag.inferred_alloc.create(sema.arena, .{}),
2231 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = alignment }),
22122232 );
22132233 try sema.requireFunctionBlock(block, src);
22142234 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
......@@ -2302,7 +2322,7 @@ fn zirAllocInferred(
23022322 // to the block even though it is currently a `.constant`.
23032323 const result = try sema.addConstant(
23042324 inferred_alloc_ty,
2305 try Value.Tag.inferred_alloc.create(sema.arena, .{}),
2325 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = 0 }),
23062326 );
23072327 try sema.requireFunctionBlock(block, src);
23082328 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
......@@ -2331,12 +2351,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
23312351 switch (ptr_val.tag()) {
23322352 .inferred_alloc_comptime => {
23332353 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
2334 const decl = iac.data;
2354 const decl = iac.data.decl;
23352355 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
23362356
23372357 const final_elem_ty = try decl.ty.copy(sema.arena);
23382358 const final_ptr_ty = try Type.ptr(sema.arena, .{
23392359 .pointee_type = final_elem_ty,
2360 .@"align" = iac.data.alignment,
23402361 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
23412362 });
23422363 const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
......@@ -2365,6 +2386,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
23652386 // Change it to a normal alloc.
23662387 const final_ptr_ty = try Type.ptr(sema.arena, .{
23672388 .pointee_type = final_elem_ty,
2389 .@"align" = inferred_alloc.data.alignment,
23682390 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
23692391 });
23702392 sema.air_instructions.set(ptr_inst, .{
......@@ -2681,10 +2703,11 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
26812703 }
26822704 var anon_decl = try block.startAnonDecl();
26832705 defer anon_decl.deinit();
2684 iac.data = try anon_decl.finish(
2706 iac.data.decl = try anon_decl.finish(
26852707 try operand_ty.copy(anon_decl.arena()),
26862708 try operand_val.copy(anon_decl.arena()),
26872709 );
2710 // TODO set the alignment on the decl
26882711 return;
26892712 } else {
26902713 return sema.failWithNeededComptime(block, src);
......@@ -2698,6 +2721,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
26982721 // Create a runtime bitcast instruction with exactly the type the pointer wants.
26992722 const ptr_ty = try Type.ptr(sema.arena, .{
27002723 .pointee_type = operand_ty,
2724 .@"align" = inferred_alloc.data.alignment,
27012725 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
27022726 });
27032727 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
src/value.zig+14-1
......@@ -256,7 +256,6 @@ pub const Value = extern union {
256256
257257 .extern_fn,
258258 .decl_ref,
259 .inferred_alloc_comptime,
260259 => Payload.Decl,
261260
262261 .repeated,
......@@ -291,6 +290,7 @@ pub const Value = extern union {
291290 .float_128 => Payload.Float_128,
292291 .@"error" => Payload.Error,
293292 .inferred_alloc => Payload.InferredAlloc,
293 .inferred_alloc_comptime => Payload.InferredAllocComptime,
294294 .@"struct" => Payload.Struct,
295295 .@"union" => Payload.Union,
296296 .bound_fn => Payload.BoundFn,
......@@ -2889,6 +2889,19 @@ pub const Value = extern union {
28892889 /// the items are contiguous in memory and thus can be passed to
28902890 /// `Module.resolvePeerTypes`.
28912891 stored_inst_list: std.ArrayListUnmanaged(Air.Inst.Ref) = .{},
2892 /// 0 means ABI-aligned.
2893 alignment: u16,
2894 },
2895 };
2896
2897 pub const InferredAllocComptime = struct {
2898 pub const base_tag = Tag.inferred_alloc_comptime;
2899
2900 base: Payload = .{ .tag = base_tag },
2901 data: struct {
2902 decl: *Module.Decl,
2903 /// 0 means ABI-aligned.
2904 alignment: u16,
28922905 },
28932906 };
28942907
test/behavior.zig+1
......@@ -44,6 +44,7 @@ test {
4444
4545 if (builtin.object_format != .c) {
4646 // Tests that pass for stage1 and stage2 but not the C backend.
47 _ = @import("behavior/align_llvm.zig");
4748 _ = @import("behavior/array.zig");
4849 _ = @import("behavior/atomics.zig");
4950 _ = @import("behavior/basic_llvm.zig");
test/behavior/align_llvm.zig created+19
......@@ -0,0 +1,19 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4const native_arch = builtin.target.cpu.arch;
5
6test "page aligned array on stack" {
7 // Large alignment value to make it hard to accidentally pass.
8 var array align(0x1000) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
9 var number1: u8 align(16) = 42;
10 var number2: u8 align(16) = 43;
11
12 try expect(@ptrToInt(&array[0]) & 0xFFF == 0);
13 try expect(array[3] == 4);
14
15 try expect(@truncate(u4, @ptrToInt(&number1)) == 0);
16 try expect(@truncate(u4, @ptrToInt(&number2)) == 0);
17 try expect(number1 == 42);
18 try expect(number2 == 43);
19}
test/behavior/align_stage1.zig-15
......@@ -223,18 +223,3 @@ test "align(N) on functions" {
223223fn overaligned_fn() align(0x1000) i32 {
224224 return 42;
225225}
226
227test "page aligned array on stack" {
228 // Large alignment value to make it hard to accidentally pass.
229 var array align(0x1000) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
230 var number1: u8 align(16) = 42;
231 var number2: u8 align(16) = 43;
232
233 try expect(@ptrToInt(&array[0]) & 0xFFF == 0);
234 try expect(array[3] == 4);
235
236 try expect(@truncate(u4, @ptrToInt(&number1)) == 0);
237 try expect(@truncate(u4, @ptrToInt(&number2)) == 0);
238 try expect(number1 == 42);
239 try expect(number2 == 43);
240}