Skip to content

Commit 6705cbd

Browse files
jacobly0andrewrk
authored andcommitted
codegen: fix packed byte-aligned relocations
Closes #23131
1 parent f45f964 commit 6705cbd

File tree

8 files changed

+40
-32
lines changed

8 files changed

+40
-32
lines changed

src/Zcu/PerThread.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,7 +1705,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
17051705
lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
17061706
error.OutOfMemory => return error.OutOfMemory,
17071707
error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
1708-
error.Overflow => {
1708+
error.Overflow, error.RelocationNotByteAligned => {
17091709
try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
17101710
gpa,
17111711
zcu.navSrcLoc(nav_index),
@@ -3131,7 +3131,7 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error
31313131
lf.updateNav(pt, nav_index) catch |err| switch (err) {
31323132
error.OutOfMemory => return error.OutOfMemory,
31333133
error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
3134-
error.Overflow => {
3134+
error.Overflow, error.RelocationNotByteAligned => {
31353135
try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
31363136
gpa,
31373137
zcu.navSrcLoc(nav_index),

src/codegen.zig

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ const Zir = std.zig.Zir;
2323
const Alignment = InternPool.Alignment;
2424
const dev = @import("dev.zig");
2525

26-
pub const CodeGenError = error{
27-
OutOfMemory,
28-
/// Compiler was asked to operate on a number larger than supported.
29-
Overflow,
26+
pub const CodeGenError = GenerateSymbolError || error{
3027
/// Indicates the error is already stored in Zcu `failed_codegen`.
3128
CodegenFail,
3229
};
@@ -177,6 +174,8 @@ pub const GenerateSymbolError = error{
177174
OutOfMemory,
178175
/// Compiler was asked to operate on a number larger than supported.
179176
Overflow,
177+
/// Compiler was asked to produce a non-byte-aligned relocation.
178+
RelocationNotByteAligned,
180179
};
181180

182181
pub fn generateSymbol(
@@ -481,12 +480,18 @@ pub fn generateSymbol(
481480
// pointer may point to a decl which must be marked used
482481
// but can also result in a relocation. Therefore we handle those separately.
483482
if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .pointer) {
484-
const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(zcu)) orelse
485-
return error.Overflow;
486-
var tmp_list = try std.ArrayListUnmanaged(u8).initCapacity(gpa, field_size);
487-
defer tmp_list.deinit(gpa);
488-
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), &tmp_list, reloc_parent);
489-
@memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items);
483+
const field_offset = std.math.divExact(u16, bits, 8) catch |err| switch (err) {
484+
error.DivisionByZero => unreachable,
485+
error.UnexpectedRemainder => return error.RelocationNotByteAligned,
486+
};
487+
code.items.len = current_pos + field_offset;
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);
490495
} else {
491496
Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, code.items[current_pos..], bits) catch unreachable;
492497
}

src/link.zig

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const Package = @import("Package.zig");
2626
const dev = @import("dev.zig");
2727
const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;
2828
const target_util = @import("target.zig");
29+
const codegen = @import("codegen.zig");
2930

3031
pub const LdScript = @import("link/LdScript.zig");
3132

@@ -683,13 +684,7 @@ pub const File = struct {
683684

684685
/// Note that `LinkFailure` is not a member of this error set because the error message
685686
/// must be attached to `Zcu.failed_codegen` rather than `Compilation.link_diags`.
686-
pub const UpdateNavError = error{
687-
Overflow,
688-
OutOfMemory,
689-
/// Indicates the error is already reported and stored in
690-
/// `failed_codegen` on the Zcu.
691-
CodegenFail,
692-
};
687+
pub const UpdateNavError = codegen.CodeGenError;
693688

694689
/// Called from within CodeGen to retrieve the symbol index of a global symbol.
695690
/// If no symbol exists yet with this name, a new undefined global symbol will
@@ -920,7 +915,7 @@ pub const File = struct {
920915
decl_val: InternPool.Index,
921916
decl_align: InternPool.Alignment,
922917
src_loc: Zcu.LazySrcLoc,
923-
) !@import("codegen.zig").GenResult {
918+
) !codegen.GenResult {
924919
switch (base.tag) {
925920
.c => unreachable,
926921
.spirv => unreachable,

src/link/Coff.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ pub fn updateFunc(
11341134
) catch |err| switch (err) {
11351135
error.CodegenFail => return error.CodegenFail,
11361136
error.OutOfMemory => return error.OutOfMemory,
1137-
error.Overflow => |e| {
1137+
error.Overflow, error.RelocationNotByteAligned => |e| {
11381138
try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
11391139
gpa,
11401140
zcu.navSrcLoc(nav_index),

src/link/Dwarf.zig

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ debug_str: StringSection,
2323
pub const UpdateError = error{
2424
ReinterpretDeclRef,
2525
Unimplemented,
26-
OutOfMemory,
2726
EndOfStream,
28-
Overflow,
2927
Underflow,
3028
UnexpectedEndOfFile,
3129
} ||
30+
codegen.GenerateSymbolError ||
3231
std.fs.File.OpenError ||
3332
std.fs.File.SetEndPosError ||
3433
std.fs.File.CopyRangeError ||

src/link/Plan9.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,9 @@ fn updateLazySymbolAtom(
10901090
) catch |err| switch (err) {
10911091
error.OutOfMemory => return error.OutOfMemory,
10921092
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)}),
10941096
};
10951097
const code = code_buffer.items;
10961098
// duped_code is freed when the atom is freed

src/register_manager.zig

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,7 @@ const link = @import("link.zig");
1414

1515
const log = std.log.scoped(.register_manager);
1616

17-
pub const AllocationError = error{
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-
};
17+
pub const AllocationError = @import("codegen.zig").CodeGenError || error{OutOfRegisters};
2518

2619
pub fn RegisterManager(
2720
comptime Function: type,

test/behavior/packed-struct.zig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,3 +1335,17 @@ test "assign packed struct initialized with RLS to packed struct literal field"
13351335
try expect(outer.inner.x == x);
13361336
try expect(outer.x == x);
13371337
}
1338+
1339+
test "byte-aligned packed relocation" {
1340+
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1341+
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1342+
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1343+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1344+
1345+
const S = struct {
1346+
var global: u8 align(2) = 0;
1347+
var packed_value: packed struct { x: u8, y: *align(2) u8 } = .{ .x = 111, .y = &global };
1348+
};
1349+
try expect(S.packed_value.x == 111);
1350+
try expect(S.packed_value.y == &S.global);
1351+
}

0 commit comments

Comments
 (0)