authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-22 21:56:32-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-23 21:40:03-04:00
logfe8bdf6f049e59cffe0033baa4d1738a64fd21cf
tree8d37291f9b748a43fb63847e861643913d6df6a9
parentc71b78eb0196cbad9fbb01ce9137d09796b48726

codegen: fix packed byte-aligned relocations

Closes #23131

8 files changed, 40 insertions(+), 32 deletions(-)

src/Zcu/PerThread.zig+2-2
...@@ -1705,7 +1705,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai...@@ -1705,7 +1705,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
1705 lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {1705 lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
1706 error.OutOfMemory => return error.OutOfMemory,1706 error.OutOfMemory => return error.OutOfMemory,
1707 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),1707 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
1708 error.Overflow => {1708 error.Overflow, error.RelocationNotByteAligned => {
1709 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(1709 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
1710 gpa,1710 gpa,
1711 zcu.navSrcLoc(nav_index),1711 zcu.navSrcLoc(nav_index),
...@@ -3131,7 +3131,7 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error...@@ -3131,7 +3131,7 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error
3131 lf.updateNav(pt, nav_index) catch |err| switch (err) {3131 lf.updateNav(pt, nav_index) catch |err| switch (err) {
3132 error.OutOfMemory => return error.OutOfMemory,3132 error.OutOfMemory => return error.OutOfMemory,
3133 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),3133 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
3134 error.Overflow => {3134 error.Overflow, error.RelocationNotByteAligned => {
3135 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(3135 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
3136 gpa,3136 gpa,
3137 zcu.navSrcLoc(nav_index),3137 zcu.navSrcLoc(nav_index),
src/codegen.zig+15-10
...@@ -23,10 +23,7 @@ const Zir = std.zig.Zir;...@@ -23,10 +23,7 @@ const Zir = std.zig.Zir;
23const Alignment = InternPool.Alignment;23const Alignment = InternPool.Alignment;
24const dev = @import("dev.zig");24const dev = @import("dev.zig");
2525
26pub const CodeGenError = error{26pub const CodeGenError = GenerateSymbolError || error{
27 OutOfMemory,
28 /// Compiler was asked to operate on a number larger than supported.
29 Overflow,
30 /// Indicates the error is already stored in Zcu `failed_codegen`.27 /// Indicates the error is already stored in Zcu `failed_codegen`.
31 CodegenFail,28 CodegenFail,
32};29};
...@@ -177,6 +174,8 @@ pub const GenerateSymbolError = error{...@@ -177,6 +174,8 @@ pub const GenerateSymbolError = error{
177 OutOfMemory,174 OutOfMemory,
178 /// Compiler was asked to operate on a number larger than supported.175 /// Compiler was asked to operate on a number larger than supported.
179 Overflow,176 Overflow,
177 /// Compiler was asked to produce a non-byte-aligned relocation.
178 RelocationNotByteAligned,
180};179};
181180
182pub fn generateSymbol(181pub fn generateSymbol(
...@@ -481,12 +480,18 @@ pub fn generateSymbol(...@@ -481,12 +480,18 @@ pub fn generateSymbol(
481 // pointer may point to a decl which must be marked used480 // pointer may point to a decl which must be marked used
482 // but can also result in a relocation. Therefore we handle those separately.481 // but can also result in a relocation. Therefore we handle those separately.
483 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .pointer) {482 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .pointer) {
484 const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(zcu)) orelse483 const field_offset = std.math.divExact(u16, bits, 8) catch |err| switch (err) {
485 return error.Overflow;484 error.DivisionByZero => unreachable,
486 var tmp_list = try std.ArrayListUnmanaged(u8).initCapacity(gpa, field_size);485 error.UnexpectedRemainder => return error.RelocationNotByteAligned,
487 defer tmp_list.deinit(gpa);486 };
488 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), &tmp_list, reloc_parent);487 code.items.len = current_pos + field_offset;
489 @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items);488 // TODO: code.lockPointers();
489 defer {
490 assert(code.items.len == current_pos + field_offset + @divExact(target.ptrBitWidth(), 8));
491 // TODO: code.unlockPointers();
492 code.items.len = current_pos + abi_size;
493 }
494 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);
490 } else {495 } else {
491 Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, code.items[current_pos..], bits) catch unreachable;496 Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, code.items[current_pos..], bits) catch unreachable;
492 }497 }
src/link.zig+3-8
...@@ -26,6 +26,7 @@ const Package = @import("Package.zig");...@@ -26,6 +26,7 @@ const Package = @import("Package.zig");
26const dev = @import("dev.zig");26const dev = @import("dev.zig");
27const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;27const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;
28const target_util = @import("target.zig");28const target_util = @import("target.zig");
29const codegen = @import("codegen.zig");
2930
30pub const LdScript = @import("link/LdScript.zig");31pub const LdScript = @import("link/LdScript.zig");
3132
...@@ -683,13 +684,7 @@ pub const File = struct {...@@ -683,13 +684,7 @@ pub const File = struct {
683684
684 /// Note that `LinkFailure` is not a member of this error set because the error message685 /// Note that `LinkFailure` is not a member of this error set because the error message
685 /// must be attached to `Zcu.failed_codegen` rather than `Compilation.link_diags`.686 /// must be attached to `Zcu.failed_codegen` rather than `Compilation.link_diags`.
686 pub const UpdateNavError = error{687 pub const UpdateNavError = codegen.CodeGenError;
687 Overflow,
688 OutOfMemory,
689 /// Indicates the error is already reported and stored in
690 /// `failed_codegen` on the Zcu.
691 CodegenFail,
692 };
693688
694 /// Called from within CodeGen to retrieve the symbol index of a global symbol.689 /// Called from within CodeGen to retrieve the symbol index of a global symbol.
695 /// If no symbol exists yet with this name, a new undefined global symbol will690 /// If no symbol exists yet with this name, a new undefined global symbol will
...@@ -920,7 +915,7 @@ pub const File = struct {...@@ -920,7 +915,7 @@ pub const File = struct {
920 decl_val: InternPool.Index,915 decl_val: InternPool.Index,
921 decl_align: InternPool.Alignment,916 decl_align: InternPool.Alignment,
922 src_loc: Zcu.LazySrcLoc,917 src_loc: Zcu.LazySrcLoc,
923 ) !@import("codegen.zig").GenResult {918 ) !codegen.GenResult {
924 switch (base.tag) {919 switch (base.tag) {
925 .c => unreachable,920 .c => unreachable,
926 .spirv => unreachable,921 .spirv => unreachable,
src/link/Coff.zig+1-1
...@@ -1134,7 +1134,7 @@ pub fn updateFunc(...@@ -1134,7 +1134,7 @@ pub fn updateFunc(
1134 ) catch |err| switch (err) {1134 ) catch |err| switch (err) {
1135 error.CodegenFail => return error.CodegenFail,1135 error.CodegenFail => return error.CodegenFail,
1136 error.OutOfMemory => return error.OutOfMemory,1136 error.OutOfMemory => return error.OutOfMemory,
1137 error.Overflow => |e| {1137 error.Overflow, error.RelocationNotByteAligned => |e| {
1138 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(1138 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
1139 gpa,1139 gpa,
1140 zcu.navSrcLoc(nav_index),1140 zcu.navSrcLoc(nav_index),
src/link/Dwarf.zig+1-2
...@@ -23,12 +23,11 @@ debug_str: StringSection,...@@ -23,12 +23,11 @@ debug_str: StringSection,
23pub const UpdateError = error{23pub const UpdateError = error{
24 ReinterpretDeclRef,24 ReinterpretDeclRef,
25 Unimplemented,25 Unimplemented,
26 OutOfMemory,
27 EndOfStream,26 EndOfStream,
28 Overflow,
29 Underflow,27 Underflow,
30 UnexpectedEndOfFile,28 UnexpectedEndOfFile,
31} ||29} ||
30 codegen.GenerateSymbolError ||
32 std.fs.File.OpenError ||31 std.fs.File.OpenError ||
33 std.fs.File.SetEndPosError ||32 std.fs.File.SetEndPosError ||
34 std.fs.File.CopyRangeError ||33 std.fs.File.CopyRangeError ||
src/link/Plan9.zig+3-1
...@@ -1090,7 +1090,9 @@ fn updateLazySymbolAtom(...@@ -1090,7 +1090,9 @@ fn updateLazySymbolAtom(
1090 ) catch |err| switch (err) {1090 ) catch |err| switch (err) {
1091 error.OutOfMemory => return error.OutOfMemory,1091 error.OutOfMemory => return error.OutOfMemory,
1092 error.CodegenFail => return error.LinkFailure,1092 error.CodegenFail => return error.LinkFailure,
1093 error.Overflow => return diags.fail("codegen failure: encountered number too big for compiler", .{}),1093 error.Overflow,
1094 error.RelocationNotByteAligned,
1095 => return diags.fail("unable to codegen: {s}", .{@errorName(err)}),
1094 };1096 };
1095 const code = code_buffer.items;1097 const code = code_buffer.items;
1096 // duped_code is freed when the atom is freed1098 // duped_code is freed when the atom is freed
src/register_manager.zig+1-8
...@@ -14,14 +14,7 @@ const link = @import("link.zig");...@@ -14,14 +14,7 @@ const link = @import("link.zig");
1414
15const log = std.log.scoped(.register_manager);15const log = std.log.scoped(.register_manager);
1616
17pub const AllocationError = error{17pub const AllocationError = @import("codegen.zig").CodeGenError || error{OutOfRegisters};
18 OutOfRegisters,
19 OutOfMemory,
20 /// Compiler was asked to operate on a number larger than supported.
21 Overflow,
22 /// Indicates the error is already stored in `failed_codegen` on the Zcu.
23 CodegenFail,
24};
2518
26pub fn RegisterManager(19pub fn RegisterManager(
27 comptime Function: type,20 comptime Function: type,
test/behavior/packed-struct.zig+14
...@@ -1349,3 +1349,17 @@ test "assign packed struct initialized with RLS to packed struct literal field"...@@ -1349,3 +1349,17 @@ test "assign packed struct initialized with RLS to packed struct literal field"
1349 try expect(outer.inner.x == x);1349 try expect(outer.inner.x == x);
1350 try expect(outer.x == x);1350 try expect(outer.x == x);
1351}1351}
1352
1353test "byte-aligned packed relocation" {
1354 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1355 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1356 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1357 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1358
1359 const S = struct {
1360 var global: u8 align(2) = 0;
1361 var packed_value: packed struct { x: u8, y: *align(2) u8 } = .{ .x = 111, .y = &global };
1362 };
1363 try expect(S.packed_value.x == 111);
1364 try expect(S.packed_value.y == &S.global);
1365}