From b9b1ab024063105a9adfe3828692867c91015dc6 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 10 Feb 2022 14:41:07 +0100 Subject: elf: store pointer relocations indexed by containing atom In `getDeclVAddr`, it may happen that the target `Decl` has not been allocated space in virtual memory. In this case, we store a relocation in the linker-global table which we will iterate over when flushing the module, and fill in any missing address in the final binary. Note that for optimisation, if the address was resolved at the time of a call to `getDeclVAddr`, we skip relocating this atom. This commit also adds the glue code for lowering const slices in the ARM backend. --- src/codegen.zig | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 389f38a020..fd4321fee9 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -142,6 +142,7 @@ pub fn generateFunction( pub fn generateSymbol( bin_file: *link.File, + parent_atom_index: u32, src_loc: Module.SrcLoc, typed_value: TypedValue, code: *std.ArrayList(u8), @@ -177,7 +178,7 @@ pub fn generateSymbol( if (typed_value.ty.sentinel()) |sentinel| { try code.ensureUnusedCapacity(payload.data.len + 1); code.appendSliceAssumeCapacity(payload.data); - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = typed_value.ty.elemType(), .val = sentinel, }, code, debug_output)) { @@ -197,7 +198,7 @@ pub fn generateSymbol( const elem_vals = typed_value.val.castTag(.array).?.data; const elem_ty = typed_value.ty.elemType(); for (elem_vals) |elem_val| { - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = elem_ty, .val = elem_val, }, code, debug_output)) { @@ -223,11 +224,11 @@ pub fn generateSymbol( .Pointer => switch (typed_value.val.tag()) { .variable => { const decl = typed_value.val.castTag(.variable).?.data.owner_decl; - return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output); + return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output); }, .decl_ref => { const decl = typed_value.val.castTag(.decl_ref).?.data; - return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output); + return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output); }, .slice => { const slice = typed_value.val.castTag(.slice).?.data; @@ -235,7 +236,7 @@ pub fn generateSymbol( // generate ptr var buf: Type.SlicePtrFieldTypeBuffer = undefined; const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf); - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = slice_ptr_field_type, .val = slice.ptr, }, code, debug_output)) { @@ -247,7 +248,7 @@ pub fn generateSymbol( } // generate length - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = Type.initTag(.usize), .val = slice.len, }, code, debug_output)) { @@ -391,7 +392,7 @@ pub fn generateSymbol( const field_ty = typed_value.ty.structFieldType(index); if (!field_ty.hasRuntimeBits()) continue; - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = field_ty, .val = field_val, }, code, debug_output)) { @@ -446,6 +447,7 @@ pub fn generateSymbol( fn lowerDeclRef( bin_file: *link.File, + parent_atom_index: u32, src_loc: Module.SrcLoc, typed_value: TypedValue, decl: *Module.Decl, @@ -456,7 +458,7 @@ fn lowerDeclRef( // generate ptr var buf: Type.SlicePtrFieldTypeBuffer = undefined; const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf); - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = slice_ptr_field_type, .val = typed_value.val, }, code, debug_output)) { @@ -472,7 +474,7 @@ fn lowerDeclRef( .base = .{ .tag = .int_u64 }, .data = typed_value.val.sliceLen(), }; - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = Type.initTag(.usize), .val = Value.initPayload(&slice_len.base), }, code, debug_output)) { @@ -495,15 +497,7 @@ fn lowerDeclRef( } decl.markAlive(); - const vaddr = vaddr: { - if (bin_file.cast(link.File.MachO)) |macho_file| { - break :vaddr try macho_file.getDeclVAddrWithReloc(decl, code.items.len); - } - // TODO handle the dependency of this symbol on the decl's vaddr. - // If the decl changes vaddr, then this symbol needs to get regenerated. - break :vaddr bin_file.getDeclVAddr(decl); - }; - + const vaddr = try bin_file.getDeclVAddr(decl, parent_atom_index, code.items.len); const endian = target.cpu.arch.endian(); switch (ptr_width) { 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian), -- cgit v1.2.3