| author | |
| committer | |
| log | 77accf597d845245847b143e42ec4109c9468480 |
| tree | 176ace677fe750bde50b689176644829f0a63588 |
| parent | da25ed95fce32449f70942ea77aa5e00e75dbbdd |
9 files changed, 147 insertions(+), 55 deletions(-)
src/Compilation.zig+4| ... | @@ -3208,6 +3208,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3208,6 +3208,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3208 | if (!zcu.navFileScope(nav).okToReportErrors()) continue; | 3208 | if (!zcu.navFileScope(nav).okToReportErrors()) continue; |
| 3209 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); | 3209 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3210 | } | 3210 | } |
| 3211 | for (zcu.failed_types.keys(), zcu.failed_types.values()) |ty_index, error_msg| { | ||
| 3212 | if (!zcu.typeFileScope(ty_index).okToReportErrors()) continue; | ||
| 3213 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); | ||
| 3214 | } | ||
| 3211 | for (zcu.failed_exports.values()) |value| { | 3215 | for (zcu.failed_exports.values()) |value| { |
| 3212 | try addModuleErrorMsg(zcu, &bundle, value.*); | 3216 | try addModuleErrorMsg(zcu, &bundle, value.*); |
| 3213 | } | 3217 | } |
src/Zcu.zig+30-6| ... | @@ -127,6 +127,7 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp | ... | @@ -127,6 +127,7 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp |
| 127 | /// This may be a simple "value" `Nav`, or it may be a function. | 127 | /// This may be a simple "value" `Nav`, or it may be a function. |
| 128 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. | 128 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. |
| 129 | failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty, | 129 | failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty, |
| 130 | failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty, | ||
| 130 | /// Keep track of one `@compileLog` callsite per `AnalUnit`. | 131 | /// Keep track of one `@compileLog` callsite per `AnalUnit`. |
| 131 | /// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`. | 132 | /// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`. |
| 132 | compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct { | 133 | compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct { |
| ... | @@ -2448,16 +2449,14 @@ pub fn deinit(zcu: *Zcu) void { | ... | @@ -2448,16 +2449,14 @@ pub fn deinit(zcu: *Zcu) void { |
| 2448 | zcu.local_zir_cache.handle.close(); | 2449 | zcu.local_zir_cache.handle.close(); |
| 2449 | zcu.global_zir_cache.handle.close(); | 2450 | zcu.global_zir_cache.handle.close(); |
| 2450 | 2451 | ||
| 2451 | for (zcu.failed_analysis.values()) |value| { | 2452 | for (zcu.failed_analysis.values()) |value| value.destroy(gpa); |
| 2452 | value.destroy(gpa); | 2453 | for (zcu.failed_codegen.values()) |value| value.destroy(gpa); |
| 2453 | } | 2454 | for (zcu.failed_types.values()) |value| value.destroy(gpa); |
| 2454 | for (zcu.failed_codegen.values()) |value| { | ||
| 2455 | value.destroy(gpa); | ||
| 2456 | } | ||
| 2457 | zcu.analysis_in_progress.deinit(gpa); | 2455 | zcu.analysis_in_progress.deinit(gpa); |
| 2458 | zcu.failed_analysis.deinit(gpa); | 2456 | zcu.failed_analysis.deinit(gpa); |
| 2459 | zcu.transitive_failed_analysis.deinit(gpa); | 2457 | zcu.transitive_failed_analysis.deinit(gpa); |
| 2460 | zcu.failed_codegen.deinit(gpa); | 2458 | zcu.failed_codegen.deinit(gpa); |
| 2459 | zcu.failed_types.deinit(gpa); | ||
| 2461 | 2460 | ||
| 2462 | for (zcu.failed_files.values()) |value| { | 2461 | for (zcu.failed_files.values()) |value| { |
| 2463 | if (value) |msg| msg.destroy(gpa); | 2462 | if (value) |msg| msg.destroy(gpa); |
| ... | @@ -3800,6 +3799,18 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc { | ... | @@ -3800,6 +3799,18 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc { |
| 3800 | }; | 3799 | }; |
| 3801 | } | 3800 | } |
| 3802 | 3801 | ||
| 3802 | pub fn typeSrcLoc(zcu: *const Zcu, ty_index: InternPool.Index) LazySrcLoc { | ||
| 3803 | _ = zcu; | ||
| 3804 | _ = ty_index; | ||
| 3805 | @panic("TODO"); | ||
| 3806 | } | ||
| 3807 | |||
| 3808 | pub fn typeFileScope(zcu: *Zcu, ty_index: InternPool.Index) *File { | ||
| 3809 | _ = zcu; | ||
| 3810 | _ = ty_index; | ||
| 3811 | @panic("TODO"); | ||
| 3812 | } | ||
| 3813 | |||
| 3803 | pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 { | 3814 | pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 { |
| 3804 | const ip = &zcu.intern_pool; | 3815 | const ip = &zcu.intern_pool; |
| 3805 | const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?; | 3816 | const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?; |
| ... | @@ -4060,3 +4071,16 @@ pub fn navValIsConst(zcu: *const Zcu, val: InternPool.Index) bool { | ... | @@ -4060,3 +4071,16 @@ pub fn navValIsConst(zcu: *const Zcu, val: InternPool.Index) bool { |
| 4060 | else => true, | 4071 | else => true, |
| 4061 | }; | 4072 | }; |
| 4062 | } | 4073 | } |
| 4074 | |||
| 4075 | pub fn codegenFail( | ||
| 4076 | zcu: *Zcu, | ||
| 4077 | nav_index: InternPool.Nav.Index, | ||
| 4078 | comptime format: []const u8, | ||
| 4079 | args: anytype, | ||
| 4080 | ) error{ CodegenFail, OutOfMemory } { | ||
| 4081 | const gpa = zcu.gpa; | ||
| 4082 | try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1); | ||
| 4083 | const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args); | ||
| 4084 | zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, msg); | ||
| 4085 | return error.CodegenFail; | ||
| 4086 | } |
src/Zcu/PerThread.zig+15-8| ... | @@ -3130,24 +3130,31 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error | ... | @@ -3130,24 +3130,31 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error |
| 3130 | } | 3130 | } |
| 3131 | } | 3131 | } |
| 3132 | 3132 | ||
| 3133 | pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) !void { | 3133 | pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) error{OutOfMemory}!void { |
| 3134 | const zcu = pt.zcu; | 3134 | const zcu = pt.zcu; |
| 3135 | const gpa = zcu.gpa; | ||
| 3135 | const comp = zcu.comp; | 3136 | const comp = zcu.comp; |
| 3136 | const ip = &zcu.intern_pool; | 3137 | const ip = &zcu.intern_pool; |
| 3137 | 3138 | ||
| 3138 | const codegen_prog_node = zcu.codegen_prog_node.start(Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), 0); | 3139 | const codegen_prog_node = zcu.codegen_prog_node.start(Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), 0); |
| 3139 | defer codegen_prog_node.end(); | 3140 | defer codegen_prog_node.end(); |
| 3140 | 3141 | ||
| 3142 | if (zcu.failed_types.fetchSwapRemove(ty)) |entry| entry.deinit(); | ||
| 3143 | |||
| 3141 | if (!Air.typeFullyResolved(Type.fromInterned(ty), zcu)) { | 3144 | if (!Air.typeFullyResolved(Type.fromInterned(ty), zcu)) { |
| 3142 | // This type failed to resolve. This is a transitive failure. | 3145 | // This type failed to resolve. This is a transitive failure. |
| 3143 | // TODO: do we need to mark this failure anywhere? I don't think so, since compilation | 3146 | return; |
| 3144 | // will fail due to the type error anyway. | ||
| 3145 | } else if (comp.bin_file) |lf| { | ||
| 3146 | lf.updateContainerType(pt, ty) catch |err| switch (err) { | ||
| 3147 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3148 | else => |e| log.err("codegen type failed: {s}", .{@errorName(e)}), | ||
| 3149 | }; | ||
| 3150 | } | 3147 | } |
| 3148 | |||
| 3149 | if (comp.bin_file) |lf| lf.updateContainerType(pt, ty) catch |err| switch (err) { | ||
| 3150 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3151 | else => |e| try zcu.failed_types.putNoClobber(gpa, ty, try Zcu.ErrorMsg.create( | ||
| 3152 | gpa, | ||
| 3153 | zcu.typeSrcLoc(ty), | ||
| 3154 | "failed to update container type: {s}", | ||
| 3155 | .{@errorName(e)}, | ||
| 3156 | )), | ||
| 3157 | }; | ||
| 3151 | } | 3158 | } |
| 3152 | 3159 | ||
| 3153 | pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void { | 3160 | pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void { |
src/link.zig+1-5| ... | @@ -1290,11 +1290,7 @@ pub const File = struct { | ... | @@ -1290,11 +1290,7 @@ pub const File = struct { |
| 1290 | args: anytype, | 1290 | args: anytype, |
| 1291 | ) error{ CodegenFail, OutOfMemory } { | 1291 | ) error{ CodegenFail, OutOfMemory } { |
| 1292 | @branchHint(.cold); | 1292 | @branchHint(.cold); |
| 1293 | const zcu = base.comp.zcu.?; | 1293 | return base.comp.zcu.?.codegenFail(nav_index, format, args); |
| 1294 | const gpa = zcu.gpa; | ||
| 1295 | try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1); | ||
| 1296 | const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args); | ||
| 1297 | zcu.failed_codegen.putAssumeCapacityNoClobber(gpa, nav_index, msg); | ||
| 1298 | } | 1294 | } |
| 1299 | 1295 | ||
| 1300 | pub const C = @import("link/C.zig"); | 1296 | pub const C = @import("link/C.zig"); |
src/link/Dwarf.zig+62-12| ... | @@ -21,12 +21,24 @@ debug_rnglists: DebugRngLists, | ... | @@ -21,12 +21,24 @@ debug_rnglists: DebugRngLists, |
| 21 | debug_str: StringSection, | 21 | debug_str: StringSection, |
| 22 | 22 | ||
| 23 | pub const UpdateError = error{ | 23 | pub const UpdateError = error{ |
| 24 | /// Indicates the error is already reported on `failed_codegen` in the Zcu. | ||
| 25 | CodegenFail, | 24 | CodegenFail, |
| 25 | ReinterpretDeclRef, | ||
| 26 | Unimplemented, | ||
| 26 | OutOfMemory, | 27 | OutOfMemory, |
| 27 | }; | 28 | EndOfStream, |
| 29 | Overflow, | ||
| 30 | Underflow, | ||
| 31 | UnexpectedEndOfFile, | ||
| 32 | } || | ||
| 33 | std.fs.File.OpenError || | ||
| 34 | std.fs.File.SetEndPosError || | ||
| 35 | std.fs.File.CopyRangeError || | ||
| 36 | std.fs.File.PReadError || | ||
| 37 | std.fs.File.PWriteError; | ||
| 28 | 38 | ||
| 29 | pub const FlushError = UpdateError || std.process.GetCwdError; | 39 | pub const FlushError = |
| 40 | UpdateError || | ||
| 41 | std.process.GetCwdError; | ||
| 30 | 42 | ||
| 31 | pub const RelocError = | 43 | pub const RelocError = |
| 32 | std.fs.File.PWriteError; | 44 | std.fs.File.PWriteError; |
| ... | @@ -587,14 +599,13 @@ const Unit = struct { | ... | @@ -587,14 +599,13 @@ const Unit = struct { |
| 587 | 599 | ||
| 588 | fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void { | 600 | fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void { |
| 589 | if (unit.off == new_off) return; | 601 | if (unit.off == new_off) return; |
| 590 | const diags = &dwarf.bin_file.base.comp.link_diags; | 602 | const n = try dwarf.getFile().?.copyRangeAll( |
| 591 | const n = dwarf.getFile().?.copyRangeAll( | ||
| 592 | sec.off(dwarf) + unit.off, | 603 | sec.off(dwarf) + unit.off, |
| 593 | dwarf.getFile().?, | 604 | dwarf.getFile().?, |
| 594 | sec.off(dwarf) + new_off, | 605 | sec.off(dwarf) + new_off, |
| 595 | unit.len, | 606 | unit.len, |
| 596 | ) catch |err| return diags.fail("failed to copy file range: {s}", .{@errorName(err)}); | 607 | ); |
| 597 | if (n != unit.len) return diags.fail("unexpected short write from copy file range", .{}); | 608 | if (n != unit.len) return error.InputOutput; |
| 598 | unit.off = new_off; | 609 | unit.off = new_off; |
| 599 | } | 610 | } |
| 600 | 611 | ||
| ... | @@ -2267,7 +2278,7 @@ pub fn deinit(dwarf: *Dwarf) void { | ... | @@ -2267,7 +2278,7 @@ pub fn deinit(dwarf: *Dwarf) void { |
| 2267 | dwarf.* = undefined; | 2278 | dwarf.* = undefined; |
| 2268 | } | 2279 | } |
| 2269 | 2280 | ||
| 2270 | fn getUnit(dwarf: *Dwarf, mod: *Module) UpdateError!Unit.Index { | 2281 | fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index { |
| 2271 | const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod); | 2282 | const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod); |
| 2272 | const unit: Unit.Index = @enumFromInt(mod_gop.index); | 2283 | const unit: Unit.Index = @enumFromInt(mod_gop.index); |
| 2273 | if (!mod_gop.found_existing) { | 2284 | if (!mod_gop.found_existing) { |
| ... | @@ -2327,7 +2338,25 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo { | ... | @@ -2327,7 +2338,25 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo { |
| 2327 | return &dwarf.mods.values()[@intFromEnum(unit)]; | 2338 | return &dwarf.mods.values()[@intFromEnum(unit)]; |
| 2328 | } | 2339 | } |
| 2329 | 2340 | ||
| 2330 | pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, sym_index: u32) UpdateError!?WipNav { | 2341 | pub fn initWipNav( |
| 2342 | dwarf: *Dwarf, | ||
| 2343 | pt: Zcu.PerThread, | ||
| 2344 | nav_index: InternPool.Nav.Index, | ||
| 2345 | sym_index: u32, | ||
| 2346 | ) error{ OutOfMemory, CodegenFail }!?WipNav { | ||
| 2347 | return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) { | ||
| 2348 | error.OutOfMemory => return error.OutOfMemory, | ||
| 2349 | error.CodegenFail => return error.CodegenFail, | ||
| 2350 | else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}), | ||
| 2351 | }; | ||
| 2352 | } | ||
| 2353 | |||
| 2354 | fn initWipNavInner( | ||
| 2355 | dwarf: *Dwarf, | ||
| 2356 | pt: Zcu.PerThread, | ||
| 2357 | nav_index: InternPool.Nav.Index, | ||
| 2358 | sym_index: u32, | ||
| 2359 | ) !?WipNav { | ||
| 2331 | const zcu = pt.zcu; | 2360 | const zcu = pt.zcu; |
| 2332 | const ip = &zcu.intern_pool; | 2361 | const ip = &zcu.intern_pool; |
| 2333 | 2362 | ||
| ... | @@ -2637,7 +2666,20 @@ pub fn finishWipNav( | ... | @@ -2637,7 +2666,20 @@ pub fn finishWipNav( |
| 2637 | pt: Zcu.PerThread, | 2666 | pt: Zcu.PerThread, |
| 2638 | nav_index: InternPool.Nav.Index, | 2667 | nav_index: InternPool.Nav.Index, |
| 2639 | wip_nav: *WipNav, | 2668 | wip_nav: *WipNav, |
| 2640 | ) UpdateError!void { | 2669 | ) error{ OutOfMemory, CodegenFail }!void { |
| 2670 | return finishWipNavInner(dwarf, pt, nav_index, wip_nav) catch |err| switch (err) { | ||
| 2671 | error.OutOfMemory => return error.OutOfMemory, | ||
| 2672 | error.CodegenFail => return error.CodegenFail, | ||
| 2673 | else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf: {s}", .{@errorName(e)}), | ||
| 2674 | }; | ||
| 2675 | } | ||
| 2676 | |||
| 2677 | fn finishWipNavInner( | ||
| 2678 | dwarf: *Dwarf, | ||
| 2679 | pt: Zcu.PerThread, | ||
| 2680 | nav_index: InternPool.Nav.Index, | ||
| 2681 | wip_nav: *WipNav, | ||
| 2682 | ) !void { | ||
| 2641 | const zcu = pt.zcu; | 2683 | const zcu = pt.zcu; |
| 2642 | const ip = &zcu.intern_pool; | 2684 | const ip = &zcu.intern_pool; |
| 2643 | const nav = ip.getNav(nav_index); | 2685 | const nav = ip.getNav(nav_index); |
| ... | @@ -2656,7 +2698,15 @@ pub fn finishWipNav( | ... | @@ -2656,7 +2698,15 @@ pub fn finishWipNav( |
| 2656 | try wip_nav.updateLazy(zcu.navSrcLoc(nav_index)); | 2698 | try wip_nav.updateLazy(zcu.navSrcLoc(nav_index)); |
| 2657 | } | 2699 | } |
| 2658 | 2700 | ||
| 2659 | pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateError!void { | 2701 | pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void { |
| 2702 | return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) { | ||
| 2703 | error.OutOfMemory => return error.OutOfMemory, | ||
| 2704 | error.CodegenFail => return error.CodegenFail, | ||
| 2705 | else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}), | ||
| 2706 | }; | ||
| 2707 | } | ||
| 2708 | |||
| 2709 | fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | ||
| 2660 | const zcu = pt.zcu; | 2710 | const zcu = pt.zcu; |
| 2661 | const ip = &zcu.intern_pool; | 2711 | const ip = &zcu.intern_pool; |
| 2662 | const nav_src_loc = zcu.navSrcLoc(nav_index); | 2712 | const nav_src_loc = zcu.navSrcLoc(nav_index); |
| ... | @@ -4310,7 +4360,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A | ... | @@ -4310,7 +4360,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A |
| 4310 | return @intFromEnum(abbrev_code); | 4360 | return @intFromEnum(abbrev_code); |
| 4311 | } | 4361 | } |
| 4312 | 4362 | ||
| 4313 | pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) !void { | 4363 | pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 4314 | const zcu = pt.zcu; | 4364 | const zcu = pt.zcu; |
| 4315 | const ip = &zcu.intern_pool; | 4365 | const ip = &zcu.intern_pool; |
| 4316 | 4366 |
src/link/Elf.zig+2-2| ... | @@ -575,7 +575,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { | ... | @@ -575,7 +575,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { |
| 575 | } | 575 | } |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | if (at_end) try self.setEndPos(end); | 578 | if (at_end) try self.base.file.?.setEndPos(end); |
| 579 | return null; | 579 | return null; |
| 580 | } | 580 | } |
| 581 | 581 | ||
| ... | @@ -638,7 +638,7 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: | ... | @@ -638,7 +638,7 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: |
| 638 | 638 | ||
| 639 | shdr.sh_offset = new_offset; | 639 | shdr.sh_offset = new_offset; |
| 640 | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { | 640 | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { |
| 641 | try self.setEndPos(shdr.sh_offset + needed_size); | 641 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); |
| 642 | } | 642 | } |
| 643 | } | 643 | } |
| 644 | 644 |
src/link/Elf/ZigObject.zig+16-8| ... | @@ -1300,7 +1300,9 @@ fn updateNavCode( | ... | @@ -1300,7 +1300,9 @@ fn updateNavCode( |
| 1300 | const capacity = atom_ptr.capacity(elf_file); | 1300 | const capacity = atom_ptr.capacity(elf_file); |
| 1301 | const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value)); | 1301 | const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value)); |
| 1302 | if (need_realloc) { | 1302 | if (need_realloc) { |
| 1303 | try self.allocateAtom(atom_ptr, true, elf_file); | 1303 | self.allocateAtom(atom_ptr, true, elf_file) catch |err| |
| 1304 | return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)}); | ||
| 1305 | |||
| 1304 | log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value }); | 1306 | log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value }); |
| 1305 | if (old_vaddr != atom_ptr.value) { | 1307 | if (old_vaddr != atom_ptr.value) { |
| 1306 | sym.value = 0; | 1308 | sym.value = 0; |
| ... | @@ -1310,7 +1312,9 @@ fn updateNavCode( | ... | @@ -1310,7 +1312,9 @@ fn updateNavCode( |
| 1310 | // TODO shrink section size | 1312 | // TODO shrink section size |
| 1311 | } | 1313 | } |
| 1312 | } else { | 1314 | } else { |
| 1313 | try self.allocateAtom(atom_ptr, true, elf_file); | 1315 | self.allocateAtom(atom_ptr, true, elf_file) catch |err| |
| 1316 | return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)}); | ||
| 1317 | |||
| 1314 | errdefer self.freeNavMetadata(elf_file, sym_index); | 1318 | errdefer self.freeNavMetadata(elf_file, sym_index); |
| 1315 | sym.value = 0; | 1319 | sym.value = 0; |
| 1316 | esym.st_value = 0; | 1320 | esym.st_value = 0; |
| ... | @@ -1342,7 +1346,8 @@ fn updateNavCode( | ... | @@ -1342,7 +1346,8 @@ fn updateNavCode( |
| 1342 | const shdr = elf_file.sections.items(.shdr)[shdr_index]; | 1346 | const shdr = elf_file.sections.items(.shdr)[shdr_index]; |
| 1343 | if (shdr.sh_type != elf.SHT_NOBITS) { | 1347 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 1344 | const file_offset = atom_ptr.offset(elf_file); | 1348 | const file_offset = atom_ptr.offset(elf_file); |
| 1345 | try elf_file.pwriteAll(code, file_offset); | 1349 | elf_file.base.file.?.pwriteAll(code, file_offset) catch |err| |
| 1350 | return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)}); | ||
| 1346 | log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len }); | 1351 | log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len }); |
| 1347 | } | 1352 | } |
| 1348 | } | 1353 | } |
| ... | @@ -1385,7 +1390,8 @@ fn updateTlv( | ... | @@ -1385,7 +1390,8 @@ fn updateTlv( |
| 1385 | const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index); | 1390 | const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index); |
| 1386 | assert(!gop.found_existing); // TODO incremental updates | 1391 | assert(!gop.found_existing); // TODO incremental updates |
| 1387 | 1392 | ||
| 1388 | try self.allocateAtom(atom_ptr, true, elf_file); | 1393 | self.allocateAtom(atom_ptr, true, elf_file) catch |err| |
| 1394 | return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)}); | ||
| 1389 | sym.value = 0; | 1395 | sym.value = 0; |
| 1390 | esym.st_value = 0; | 1396 | esym.st_value = 0; |
| 1391 | 1397 | ||
| ... | @@ -1394,7 +1400,8 @@ fn updateTlv( | ... | @@ -1394,7 +1400,8 @@ fn updateTlv( |
| 1394 | const shdr = elf_file.sections.items(.shdr)[shndx]; | 1400 | const shdr = elf_file.sections.items(.shdr)[shndx]; |
| 1395 | if (shdr.sh_type != elf.SHT_NOBITS) { | 1401 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 1396 | const file_offset = atom_ptr.offset(elf_file); | 1402 | const file_offset = atom_ptr.offset(elf_file); |
| 1397 | try elf_file.pwriteAll(code, file_offset); | 1403 | elf_file.base.file.?.pwriteAll(code, file_offset) catch |err| |
| 1404 | return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)}); | ||
| 1398 | log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{ | 1405 | log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{ |
| 1399 | atom_ptr.name(elf_file), | 1406 | atom_ptr.name(elf_file), |
| 1400 | file_offset, | 1407 | file_offset, |
| ... | @@ -1513,7 +1520,8 @@ pub fn updateFunc( | ... | @@ -1513,7 +1520,8 @@ pub fn updateFunc( |
| 1513 | target_sym.flags.has_trampoline = true; | 1520 | target_sym.flags.has_trampoline = true; |
| 1514 | } | 1521 | } |
| 1515 | const target_sym = self.symbol(sym_index); | 1522 | const target_sym = self.symbol(sym_index); |
| 1516 | try writeTrampoline(self.symbol(target_sym.extra(elf_file).trampoline).*, target_sym.*, elf_file); | 1523 | writeTrampoline(self.symbol(target_sym.extra(elf_file).trampoline).*, target_sym.*, elf_file) catch |err| |
| 1524 | return elf_file.base.cgFail(func.owner_nav, "failed to write trampoline: {s}", .{@errorName(err)}); | ||
| 1517 | } | 1525 | } |
| 1518 | } | 1526 | } |
| 1519 | 1527 | ||
| ... | @@ -1898,7 +1906,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { | ... | @@ -1898,7 +1906,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { |
| 1898 | return len; | 1906 | return len; |
| 1899 | } | 1907 | } |
| 1900 | 1908 | ||
| 1901 | fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.UpdateNavError!void { | 1909 | fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { |
| 1902 | const atom_ptr = tr_sym.atom(elf_file).?; | 1910 | const atom_ptr = tr_sym.atom(elf_file).?; |
| 1903 | const fileoff = atom_ptr.offset(elf_file); | 1911 | const fileoff = atom_ptr.offset(elf_file); |
| 1904 | const source_addr = tr_sym.address(.{}, elf_file); | 1912 | const source_addr = tr_sym.address(.{}, elf_file); |
| ... | @@ -1908,7 +1916,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.Upd | ... | @@ -1908,7 +1916,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.Upd |
| 1908 | .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf), | 1916 | .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf), |
| 1909 | else => @panic("TODO implement write trampoline for this CPU arch"), | 1917 | else => @panic("TODO implement write trampoline for this CPU arch"), |
| 1910 | }; | 1918 | }; |
| 1911 | try elf_file.pwriteAll(out, fileoff); | 1919 | try elf_file.base.file.?.pwriteAll(out, fileoff); |
| 1912 | 1920 | ||
| 1913 | if (elf_file.base.child_pid) |pid| { | 1921 | if (elf_file.base.child_pid) |pid| { |
| 1914 | switch (builtin.os.tag) { | 1922 | switch (builtin.os.tag) { |
src/link/MachO.zig+13-13| ... | @@ -532,7 +532,10 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n | ... | @@ -532,7 +532,10 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 532 | try self.generateUnwindInfo(); | 532 | try self.generateUnwindInfo(); |
| 533 | 533 | ||
| 534 | try self.initSegments(); | 534 | try self.initSegments(); |
| 535 | try self.allocateSections(); | 535 | self.allocateSections() catch |err| switch (err) { |
| 536 | error.LinkFailure => return error.LinkFailure, | ||
| 537 | else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}), | ||
| 538 | }; | ||
| 536 | self.allocateSegments(); | 539 | self.allocateSegments(); |
| 537 | self.allocateSyntheticSymbols(); | 540 | self.allocateSyntheticSymbols(); |
| 538 | 541 | ||
| ... | @@ -3133,7 +3136,7 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) !?u64 { | ... | @@ -3133,7 +3136,7 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) !?u64 { |
| 3133 | } | 3136 | } |
| 3134 | } | 3137 | } |
| 3135 | 3138 | ||
| 3136 | if (at_end) try self.setEndPos(end); | 3139 | if (at_end) try self.base.file.?.setEndPos(end); |
| 3137 | return null; | 3140 | return null; |
| 3138 | } | 3141 | } |
| 3139 | 3142 | ||
| ... | @@ -3217,25 +3220,22 @@ pub fn findFreeSpaceVirtual(self: *MachO, object_size: u64, min_alignment: u32) | ... | @@ -3217,25 +3220,22 @@ pub fn findFreeSpaceVirtual(self: *MachO, object_size: u64, min_alignment: u32) |
| 3217 | return start; | 3220 | return start; |
| 3218 | } | 3221 | } |
| 3219 | 3222 | ||
| 3220 | pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) error{LinkFailure}!void { | 3223 | pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void { |
| 3221 | const diags = &self.base.comp.link_diags; | ||
| 3222 | const file = self.base.file.?; | 3224 | const file = self.base.file.?; |
| 3223 | const amt = file.copyRangeAll(old_offset, file, new_offset, size) catch |err| | 3225 | const amt = try file.copyRangeAll(old_offset, file, new_offset, size); |
| 3224 | return diags.fail("failed to copy file range: {s}", .{@errorName(err)}); | 3226 | if (amt != size) return error.InputOutput; |
| 3225 | if (amt != size) | ||
| 3226 | return diags.fail("unexpected short write in copy file range", .{}); | ||
| 3227 | } | 3227 | } |
| 3228 | 3228 | ||
| 3229 | /// Like File.copyRangeAll but also ensures the source region is zeroed out after copy. | 3229 | /// Like File.copyRangeAll but also ensures the source region is zeroed out after copy. |
| 3230 | /// This is so that we guarantee zeroed out regions for mapping of zerofill sections by the loader. | 3230 | /// This is so that we guarantee zeroed out regions for mapping of zerofill sections by the loader. |
| 3231 | fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64) error{ LinkFailure, OutOfMemory }!void { | 3231 | fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void { |
| 3232 | const gpa = self.base.comp.gpa; | 3232 | const gpa = self.base.comp.gpa; |
| 3233 | try self.copyRangeAll(old_offset, new_offset, size); | 3233 | try self.copyRangeAll(old_offset, new_offset, size); |
| 3234 | const size_u = try self.cast(usize, size); | 3234 | const size_u = math.cast(usize, size) orelse return error.Overflow; |
| 3235 | const zeroes = try gpa.alloc(u8, size_u); // TODO no need to allocate here. | 3235 | const zeroes = try gpa.alloc(u8, size_u); // TODO no need to allocate here. |
| 3236 | defer gpa.free(zeroes); | 3236 | defer gpa.free(zeroes); |
| 3237 | @memset(zeroes, 0); | 3237 | @memset(zeroes, 0); |
| 3238 | try self.pwriteAll(zeroes, old_offset); | 3238 | try self.base.file.?.pwriteAll(zeroes, old_offset); |
| 3239 | } | 3239 | } |
| 3240 | 3240 | ||
| 3241 | const InitMetadataOptions = struct { | 3241 | const InitMetadataOptions = struct { |
| ... | @@ -3459,7 +3459,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo | ... | @@ -3459,7 +3459,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo |
| 3459 | 3459 | ||
| 3460 | sect.offset = @intCast(new_offset); | 3460 | sect.offset = @intCast(new_offset); |
| 3461 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { | 3461 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { |
| 3462 | try self.setEndPos(sect.offset + needed_size); | 3462 | try self.base.file.?.setEndPos(sect.offset + needed_size); |
| 3463 | } | 3463 | } |
| 3464 | seg.filesize = needed_size; | 3464 | seg.filesize = needed_size; |
| 3465 | } | 3465 | } |
| ... | @@ -3508,7 +3508,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void | ... | @@ -3508,7 +3508,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void |
| 3508 | sect.offset = @intCast(new_offset); | 3508 | sect.offset = @intCast(new_offset); |
| 3509 | sect.addr = new_addr; | 3509 | sect.addr = new_addr; |
| 3510 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { | 3510 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { |
| 3511 | try self.setEndPos(sect.offset + needed_size); | 3511 | try self.base.file.?.setEndPos(sect.offset + needed_size); |
| 3512 | } | 3512 | } |
| 3513 | } | 3513 | } |
| 3514 | sect.size = needed_size; | 3514 | sect.size = needed_size; |
src/link/MachO/relocatable.zig+4-1| ... | @@ -55,7 +55,10 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat | ... | @@ -55,7 +55,10 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat |
| 55 | try calcSectionSizes(macho_file); | 55 | try calcSectionSizes(macho_file); |
| 56 | 56 | ||
| 57 | try createSegment(macho_file); | 57 | try createSegment(macho_file); |
| 58 | try allocateSections(macho_file); | 58 | allocateSections(macho_file) catch |err| switch (err) { |
| 59 | error.LinkFailure => return error.LinkFailure, | ||
| 60 | else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}), | ||
| 61 | }; | ||
| 59 | allocateSegment(macho_file); | 62 | allocateSegment(macho_file); |
| 60 | 63 | ||
| 61 | if (build_options.enable_logging) { | 64 | if (build_options.enable_logging) { |