| ... | @@ -155,12 +155,14 @@ last_atom_and_free_list_table: std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFre | ... | @@ -155,12 +155,14 @@ last_atom_and_free_list_table: std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFre |
| 155 | /// value assigned to label `foo` is an unnamed constant belonging/associated | 155 | /// value assigned to label `foo` is an unnamed constant belonging/associated |
| 156 | /// with `Decl` `main`, and lives as long as that `Decl`. | 156 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| 157 | unnamed_consts: UnnamedConstTable = .{}, | 157 | unnamed_consts: UnnamedConstTable = .{}, |
| | 158 | anon_decls: AnonDeclTable = .{}, |
| 158 | | 159 | |
| 159 | comdat_groups: std.ArrayListUnmanaged(ComdatGroup) = .{}, | 160 | comdat_groups: std.ArrayListUnmanaged(ComdatGroup) = .{}, |
| 160 | comdat_groups_owners: std.ArrayListUnmanaged(ComdatGroupOwner) = .{}, | 161 | comdat_groups_owners: std.ArrayListUnmanaged(ComdatGroupOwner) = .{}, |
| 161 | comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}, | 162 | comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}, |
| 162 | | 163 | |
| 163 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Symbol.Index)); | 164 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Symbol.Index)); |
| | 165 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Symbol.Index); |
| 164 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata); | 166 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata); |
| 165 | | 167 | |
| 166 | /// When allocating, the ideal_capacity is calculated by | 168 | /// When allocating, the ideal_capacity is calculated by |
| ... | @@ -321,6 +323,7 @@ pub fn deinit(self: *Elf) void { | ... | @@ -321,6 +323,7 @@ pub fn deinit(self: *Elf) void { |
| 321 | } | 323 | } |
| 322 | self.unnamed_consts.deinit(gpa); | 324 | self.unnamed_consts.deinit(gpa); |
| 323 | } | 325 | } |
| | 326 | self.anon_decls.deinit(gpa); |
| 324 | | 327 | |
| 325 | if (self.dwarf) |*dw| { | 328 | if (self.dwarf) |*dw| { |
| 326 | dw.deinit(); | 329 | dw.deinit(); |
| ... | @@ -348,13 +351,8 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. | ... | @@ -348,13 +351,8 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. |
| 348 | return vaddr; | 351 | return vaddr; |
| 349 | } | 352 | } |
| 350 | | 353 | |
| 351 | pub fn getAnonDeclVAddr( | 354 | pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { |
| 352 | self: *Elf, | 355 | // This is basically the same as lowerUnnamedConst. |
| 353 | decl_val: InternPool.Index, | | |
| 354 | reloc_info: link.File.RelocInfo, | | |
| 355 | ) !u64 { | | |
| 356 | // This is basically the same as lowerUnnamedConst except it needs | | |
| 357 | // to return the same thing as `getDeclVAddr` | | |
| 358 | // example: | 356 | // example: |
| 359 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | 357 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 360 | // const val = decl_val.toValue(); | 358 | // const val = decl_val.toValue(); |
| ... | @@ -363,10 +361,44 @@ pub fn getAnonDeclVAddr( | ... | @@ -363,10 +361,44 @@ pub fn getAnonDeclVAddr( |
| 363 | // be used by more than one function, however, its address is being used so we need | 361 | // be used by more than one function, however, its address is being used so we need |
| 364 | // to put it in some location. | 362 | // to put it in some location. |
| 365 | // ... | 363 | // ... |
| 366 | _ = self; | 364 | const gpa = self.base.allocator; |
| 367 | _ = decl_val; | 365 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 368 | _ = reloc_info; | 366 | if (!gop.found_existing) { |
| 369 | _ = @panic("TODO: link/Elf getAnonDeclVAddr"); | 367 | const mod = self.base.options.module.?; |
| | 368 | const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| | 369 | const val = decl_val.toValue(); |
| | 370 | const tv = TypedValue{ .ty = ty, .val = val }; |
| | 371 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| | 372 | defer gpa.free(name); |
| | 373 | const res = self.lowerConst(name, tv, self.rodata_section_index.?, src_loc) catch |err| switch (err) { |
| | 374 | else => { |
| | 375 | // TODO improve error message |
| | 376 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ |
| | 377 | @errorName(err), |
| | 378 | }); |
| | 379 | return .{ .fail = em }; |
| | 380 | }, |
| | 381 | }; |
| | 382 | const sym_index = switch (res) { |
| | 383 | .ok => |sym_index| sym_index, |
| | 384 | .fail => |em| return .{ .fail = em }, |
| | 385 | }; |
| | 386 | gop.value_ptr.* = sym_index; |
| | 387 | } |
| | 388 | return .ok; |
| | 389 | } |
| | 390 | |
| | 391 | pub fn getAnonDeclVAddr(self: *Elf, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
| | 392 | const sym_index = self.anon_decls.get(decl_val).?; |
| | 393 | const sym = self.symbol(sym_index); |
| | 394 | const vaddr = sym.value; |
| | 395 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(self).?; |
| | 396 | try parent_atom.addReloc(self, .{ |
| | 397 | .r_offset = reloc_info.offset, |
| | 398 | .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | elf.R_X86_64_64, |
| | 399 | .r_addend = reloc_info.addend, |
| | 400 | }); |
| | 401 | return vaddr; |
| 370 | } | 402 | } |
| 371 | | 403 | |
| 372 | /// Returns end pos of collision, if any. | 404 | /// Returns end pos of collision, if any. |
| ... | @@ -3126,50 +3158,68 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. | ... | @@ -3126,50 +3158,68 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. |
| 3126 | | 3158 | |
| 3127 | pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { | 3159 | pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 3128 | const gpa = self.base.allocator; | 3160 | const gpa = self.base.allocator; |
| 3129 | | | |
| 3130 | var code_buffer = std.ArrayList(u8).init(gpa); | | |
| 3131 | defer code_buffer.deinit(); | | |
| 3132 | | | |
| 3133 | const mod = self.base.options.module.?; | 3161 | const mod = self.base.options.module.?; |
| 3134 | const gop = try self.unnamed_consts.getOrPut(gpa, decl_index); | 3162 | const gop = try self.unnamed_consts.getOrPut(gpa, decl_index); |
| 3135 | if (!gop.found_existing) { | 3163 | if (!gop.found_existing) { |
| 3136 | gop.value_ptr.* = .{}; | 3164 | gop.value_ptr.* = .{}; |
| 3137 | } | 3165 | } |
| 3138 | const unnamed_consts = gop.value_ptr; | 3166 | const unnamed_consts = gop.value_ptr; |
| 3139 | | | |
| 3140 | const decl = mod.declPtr(decl_index); | 3167 | const decl = mod.declPtr(decl_index); |
| 3141 | const name_str_index = blk: { | 3168 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); |
| 3142 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 3169 | const index = unnamed_consts.items.len; |
| 3143 | const index = unnamed_consts.items.len; | 3170 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 3144 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); | 3171 | defer gpa.free(name); |
| 3145 | defer gpa.free(name); | 3172 | const sym_index = switch (try self.lowerConst(name, typed_value, self.rodata_section_index.?, decl.srcLoc(mod))) { |
| 3146 | break :blk try self.strtab.insert(gpa, name); | 3173 | .ok => |sym_index| sym_index, |
| | 3174 | .fail => |em| { |
| | 3175 | decl.analysis = .codegen_failure; |
| | 3176 | try mod.failed_decls.put(mod.gpa, decl_index, em); |
| | 3177 | log.err("{s}", .{em.msg}); |
| | 3178 | return error.CodegenFail; |
| | 3179 | }, |
| 3147 | }; | 3180 | }; |
| | 3181 | const sym = self.symbol(sym_index); |
| | 3182 | try unnamed_consts.append(gpa, sym.atom_index); |
| | 3183 | return sym_index; |
| | 3184 | } |
| | 3185 | |
| | 3186 | const LowerConstResult = union(enum) { |
| | 3187 | ok: Symbol.Index, |
| | 3188 | fail: *Module.ErrorMsg, |
| | 3189 | }; |
| | 3190 | |
| | 3191 | fn lowerConst( |
| | 3192 | self: *Elf, |
| | 3193 | name: []const u8, |
| | 3194 | tv: TypedValue, |
| | 3195 | output_section_index: u16, |
| | 3196 | src_loc: Module.SrcLoc, |
| | 3197 | ) !LowerConstResult { |
| | 3198 | const gpa = self.base.allocator; |
| | 3199 | |
| | 3200 | var code_buffer = std.ArrayList(u8).init(gpa); |
| | 3201 | defer code_buffer.deinit(); |
| 3148 | | 3202 | |
| | 3203 | const mod = self.base.options.module.?; |
| 3149 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; | 3204 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 3150 | const sym_index = try zig_module.addAtom(self); | 3205 | const sym_index = try zig_module.addAtom(self); |
| 3151 | | 3206 | |
| 3152 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{ | 3207 | const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{ |
| 3153 | .none = {}, | 3208 | .none = {}, |
| 3154 | }, .{ | 3209 | }, .{ |
| 3155 | .parent_atom_index = sym_index, | 3210 | .parent_atom_index = sym_index, |
| 3156 | }); | 3211 | }); |
| 3157 | const code = switch (res) { | 3212 | const code = switch (res) { |
| 3158 | .ok => code_buffer.items, | 3213 | .ok => code_buffer.items, |
| 3159 | .fail => |em| { | 3214 | .fail => |em| return .{ .fail = em }, |
| 3160 | decl.analysis = .codegen_failure; | | |
| 3161 | try mod.failed_decls.put(mod.gpa, decl_index, em); | | |
| 3162 | log.err("{s}", .{em.msg}); | | |
| 3163 | return error.CodegenFail; | | |
| 3164 | }, | | |
| 3165 | }; | 3215 | }; |
| 3166 | | 3216 | |
| 3167 | const required_alignment = typed_value.ty.abiAlignment(mod); | 3217 | const required_alignment = tv.ty.abiAlignment(mod); |
| 3168 | const shdr_index = self.rodata_section_index.?; | 3218 | const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?; |
| 3169 | const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?; | | |
| 3170 | const local_sym = self.symbol(sym_index); | 3219 | const local_sym = self.symbol(sym_index); |
| | 3220 | const name_str_index = try self.strtab.insert(gpa, name); |
| 3171 | local_sym.name_offset = name_str_index; | 3221 | local_sym.name_offset = name_str_index; |
| 3172 | local_sym.output_section_index = self.rodata_section_index.?; | 3222 | local_sym.output_section_index = output_section_index; |
| 3173 | const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; | 3223 | const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; |
| 3174 | local_esym.st_name = name_str_index; | 3224 | local_esym.st_name = name_str_index; |
| 3175 | local_esym.st_info |= elf.STT_OBJECT; | 3225 | local_esym.st_info |= elf.STT_OBJECT; |
| ... | @@ -3179,21 +3229,20 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module | ... | @@ -3179,21 +3229,20 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 3179 | atom_ptr.name_offset = name_str_index; | 3229 | atom_ptr.name_offset = name_str_index; |
| 3180 | atom_ptr.alignment = required_alignment; | 3230 | atom_ptr.alignment = required_alignment; |
| 3181 | atom_ptr.size = code.len; | 3231 | atom_ptr.size = code.len; |
| 3182 | atom_ptr.output_section_index = self.rodata_section_index.?; | 3232 | atom_ptr.output_section_index = output_section_index; |
| 3183 | | 3233 | |
| 3184 | try atom_ptr.allocate(self); | 3234 | try atom_ptr.allocate(self); |
| | 3235 | // TODO rename and re-audit this method |
| 3185 | errdefer self.freeDeclMetadata(sym_index); | 3236 | errdefer self.freeDeclMetadata(sym_index); |
| 3186 | | 3237 | |
| 3187 | local_sym.value = atom_ptr.value; | 3238 | local_sym.value = atom_ptr.value; |
| 3188 | local_esym.st_value = atom_ptr.value; | 3239 | local_esym.st_value = atom_ptr.value; |
| 3189 | | 3240 | |
| 3190 | try unnamed_consts.append(gpa, atom_ptr.atom_index); | | |
| 3191 | | | |
| 3192 | const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr; | 3241 | const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr; |
| 3193 | const file_offset = self.shdrs.items[shdr_index].sh_offset + section_offset; | 3242 | const file_offset = self.shdrs.items[output_section_index].sh_offset + section_offset; |
| 3194 | try self.base.file.?.pwriteAll(code, file_offset); | 3243 | try self.base.file.?.pwriteAll(code, file_offset); |
| 3195 | | 3244 | |
| 3196 | return sym_index; | 3245 | return .{ .ok = sym_index }; |
| 3197 | } | 3246 | } |
| 3198 | | 3247 | |
| 3199 | pub fn updateDeclExports( | 3248 | pub fn updateDeclExports( |