authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-02 08:58:26+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-02 08:58:26+01:00
log7cfc3f0cfa626abe25c8318a7852977cbc1c723b
treec17155900c2dcbfc7a929c2e4f213ae17239f76f
parented2364a1480f99a7380285cec15ff1962d9df519
parent836f007c22e50557dde46c8f766e1150c25271b3
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11026 from ziglang/codegen-field-ptr

codegen: lower field_ptr to memory across linking backends

9 files changed, 151 insertions(+), 70 deletions(-)

src/arch/x86_64/CodeGen.zig+2-1
...@@ -2565,7 +2565,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2565,7 +2565,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
25652565
2566 const payload = try self.addExtra(Mir.ImmPair{2566 const payload = try self.addExtra(Mir.ImmPair{
2567 .dest_off = 0,2567 .dest_off = 0,
2568 .operand = @intCast(u32, imm),2568 // TODO check if this logic is correct
2569 .operand = @truncate(u32, imm),
2569 });2570 });
2570 const flags: u2 = switch (abi_size) {2571 const flags: u2 = switch (abi_size) {
2571 1 => 0b00,2572 1 => 0b00,
src/codegen.zig+98-37
...@@ -142,11 +142,11 @@ pub fn generateFunction(...@@ -142,11 +142,11 @@ pub fn generateFunction(
142142
143pub fn generateSymbol(143pub fn generateSymbol(
144 bin_file: *link.File,144 bin_file: *link.File,
145 parent_atom_index: u32,
146 src_loc: Module.SrcLoc,145 src_loc: Module.SrcLoc,
147 typed_value: TypedValue,146 typed_value: TypedValue,
148 code: *std.ArrayList(u8),147 code: *std.ArrayList(u8),
149 debug_output: DebugInfoOutput,148 debug_output: DebugInfoOutput,
149 reloc_info: RelocInfo,
150) GenerateSymbolError!Result {150) GenerateSymbolError!Result {
151 const tracy = trace(@src());151 const tracy = trace(@src());
152 defer tracy.end();152 defer tracy.end();
...@@ -178,10 +178,10 @@ pub fn generateSymbol(...@@ -178,10 +178,10 @@ pub fn generateSymbol(
178 if (typed_value.ty.sentinel()) |sentinel| {178 if (typed_value.ty.sentinel()) |sentinel| {
179 try code.ensureUnusedCapacity(payload.data.len + 1);179 try code.ensureUnusedCapacity(payload.data.len + 1);
180 code.appendSliceAssumeCapacity(payload.data);180 code.appendSliceAssumeCapacity(payload.data);
181 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{181 switch (try generateSymbol(bin_file, src_loc, .{
182 .ty = typed_value.ty.elemType(),182 .ty = typed_value.ty.elemType(),
183 .val = sentinel,183 .val = sentinel,
184 }, code, debug_output)) {184 }, code, debug_output, reloc_info)) {
185 .appended => return Result{ .appended = {} },185 .appended => return Result{ .appended = {} },
186 .externally_managed => |slice| {186 .externally_managed => |slice| {
187 code.appendSliceAssumeCapacity(slice);187 code.appendSliceAssumeCapacity(slice);
...@@ -198,10 +198,10 @@ pub fn generateSymbol(...@@ -198,10 +198,10 @@ pub fn generateSymbol(
198 const elem_vals = typed_value.val.castTag(.array).?.data;198 const elem_vals = typed_value.val.castTag(.array).?.data;
199 const elem_ty = typed_value.ty.elemType();199 const elem_ty = typed_value.ty.elemType();
200 for (elem_vals) |elem_val| {200 for (elem_vals) |elem_val| {
201 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{201 switch (try generateSymbol(bin_file, src_loc, .{
202 .ty = elem_ty,202 .ty = elem_ty,
203 .val = elem_val,203 .val = elem_val,
204 }, code, debug_output)) {204 }, code, debug_output, reloc_info)) {
205 .appended => {},205 .appended => {},
206 .externally_managed => |slice| {206 .externally_managed => |slice| {
207 code.appendSliceAssumeCapacity(slice);207 code.appendSliceAssumeCapacity(slice);
...@@ -219,10 +219,10 @@ pub fn generateSymbol(...@@ -219,10 +219,10 @@ pub fn generateSymbol(
219219
220 var index: u64 = 0;220 var index: u64 = 0;
221 while (index < len) : (index += 1) {221 while (index < len) : (index += 1) {
222 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{222 switch (try generateSymbol(bin_file, src_loc, .{
223 .ty = elem_ty,223 .ty = elem_ty,
224 .val = array,224 .val = array,
225 }, code, debug_output)) {225 }, code, debug_output, reloc_info)) {
226 .appended => {},226 .appended => {},
227 .externally_managed => |slice| {227 .externally_managed => |slice| {
228 code.appendSliceAssumeCapacity(slice);228 code.appendSliceAssumeCapacity(slice);
...@@ -232,10 +232,10 @@ pub fn generateSymbol(...@@ -232,10 +232,10 @@ pub fn generateSymbol(
232 }232 }
233233
234 if (sentinel) |sentinel_val| {234 if (sentinel) |sentinel_val| {
235 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{235 switch (try generateSymbol(bin_file, src_loc, .{
236 .ty = elem_ty,236 .ty = elem_ty,
237 .val = sentinel_val,237 .val = sentinel_val,
238 }, code, debug_output)) {238 }, code, debug_output, reloc_info)) {
239 .appended => {},239 .appended => {},
240 .externally_managed => |slice| {240 .externally_managed => |slice| {
241 code.appendSliceAssumeCapacity(slice);241 code.appendSliceAssumeCapacity(slice);
...@@ -249,10 +249,10 @@ pub fn generateSymbol(...@@ -249,10 +249,10 @@ pub fn generateSymbol(
249 .empty_array_sentinel => {249 .empty_array_sentinel => {
250 const elem_ty = typed_value.ty.childType();250 const elem_ty = typed_value.ty.childType();
251 const sentinel_val = typed_value.ty.sentinel().?;251 const sentinel_val = typed_value.ty.sentinel().?;
252 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{252 switch (try generateSymbol(bin_file, src_loc, .{
253 .ty = elem_ty,253 .ty = elem_ty,
254 .val = sentinel_val,254 .val = sentinel_val,
255 }, code, debug_output)) {255 }, code, debug_output, reloc_info)) {
256 .appended => {},256 .appended => {},
257 .externally_managed => |slice| {257 .externally_managed => |slice| {
258 code.appendSliceAssumeCapacity(slice);258 code.appendSliceAssumeCapacity(slice);
...@@ -273,11 +273,11 @@ pub fn generateSymbol(...@@ -273,11 +273,11 @@ pub fn generateSymbol(
273 .Pointer => switch (typed_value.val.tag()) {273 .Pointer => switch (typed_value.val.tag()) {
274 .variable => {274 .variable => {
275 const decl = typed_value.val.castTag(.variable).?.data.owner_decl;275 const decl = typed_value.val.castTag(.variable).?.data.owner_decl;
276 return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output);276 return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output, reloc_info);
277 },277 },
278 .decl_ref => {278 .decl_ref => {
279 const decl = typed_value.val.castTag(.decl_ref).?.data;279 const decl = typed_value.val.castTag(.decl_ref).?.data;
280 return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output);280 return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output, reloc_info);
281 },281 },
282 .slice => {282 .slice => {
283 const slice = typed_value.val.castTag(.slice).?.data;283 const slice = typed_value.val.castTag(.slice).?.data;
...@@ -285,10 +285,10 @@ pub fn generateSymbol(...@@ -285,10 +285,10 @@ pub fn generateSymbol(
285 // generate ptr285 // generate ptr
286 var buf: Type.SlicePtrFieldTypeBuffer = undefined;286 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
287 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);287 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
288 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{288 switch (try generateSymbol(bin_file, src_loc, .{
289 .ty = slice_ptr_field_type,289 .ty = slice_ptr_field_type,
290 .val = slice.ptr,290 .val = slice.ptr,
291 }, code, debug_output)) {291 }, code, debug_output, reloc_info)) {
292 .appended => {},292 .appended => {},
293 .externally_managed => |external_slice| {293 .externally_managed => |external_slice| {
294 code.appendSliceAssumeCapacity(external_slice);294 code.appendSliceAssumeCapacity(external_slice);
...@@ -297,10 +297,10 @@ pub fn generateSymbol(...@@ -297,10 +297,10 @@ pub fn generateSymbol(
297 }297 }
298298
299 // generate length299 // generate length
300 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{300 switch (try generateSymbol(bin_file, src_loc, .{
301 .ty = Type.initTag(.usize),301 .ty = Type.initTag(.usize),
302 .val = slice.len,302 .val = slice.len,
303 }, code, debug_output)) {303 }, code, debug_output, reloc_info)) {
304 .appended => {},304 .appended => {},
305 .externally_managed => |external_slice| {305 .externally_managed => |external_slice| {
306 code.appendSliceAssumeCapacity(external_slice);306 code.appendSliceAssumeCapacity(external_slice);
...@@ -310,6 +310,58 @@ pub fn generateSymbol(...@@ -310,6 +310,58 @@ pub fn generateSymbol(
310310
311 return Result{ .appended = {} };311 return Result{ .appended = {} };
312 },312 },
313 .field_ptr => {
314 const target = bin_file.options.target;
315 const field_ptr = typed_value.val.castTag(.field_ptr).?.data;
316 const container_ptr = field_ptr.container_ptr;
317
318 switch (container_ptr.tag()) {
319 .decl_ref => {
320 const decl = container_ptr.castTag(.decl_ref).?.data;
321 const addend = blk: {
322 switch (decl.ty.tag()) {
323 .@"struct" => {
324 const addend = decl.ty.structFieldOffset(field_ptr.field_index, target);
325 break :blk @intCast(u32, addend);
326 },
327 else => return Result{
328 .fail = try ErrorMsg.create(
329 bin_file.allocator,
330 src_loc,
331 "TODO implement generateSymbol for pointer type value: '{s}'",
332 .{@tagName(typed_value.val.tag())},
333 ),
334 },
335 }
336 };
337 return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output, .{
338 .parent_atom_index = reloc_info.parent_atom_index,
339 .addend = (reloc_info.addend orelse 0) + addend,
340 });
341 },
342 .field_ptr => {
343 switch (try generateSymbol(bin_file, src_loc, .{
344 .ty = typed_value.ty,
345 .val = container_ptr,
346 }, code, debug_output, reloc_info)) {
347 .appended => {},
348 .externally_managed => |external_slice| {
349 code.appendSliceAssumeCapacity(external_slice);
350 },
351 .fail => |em| return Result{ .fail = em },
352 }
353 return Result{ .appended = {} };
354 },
355 else => return Result{
356 .fail = try ErrorMsg.create(
357 bin_file.allocator,
358 src_loc,
359 "TODO implement generateSymbol for pointer type value: '{s}'",
360 .{@tagName(typed_value.val.tag())},
361 ),
362 },
363 }
364 },
313 else => return Result{365 else => return Result{
314 .fail = try ErrorMsg.create(366 .fail = try ErrorMsg.create(
315 bin_file.allocator,367 bin_file.allocator,
...@@ -441,10 +493,10 @@ pub fn generateSymbol(...@@ -441,10 +493,10 @@ pub fn generateSymbol(
441 const field_ty = typed_value.ty.structFieldType(index);493 const field_ty = typed_value.ty.structFieldType(index);
442 if (!field_ty.hasRuntimeBits()) continue;494 if (!field_ty.hasRuntimeBits()) continue;
443495
444 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{496 switch (try generateSymbol(bin_file, src_loc, .{
445 .ty = field_ty,497 .ty = field_ty,
446 .val = field_val,498 .val = field_val,
447 }, code, debug_output)) {499 }, code, debug_output, reloc_info)) {
448 .appended => {},500 .appended => {},
449 .externally_managed => |external_slice| {501 .externally_managed => |external_slice| {
450 code.appendSliceAssumeCapacity(external_slice);502 code.appendSliceAssumeCapacity(external_slice);
...@@ -472,10 +524,10 @@ pub fn generateSymbol(...@@ -472,10 +524,10 @@ pub fn generateSymbol(
472 const layout = typed_value.ty.unionGetLayout(target);524 const layout = typed_value.ty.unionGetLayout(target);
473525
474 if (layout.payload_size == 0) {526 if (layout.payload_size == 0) {
475 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{527 switch (try generateSymbol(bin_file, src_loc, .{
476 .ty = typed_value.ty.unionTagType().?,528 .ty = typed_value.ty.unionTagType().?,
477 .val = union_obj.tag,529 .val = union_obj.tag,
478 }, code, debug_output)) {530 }, code, debug_output, reloc_info)) {
479 .appended => {},531 .appended => {},
480 .externally_managed => |external_slice| {532 .externally_managed => |external_slice| {
481 code.appendSliceAssumeCapacity(external_slice);533 code.appendSliceAssumeCapacity(external_slice);
...@@ -486,10 +538,10 @@ pub fn generateSymbol(...@@ -486,10 +538,10 @@ pub fn generateSymbol(
486538
487 // Check if we should store the tag first.539 // Check if we should store the tag first.
488 if (layout.tag_align >= layout.payload_align) {540 if (layout.tag_align >= layout.payload_align) {
489 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{541 switch (try generateSymbol(bin_file, src_loc, .{
490 .ty = typed_value.ty.unionTagType().?,542 .ty = typed_value.ty.unionTagType().?,
491 .val = union_obj.tag,543 .val = union_obj.tag,
492 }, code, debug_output)) {544 }, code, debug_output, reloc_info)) {
493 .appended => {},545 .appended => {},
494 .externally_managed => |external_slice| {546 .externally_managed => |external_slice| {
495 code.appendSliceAssumeCapacity(external_slice);547 code.appendSliceAssumeCapacity(external_slice);
...@@ -505,10 +557,10 @@ pub fn generateSymbol(...@@ -505,10 +557,10 @@ pub fn generateSymbol(
505 if (!field_ty.hasRuntimeBits()) {557 if (!field_ty.hasRuntimeBits()) {
506 try code.writer().writeByteNTimes(0xaa, try math.cast(usize, layout.payload_size));558 try code.writer().writeByteNTimes(0xaa, try math.cast(usize, layout.payload_size));
507 } else {559 } else {
508 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{560 switch (try generateSymbol(bin_file, src_loc, .{
509 .ty = field_ty,561 .ty = field_ty,
510 .val = union_obj.val,562 .val = union_obj.val,
511 }, code, debug_output)) {563 }, code, debug_output, reloc_info)) {
512 .appended => {},564 .appended => {},
513 .externally_managed => |external_slice| {565 .externally_managed => |external_slice| {
514 code.appendSliceAssumeCapacity(external_slice);566 code.appendSliceAssumeCapacity(external_slice);
...@@ -523,10 +575,10 @@ pub fn generateSymbol(...@@ -523,10 +575,10 @@ pub fn generateSymbol(
523 }575 }
524576
525 if (layout.tag_size > 0) {577 if (layout.tag_size > 0) {
526 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{578 switch (try generateSymbol(bin_file, src_loc, .{
527 .ty = union_ty.tag_ty,579 .ty = union_ty.tag_ty,
528 .val = union_obj.tag,580 .val = union_obj.tag,
529 }, code, debug_output)) {581 }, code, debug_output, reloc_info)) {
530 .appended => {},582 .appended => {},
531 .externally_managed => |external_slice| {583 .externally_managed => |external_slice| {
532 code.appendSliceAssumeCapacity(external_slice);584 code.appendSliceAssumeCapacity(external_slice);
...@@ -555,10 +607,10 @@ pub fn generateSymbol(...@@ -555,10 +607,10 @@ pub fn generateSymbol(
555607
556 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);608 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
557 const begin = code.items.len;609 const begin = code.items.len;
558 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{610 switch (try generateSymbol(bin_file, src_loc, .{
559 .ty = error_ty,611 .ty = error_ty,
560 .val = error_val,612 .val = error_val,
561 }, code, debug_output)) {613 }, code, debug_output, reloc_info)) {
562 .appended => {},614 .appended => {},
563 .externally_managed => |external_slice| {615 .externally_managed => |external_slice| {
564 code.appendSliceAssumeCapacity(external_slice);616 code.appendSliceAssumeCapacity(external_slice);
...@@ -568,10 +620,10 @@ pub fn generateSymbol(...@@ -568,10 +620,10 @@ pub fn generateSymbol(
568620
569 if (payload_ty.hasRuntimeBits()) {621 if (payload_ty.hasRuntimeBits()) {
570 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);622 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
571 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{623 switch (try generateSymbol(bin_file, src_loc, .{
572 .ty = payload_ty,624 .ty = payload_ty,
573 .val = payload_val,625 .val = payload_val,
574 }, code, debug_output)) {626 }, code, debug_output, reloc_info)) {
575 .appended => {},627 .appended => {},
576 .externally_managed => |external_slice| {628 .externally_managed => |external_slice| {
577 code.appendSliceAssumeCapacity(external_slice);629 code.appendSliceAssumeCapacity(external_slice);
...@@ -618,23 +670,28 @@ pub fn generateSymbol(...@@ -618,23 +670,28 @@ pub fn generateSymbol(
618 }670 }
619}671}
620672
673const RelocInfo = struct {
674 parent_atom_index: u32,
675 addend: ?u32 = null,
676};
677
621fn lowerDeclRef(678fn lowerDeclRef(
622 bin_file: *link.File,679 bin_file: *link.File,
623 parent_atom_index: u32,
624 src_loc: Module.SrcLoc,680 src_loc: Module.SrcLoc,
625 typed_value: TypedValue,681 typed_value: TypedValue,
626 decl: *Module.Decl,682 decl: *Module.Decl,
627 code: *std.ArrayList(u8),683 code: *std.ArrayList(u8),
628 debug_output: DebugInfoOutput,684 debug_output: DebugInfoOutput,
685 reloc_info: RelocInfo,
629) GenerateSymbolError!Result {686) GenerateSymbolError!Result {
630 if (typed_value.ty.isSlice()) {687 if (typed_value.ty.isSlice()) {
631 // generate ptr688 // generate ptr
632 var buf: Type.SlicePtrFieldTypeBuffer = undefined;689 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
633 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);690 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
634 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{691 switch (try generateSymbol(bin_file, src_loc, .{
635 .ty = slice_ptr_field_type,692 .ty = slice_ptr_field_type,
636 .val = typed_value.val,693 .val = typed_value.val,
637 }, code, debug_output)) {694 }, code, debug_output, reloc_info)) {
638 .appended => {},695 .appended => {},
639 .externally_managed => |external_slice| {696 .externally_managed => |external_slice| {
640 code.appendSliceAssumeCapacity(external_slice);697 code.appendSliceAssumeCapacity(external_slice);
...@@ -647,10 +704,10 @@ fn lowerDeclRef(...@@ -647,10 +704,10 @@ fn lowerDeclRef(
647 .base = .{ .tag = .int_u64 },704 .base = .{ .tag = .int_u64 },
648 .data = typed_value.val.sliceLen(),705 .data = typed_value.val.sliceLen(),
649 };706 };
650 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{707 switch (try generateSymbol(bin_file, src_loc, .{
651 .ty = Type.usize,708 .ty = Type.usize,
652 .val = Value.initPayload(&slice_len.base),709 .val = Value.initPayload(&slice_len.base),
653 }, code, debug_output)) {710 }, code, debug_output, reloc_info)) {
654 .appended => {},711 .appended => {},
655 .externally_managed => |external_slice| {712 .externally_managed => |external_slice| {
656 code.appendSliceAssumeCapacity(external_slice);713 code.appendSliceAssumeCapacity(external_slice);
...@@ -670,7 +727,11 @@ fn lowerDeclRef(...@@ -670,7 +727,11 @@ fn lowerDeclRef(
670 }727 }
671728
672 decl.markAlive();729 decl.markAlive();
673 const vaddr = try bin_file.getDeclVAddr(decl, parent_atom_index, code.items.len);730 const vaddr = try bin_file.getDeclVAddr(decl, .{
731 .parent_atom_index = reloc_info.parent_atom_index,
732 .offset = code.items.len,
733 .addend = reloc_info.addend orelse 0,
734 });
674 const endian = target.cpu.arch.endian();735 const endian = target.cpu.arch.endian();
675 switch (ptr_width) {736 switch (ptr_width) {
676 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian),737 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian),
src/link.zig+11-5
...@@ -685,16 +685,22 @@ pub const File = struct {...@@ -685,16 +685,22 @@ pub const File = struct {
685 }685 }
686 }686 }
687687
688 pub const RelocInfo = struct {
689 parent_atom_index: u32,
690 offset: u64,
691 addend: u32,
692 };
693
688 /// Get allocated `Decl`'s address in virtual memory.694 /// Get allocated `Decl`'s address in virtual memory.
689 /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's695 /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's
690 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the696 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the
691 /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.697 /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
692 pub fn getDeclVAddr(base: *File, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {698 pub fn getDeclVAddr(base: *File, decl: *const Module.Decl, reloc_info: RelocInfo) !u64 {
693 switch (base.tag) {699 switch (base.tag) {
694 .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl, parent_atom_index, offset),700 .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl, reloc_info),
695 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl, parent_atom_index, offset),701 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl, reloc_info),
696 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, parent_atom_index, offset),702 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info),
697 .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, parent_atom_index, offset),703 .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info),
698 .c => unreachable,704 .c => unreachable,
699 .wasm => unreachable,705 .wasm => unreachable,
700 .spirv => unreachable,706 .spirv => unreachable,
src/link/Coff.zig+6-5
...@@ -724,10 +724,12 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -724,10 +724,12 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
724 var code_buffer = std.ArrayList(u8).init(self.base.allocator);724 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
725 defer code_buffer.deinit();725 defer code_buffer.deinit();
726726
727 const res = try codegen.generateSymbol(&self.base, 0, decl.srcLoc(), .{727 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
728 .ty = decl.ty,728 .ty = decl.ty,
729 .val = decl.val,729 .val = decl.val,
730 }, &code_buffer, .none);730 }, &code_buffer, .none, .{
731 .parent_atom_index = 0,
732 });
731 const code = switch (res) {733 const code = switch (res) {
732 .externally_managed => |x| x,734 .externally_managed => |x| x,
733 .appended => code_buffer.items,735 .appended => code_buffer.items,
...@@ -1463,9 +1465,8 @@ fn findLib(self: *Coff, arena: Allocator, name: []const u8) !?[]const u8 {...@@ -1463,9 +1465,8 @@ fn findLib(self: *Coff, arena: Allocator, name: []const u8) !?[]const u8 {
1463 return null;1465 return null;
1464}1466}
14651467
1466pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {1468pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, reloc_info: link.File.RelocInfo) !u64 {
1467 _ = parent_atom_index;1469 _ = reloc_info;
1468 _ = offset;
1469 assert(self.llvm_object == null);1470 assert(self.llvm_object == null);
1470 return self.text_section_virtual_address + decl.link.coff.text_offset;1471 return self.text_section_virtual_address + decl.link.coff.text_offset;
1471}1472}
src/link/Elf.zig+12-6
...@@ -188,6 +188,7 @@ relocs: RelocTable = .{},...@@ -188,6 +188,7 @@ relocs: RelocTable = .{},
188const Reloc = struct {188const Reloc = struct {
189 target: u32,189 target: u32,
190 offset: u64,190 offset: u64,
191 addend: u32,
191 prev_vaddr: u64,192 prev_vaddr: u64,
192};193};
193194
...@@ -421,20 +422,21 @@ pub fn deinit(self: *Elf) void {...@@ -421,20 +422,21 @@ pub fn deinit(self: *Elf) void {
421 self.atom_by_index_table.deinit(self.base.allocator);422 self.atom_by_index_table.deinit(self.base.allocator);
422}423}
423424
424pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {425pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, reloc_info: File.RelocInfo) !u64 {
425 assert(self.llvm_object == null);426 assert(self.llvm_object == null);
426 assert(decl.link.elf.local_sym_index != 0);427 assert(decl.link.elf.local_sym_index != 0);
427428
428 const target = decl.link.elf.local_sym_index;429 const target = decl.link.elf.local_sym_index;
429 const vaddr = self.local_symbols.items[target].st_value;430 const vaddr = self.local_symbols.items[target].st_value;
430 const atom = self.atom_by_index_table.get(parent_atom_index).?;431 const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?;
431 const gop = try self.relocs.getOrPut(self.base.allocator, atom);432 const gop = try self.relocs.getOrPut(self.base.allocator, atom);
432 if (!gop.found_existing) {433 if (!gop.found_existing) {
433 gop.value_ptr.* = .{};434 gop.value_ptr.* = .{};
434 }435 }
435 try gop.value_ptr.append(self.base.allocator, .{436 try gop.value_ptr.append(self.base.allocator, .{
436 .target = target,437 .target = target,
437 .offset = offset,438 .offset = reloc_info.offset,
439 .addend = reloc_info.addend,
438 .prev_vaddr = vaddr,440 .prev_vaddr = vaddr,
439 });441 });
440442
...@@ -1039,7 +1041,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1039,7 +1041,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
10391041
1040 for (relocs.items) |*reloc| {1042 for (relocs.items) |*reloc| {
1041 const target_sym = self.local_symbols.items[reloc.target];1043 const target_sym = self.local_symbols.items[reloc.target];
1042 const target_vaddr = target_sym.st_value;1044 const target_vaddr = target_sym.st_value + reloc.addend;
10431045
1044 if (target_vaddr == reloc.prev_vaddr) continue;1046 if (target_vaddr == reloc.prev_vaddr) continue;
10451047
...@@ -3074,7 +3076,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -3074,7 +3076,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
30743076
3075 // TODO implement .debug_info for global variables3077 // TODO implement .debug_info for global variables
3076 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;3078 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
3077 const res = try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{3079 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
3078 .ty = decl.ty,3080 .ty = decl.ty,
3079 .val = decl_val,3081 .val = decl_val,
3080 }, &code_buffer, .{3082 }, &code_buffer, .{
...@@ -3083,6 +3085,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -3083,6 +3085,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
3083 .dbg_info = &dbg_info_buffer,3085 .dbg_info = &dbg_info_buffer,
3084 .dbg_info_type_relocs = &dbg_info_type_relocs,3086 .dbg_info_type_relocs = &dbg_info_type_relocs,
3085 },3087 },
3088 }, .{
3089 .parent_atom_index = decl.link.elf.local_sym_index,
3086 });3090 });
3087 const code = switch (res) {3091 const code = switch (res) {
3088 .externally_managed => |x| x,3092 .externally_managed => |x| x,
...@@ -3130,8 +3134,10 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl...@@ -3130,8 +3134,10 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl
3130 atom.local_sym_index = try self.allocateLocalSymbol();3134 atom.local_sym_index = try self.allocateLocalSymbol();
3131 try self.atom_by_index_table.putNoClobber(self.base.allocator, atom.local_sym_index, atom);3135 try self.atom_by_index_table.putNoClobber(self.base.allocator, atom.local_sym_index, atom);
31323136
3133 const res = try codegen.generateSymbol(&self.base, atom.local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{3137 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
3134 .none = .{},3138 .none = .{},
3139 }, .{
3140 .parent_atom_index = atom.local_sym_index,
3135 });3141 });
3136 const code = switch (res) {3142 const code = switch (res) {
3137 .externally_managed => |x| x,3143 .externally_managed => |x| x,
src/link/MachO.zig+16-9
...@@ -3781,8 +3781,10 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De...@@ -3781,8 +3781,10 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
3781 const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment));3781 const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment));
3782 try self.atom_by_index_table.putNoClobber(self.base.allocator, local_sym_index, atom);3782 try self.atom_by_index_table.putNoClobber(self.base.allocator, local_sym_index, atom);
37833783
3784 const res = try codegen.generateSymbol(&self.base, local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{3784 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
3785 .none = .{},3785 .none = .{},
3786 }, .{
3787 .parent_atom_index = local_sym_index,
3786 });3788 });
3787 const code = switch (res) {3789 const code = switch (res) {
3788 .externally_managed => |x| x,3790 .externally_managed => |x| x,
...@@ -3790,6 +3792,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De...@@ -3790,6 +3792,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
3790 .fail => |em| {3792 .fail => |em| {
3791 decl.analysis = .codegen_failure;3793 decl.analysis = .codegen_failure;
3792 try module.failed_decls.put(module.gpa, decl, em);3794 try module.failed_decls.put(module.gpa, decl, em);
3795 log.err("{s}", .{em.msg});
3793 return error.AnalysisFail;3796 return error.AnalysisFail;
3794 },3797 },
3795 };3798 };
...@@ -3860,7 +3863,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -3860,7 +3863,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
38603863
3861 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;3864 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
3862 const res = if (debug_buffers) |dbg|3865 const res = if (debug_buffers) |dbg|
3863 try codegen.generateSymbol(&self.base, decl.link.macho.local_sym_index, decl.srcLoc(), .{3866 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
3864 .ty = decl.ty,3867 .ty = decl.ty,
3865 .val = decl_val,3868 .val = decl_val,
3866 }, &code_buffer, .{3869 }, &code_buffer, .{
...@@ -3869,12 +3872,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -3869,12 +3872,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
3869 .dbg_info = &dbg.dbg_info_buffer,3872 .dbg_info = &dbg.dbg_info_buffer,
3870 .dbg_info_type_relocs = &dbg.dbg_info_type_relocs,3873 .dbg_info_type_relocs = &dbg.dbg_info_type_relocs,
3871 },3874 },
3875 }, .{
3876 .parent_atom_index = decl.link.macho.local_sym_index,
3872 })3877 })
3873 else3878 else
3874 try codegen.generateSymbol(&self.base, decl.link.macho.local_sym_index, decl.srcLoc(), .{3879 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
3875 .ty = decl.ty,3880 .ty = decl.ty,
3876 .val = decl_val,3881 .val = decl_val,
3877 }, &code_buffer, .none);3882 }, &code_buffer, .none, .{
3883 .parent_atom_index = decl.link.macho.local_sym_index,
3884 });
38783885
3879 const code = blk: {3886 const code = blk: {
3880 switch (res) {3887 switch (res) {
...@@ -4357,15 +4364,15 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {...@@ -4357,15 +4364,15 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
4357 }4364 }
4358}4365}
43594366
4360pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {4367pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, reloc_info: File.RelocInfo) !u64 {
4361 assert(self.llvm_object == null);4368 assert(self.llvm_object == null);
4362 assert(decl.link.macho.local_sym_index != 0);4369 assert(decl.link.macho.local_sym_index != 0);
43634370
4364 const atom = self.atom_by_index_table.get(parent_atom_index).?;4371 const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?;
4365 try atom.relocs.append(self.base.allocator, .{4372 try atom.relocs.append(self.base.allocator, .{
4366 .offset = @intCast(u32, offset),4373 .offset = @intCast(u32, reloc_info.offset),
4367 .target = .{ .local = decl.link.macho.local_sym_index },4374 .target = .{ .local = decl.link.macho.local_sym_index },
4368 .addend = 0,4375 .addend = reloc_info.addend,
4369 .subtractor = null,4376 .subtractor = null,
4370 .pcrel = false,4377 .pcrel = false,
4371 .length = 3,4378 .length = 3,
...@@ -4375,7 +4382,7 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u...@@ -4375,7 +4382,7 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u
4375 else => unreachable,4382 else => unreachable,
4376 },4383 },
4377 });4384 });
4378 try atom.rebases.append(self.base.allocator, offset);4385 try atom.rebases.append(self.base.allocator, reloc_info.offset);
43794386
4380 return 0;4387 return 0;
4381}4388}
src/link/Plan9.zig+6-5
...@@ -304,10 +304,12 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void {...@@ -304,10 +304,12 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void {
304 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;304 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
305 // TODO we need the symbol index for symbol in the table of locals for the containing atom305 // TODO we need the symbol index for symbol in the table of locals for the containing atom
306 const sym_index = decl.link.plan9.sym_index orelse 0;306 const sym_index = decl.link.plan9.sym_index orelse 0;
307 const res = try codegen.generateSymbol(&self.base, @intCast(u32, sym_index), decl.srcLoc(), .{307 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
308 .ty = decl.ty,308 .ty = decl.ty,
309 .val = decl_val,309 .val = decl_val,
310 }, &code_buffer, .{ .none = .{} });310 }, &code_buffer, .{ .none = .{} }, .{
311 .parent_atom_index = @intCast(u32, sym_index),
312 });
311 const code = switch (res) {313 const code = switch (res) {
312 .externally_managed => |x| x,314 .externally_managed => |x| x,
313 .appended => code_buffer.items,315 .appended => code_buffer.items,
...@@ -752,9 +754,8 @@ pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void {...@@ -752,9 +754,8 @@ pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void {
752 _ = self;754 _ = self;
753 _ = decl;755 _ = decl;
754}756}
755pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {757pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, reloc_info: link.File.RelocInfo) !u64 {
756 _ = parent_atom_index;758 _ = reloc_info;
757 _ = offset;
758 if (decl.ty.zigTypeTag() == .Fn) {759 if (decl.ty.zigTypeTag() == .Fn) {
759 var start = self.bases.text;760 var start = self.bases.text;
760 var it_file = self.fn_decl_table.iterator();761 var it_file = self.fn_decl_table.iterator();
test/behavior/bugs/3046.zig-1
...@@ -13,7 +13,6 @@ fn couldFail() anyerror!i32 {...@@ -13,7 +13,6 @@ fn couldFail() anyerror!i32 {
13var some_struct: SomeStruct = undefined;13var some_struct: SomeStruct = undefined;
1414
15test "fixed" {15test "fixed" {
16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
test/behavior/struct.zig-1
...@@ -780,7 +780,6 @@ test "packed struct with u0 field access" {...@@ -780,7 +780,6 @@ test "packed struct with u0 field access" {
780780
781test "access to global struct fields" {781test "access to global struct fields" {
782 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO782 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
783 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
784 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO783 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO784 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
786 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO785 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO