aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2025-08-30 12:08:18 -0400
committerAndrew Kelley <andrew@ziglang.org>2025-09-21 14:09:14 -0700
commitf58200e3f2967a06f343c9fc9dcae9de18def92a (patch)
tree84257e40a7a0186fbc10cf7467e65f004036d3e3 /src/codegen.zig
parent2a97e0af6d42e038d962890a320e262e676d44cb (diff)
downloadzig-f58200e3f2967a06f343c9fc9dcae9de18def92a.tar.gz
zig-f58200e3f2967a06f343c9fc9dcae9de18def92a.zip
Elf2: create a new linker from scratch
This iteration already has significantly better incremental support. Closes #24110
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig271
1 files changed, 133 insertions, 138 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 56e6e7c99f..4cbf3f5616 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -6,7 +6,6 @@ const link = @import("link.zig");
const log = std.log.scoped(.codegen);
const mem = std.mem;
const math = std.math;
-const ArrayList = std.ArrayList;
const target_util = @import("target.zig");
const trace = @import("tracy.zig").trace;
@@ -179,10 +178,11 @@ pub fn emitFunction(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
+ atom_index: u32,
any_mir: *const AnyMir,
- code: *ArrayList(u8),
+ w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+) (CodeGenError || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const func = zcu.funcInfo(func_index);
const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
@@ -195,7 +195,7 @@ pub fn emitFunction(
=> |backend| {
dev.check(devFeatureForBackend(backend));
const mir = &@field(any_mir, AnyMir.tag(backend));
- return mir.emit(lf, pt, src_loc, func_index, code, debug_output);
+ return mir.emit(lf, pt, src_loc, func_index, atom_index, w, debug_output);
},
}
}
@@ -205,9 +205,10 @@ pub fn generateLazyFunction(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
lazy_sym: link.File.LazySymbol,
- code: *ArrayList(u8),
+ atom_index: u32,
+ w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+) (CodeGenError || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
&zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result
@@ -217,19 +218,11 @@ pub fn generateLazyFunction(
else => unreachable,
inline .stage2_riscv64, .stage2_x86_64 => |backend| {
dev.check(devFeatureForBackend(backend));
- return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output);
+ return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, atom_index, w, debug_output);
},
}
}
-fn writeFloat(comptime F: type, f: F, target: *const std.Target, endian: std.builtin.Endian, code: []u8) void {
- _ = target;
- const bits = @typeInfo(F).float.bits;
- const Int = @Type(.{ .int = .{ .signedness = .unsigned, .bits = bits } });
- const int: Int = @bitCast(f);
- mem.writeInt(Int, code[0..@divExact(bits, 8)], int, endian);
-}
-
pub fn generateLazySymbol(
bin_file: *link.File,
pt: Zcu.PerThread,
@@ -237,17 +230,14 @@ pub fn generateLazySymbol(
lazy_sym: link.File.LazySymbol,
// TODO don't use an "out" parameter like this; put it in the result instead
alignment: *Alignment,
- code: *ArrayList(u8),
+ w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
reloc_parent: link.File.RelocInfo.Parent,
-) CodeGenError!void {
- _ = reloc_parent;
-
+) (CodeGenError || std.Io.Writer.Error)!void {
const tracy = trace(@src());
defer tracy.end();
const comp = bin_file.comp;
- const gpa = comp.gpa;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const target = &comp.root_mod.resolved_target.result;
@@ -260,37 +250,36 @@ pub fn generateLazySymbol(
if (lazy_sym.kind == .code) {
alignment.* = target_util.defaultFunctionAlignment(target);
- return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, code, debug_output);
+ return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output);
}
if (lazy_sym.ty == .anyerror_type) {
alignment.* = .@"4";
const err_names = ip.global_error_set.getNamesFromMainThread();
- var offset_index: u32 = @intCast(code.items.len);
- var string_index: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0)));
- try code.resize(gpa, offset_index + string_index);
- mem.writeInt(u32, code.items[offset_index..][0..4], @intCast(err_names.len), endian);
+ const strings_start: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0)));
+ var string_index = strings_start;
+ try w.rebase(w.end, string_index);
+ w.writeInt(u32, @intCast(err_names.len), endian) catch unreachable;
if (err_names.len == 0) return;
- offset_index += 4;
for (err_names) |err_name_nts| {
- const err_name = err_name_nts.toSlice(ip);
- mem.writeInt(u32, code.items[offset_index..][0..4], string_index, endian);
- offset_index += 4;
- try code.ensureUnusedCapacity(gpa, err_name.len + 1);
- code.appendSliceAssumeCapacity(err_name);
- code.appendAssumeCapacity(0);
- string_index += @intCast(err_name.len + 1);
+ w.writeInt(u32, string_index, endian) catch unreachable;
+ string_index += @intCast(err_name_nts.toSlice(ip).len + 1);
+ }
+ w.writeInt(u32, string_index, endian) catch unreachable;
+ try w.rebase(w.end, string_index - strings_start);
+ for (err_names) |err_name_nts| {
+ w.writeAll(err_name_nts.toSlice(ip)) catch unreachable;
+ w.writeByte(0) catch unreachable;
}
- mem.writeInt(u32, code.items[offset_index..][0..4], string_index, endian);
} else if (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu) == .@"enum") {
alignment.* = .@"1";
const enum_ty = Type.fromInterned(lazy_sym.ty);
const tag_names = enum_ty.enumFields(zcu);
for (0..tag_names.len) |tag_index| {
const tag_name = tag_names.get(ip)[tag_index].toSlice(ip);
- try code.ensureUnusedCapacity(gpa, tag_name.len + 1);
- code.appendSliceAssumeCapacity(tag_name);
- code.appendAssumeCapacity(0);
+ try w.rebase(w.end, tag_name.len + 1);
+ w.writeAll(tag_name) catch unreachable;
+ w.writeByte(0) catch unreachable;
}
} else {
return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {f}", .{
@@ -312,14 +301,13 @@ pub fn generateSymbol(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
val: Value,
- code: *ArrayList(u8),
+ w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
-) GenerateSymbolError!void {
+) (GenerateSymbolError || std.Io.Writer.Error)!void {
const tracy = trace(@src());
defer tracy.end();
const zcu = pt.zcu;
- const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const ty = val.typeOf(zcu);
@@ -330,7 +318,7 @@ pub fn generateSymbol(
if (val.isUndef(zcu)) {
const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
- try code.appendNTimes(gpa, 0xaa, abi_size);
+ try w.splatByteAll(0xaa, abi_size);
return;
}
@@ -360,7 +348,7 @@ pub fn generateSymbol(
.null => unreachable, // non-runtime value
.@"unreachable" => unreachable, // non-runtime value
.empty_tuple => return,
- .false, .true => try code.append(gpa, switch (simple_value) {
+ .false, .true => try w.writeByte(switch (simple_value) {
.false => 0,
.true => 1,
else => unreachable,
@@ -376,11 +364,11 @@ pub fn generateSymbol(
const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
var space: Value.BigIntSpace = undefined;
const int_val = val.toBigInt(&space, zcu);
- int_val.writeTwosComplement(try code.addManyAsSlice(gpa, abi_size), endian);
+ int_val.writeTwosComplement(try w.writableSlice(abi_size), endian);
},
.err => |err| {
const int = try pt.getErrorValue(err.name);
- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), @intCast(int), endian);
+ try w.writeInt(u16, @intCast(int), endian);
},
.error_union => |error_union| {
const payload_ty = ty.errorUnionPayload(zcu);
@@ -390,7 +378,7 @@ pub fn generateSymbol(
};
if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian);
+ try w.writeInt(u16, err_val, endian);
return;
}
@@ -400,63 +388,63 @@ pub fn generateSymbol(
// error value first when its type is larger than the error union's payload
if (error_align.order(payload_align) == .gt) {
- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian);
+ try w.writeInt(u16, err_val, endian);
}
// emit payload part of the error union
{
- const begin = code.items.len;
+ const begin = w.end;
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (error_union.val) {
.err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }),
.payload => |payload| payload,
- }), code, reloc_parent);
- const unpadded_end = code.items.len - begin;
+ }), w, reloc_parent);
+ const unpadded_end = w.end - begin;
const padded_end = abi_align.forward(unpadded_end);
const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
if (padding > 0) {
- try code.appendNTimes(gpa, 0, padding);
+ try w.splatByteAll(0, padding);
}
}
// Payload size is larger than error set, so emit our error set last
if (error_align.compare(.lte, payload_align)) {
- const begin = code.items.len;
- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian);
- const unpadded_end = code.items.len - begin;
+ const begin = w.end;
+ try w.writeInt(u16, err_val, endian);
+ const unpadded_end = w.end - begin;
const padded_end = abi_align.forward(unpadded_end);
const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
if (padding > 0) {
- try code.appendNTimes(gpa, 0, padding);
+ try w.splatByteAll(0, padding);
}
}
},
.enum_tag => |enum_tag| {
const int_tag_ty = ty.intTagType(zcu);
- try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), w, reloc_parent);
},
.float => |float| storage: switch (float.storage) {
- .f16 => |f16_val| writeFloat(f16, f16_val, target, endian, try code.addManyAsArray(gpa, 2)),
- .f32 => |f32_val| writeFloat(f32, f32_val, target, endian, try code.addManyAsArray(gpa, 4)),
- .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(gpa, 8)),
+ .f16 => |f16_val| try w.writeInt(u16, @bitCast(f16_val), endian),
+ .f32 => |f32_val| try w.writeInt(u32, @bitCast(f32_val), endian),
+ .f64 => |f64_val| try w.writeInt(u64, @bitCast(f64_val), endian),
.f80 => |f80_val| {
- writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(gpa, 10));
+ try w.writeInt(u80, @bitCast(f80_val), endian);
const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
- try code.appendNTimes(gpa, 0, abi_size - 10);
+ try w.splatByteAll(0, abi_size - 10);
},
.f128 => |f128_val| switch (Type.fromInterned(float.ty).floatBits(target)) {
else => unreachable,
16 => continue :storage .{ .f16 = @floatCast(f128_val) },
32 => continue :storage .{ .f32 = @floatCast(f128_val) },
64 => continue :storage .{ .f64 = @floatCast(f128_val) },
- 128 => writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(gpa, 16)),
+ 128 => try w.writeInt(u128, @bitCast(f128_val), endian),
},
},
- .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), code, reloc_parent, 0),
+ .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0),
.slice => |slice| {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), code, reloc_parent);
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), w, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), w, reloc_parent);
},
.opt => {
const payload_type = ty.optionalChild(zcu);
@@ -465,9 +453,9 @@ pub fn generateSymbol(
if (ty.optionalReprIsPayload(zcu)) {
if (payload_val) |value| {
- try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent);
} else {
- try code.appendNTimes(gpa, 0, abi_size);
+ try w.splatByteAll(0, abi_size);
}
} else {
const padding = abi_size - (math.cast(usize, payload_type.abiSize(zcu)) orelse return error.Overflow) - 1;
@@ -475,15 +463,15 @@ pub fn generateSymbol(
const value = payload_val orelse Value.fromInterned(try pt.intern(.{
.undef = payload_type.toIntern(),
}));
- try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent);
}
- try code.append(gpa, @intFromBool(payload_val != null));
- try code.appendNTimes(gpa, 0, padding);
+ try w.writeByte(@intFromBool(payload_val != null));
+ try w.splatByteAll(0, padding);
}
},
.aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
.array_type => |array_type| switch (aggregate.storage) {
- .bytes => |bytes| try code.appendSlice(gpa, bytes.toSlice(array_type.lenIncludingSentinel(), ip)),
+ .bytes => |bytes| try w.writeAll(bytes.toSlice(array_type.lenIncludingSentinel(), ip)),
.elems, .repeated_elem => {
var index: u64 = 0;
while (index < array_type.lenIncludingSentinel()) : (index += 1) {
@@ -494,14 +482,14 @@ pub fn generateSymbol(
elem
else
array_type.sentinel,
- }), code, reloc_parent);
+ }), w, reloc_parent);
}
},
},
.vector_type => |vector_type| {
const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
if (vector_type.child == .bool_type) {
- const bytes = try code.addManyAsSlice(gpa, abi_size);
+ const bytes = try w.writableSlice(abi_size);
@memset(bytes, 0xaa);
var index: usize = 0;
const len = math.cast(usize, vector_type.len) orelse return error.Overflow;
@@ -540,7 +528,7 @@ pub fn generateSymbol(
}
} else {
switch (aggregate.storage) {
- .bytes => |bytes| try code.appendSlice(gpa, bytes.toSlice(vector_type.len, ip)),
+ .bytes => |bytes| try w.writeAll(bytes.toSlice(vector_type.len, ip)),
.elems, .repeated_elem => {
var index: u64 = 0;
while (index < vector_type.len) : (index += 1) {
@@ -550,7 +538,7 @@ pub fn generateSymbol(
math.cast(usize, index) orelse return error.Overflow
],
.repeated_elem => |elem| elem,
- }), code, reloc_parent);
+ }), w, reloc_parent);
}
},
}
@@ -558,11 +546,11 @@ pub fn generateSymbol(
const padding = abi_size -
(math.cast(usize, Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len) orelse
return error.Overflow);
- if (padding > 0) try code.appendNTimes(gpa, 0, padding);
+ if (padding > 0) try w.splatByteAll(0, padding);
}
},
.tuple_type => |tuple| {
- const struct_begin = code.items.len;
+ const struct_begin = w.end;
for (
tuple.types.get(ip),
tuple.values.get(ip),
@@ -580,8 +568,8 @@ pub fn generateSymbol(
.repeated_elem => |elem| elem,
};
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);
- const unpadded_field_end = code.items.len - struct_begin;
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent);
+ const unpadded_field_end = w.end - struct_begin;
// Pad struct members if required
const padded_field_end = ty.structFieldOffset(index + 1, zcu);
@@ -589,7 +577,7 @@ pub fn generateSymbol(
return error.Overflow;
if (padding > 0) {
- try code.appendNTimes(gpa, 0, padding);
+ try w.splatByteAll(0, padding);
}
}
},
@@ -598,8 +586,9 @@ pub fn generateSymbol(
switch (struct_type.layout) {
.@"packed" => {
const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
- const current_pos = code.items.len;
- try code.appendNTimes(gpa, 0, abi_size);
+ const start = w.end;
+ const buffer = try w.writableSlice(abi_size);
+ @memset(buffer, 0);
var bits: u16 = 0;
for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
@@ -619,22 +608,20 @@ pub fn generateSymbol(
error.DivisionByZero => unreachable,
error.UnexpectedRemainder => return error.RelocationNotByteAligned,
};
- code.items.len = current_pos + field_offset;
- // TODO: code.lockPointers();
+ w.end = start + field_offset;
defer {
- assert(code.items.len == current_pos + field_offset + @divExact(target.ptrBitWidth(), 8));
- // TODO: code.unlockPointers();
- code.items.len = current_pos + abi_size;
+ assert(w.end == start + field_offset + @divExact(target.ptrBitWidth(), 8));
+ w.end = start + abi_size;
}
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent);
} else {
- Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, code.items[current_pos..], bits) catch unreachable;
+ Value.fromInterned(field_val).writeToPackedMemory(.fromInterned(field_ty), pt, buffer, bits) catch unreachable;
}
bits += @intCast(Type.fromInterned(field_ty).bitSize(zcu));
}
},
.auto, .@"extern" => {
- const struct_begin = code.items.len;
+ const struct_begin = w.end;
const field_types = struct_type.field_types.get(ip);
const offsets = struct_type.offsets.get(ip);
@@ -654,11 +641,11 @@ pub fn generateSymbol(
const padding = math.cast(
usize,
- offsets[field_index] - (code.items.len - struct_begin),
+ offsets[field_index] - (w.end - struct_begin),
) orelse return error.Overflow;
- if (padding > 0) try code.appendNTimes(gpa, 0, padding);
+ if (padding > 0) try w.splatByteAll(0, padding);
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent);
}
const size = struct_type.sizeUnordered(ip);
@@ -666,10 +653,9 @@ pub fn generateSymbol(
const padding = math.cast(
usize,
- std.mem.alignForward(u64, size, @max(alignment, 1)) -
- (code.items.len - struct_begin),
+ std.mem.alignForward(u64, size, @max(alignment, 1)) - (w.end - struct_begin),
) orelse return error.Overflow;
- if (padding > 0) try code.appendNTimes(gpa, 0, padding);
+ if (padding > 0) try w.splatByteAll(0, padding);
},
}
},
@@ -679,12 +665,12 @@ pub fn generateSymbol(
const layout = ty.unionGetLayout(zcu);
if (layout.payload_size == 0) {
- return generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);
+ return generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);
}
// Check if we should store the tag first.
if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);
}
const union_obj = zcu.typeToUnion(ty).?;
@@ -692,24 +678,24 @@ pub fn generateSymbol(
const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBits(zcu)) {
- try code.appendNTimes(gpa, 0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
+ try w.splatByteAll(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
} else {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent);
const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(zcu)) orelse return error.Overflow;
if (padding > 0) {
- try code.appendNTimes(gpa, 0, padding);
+ try w.splatByteAll(0, padding);
}
}
} else {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent);
}
if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);
+ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);
if (layout.padding > 0) {
- try code.appendNTimes(gpa, 0, layout.padding);
+ try w.splatByteAll(0, layout.padding);
}
}
},
@@ -722,30 +708,30 @@ fn lowerPtr(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
ptr_val: InternPool.Index,
- code: *ArrayList(u8),
+ w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
prev_offset: u64,
-) GenerateSymbolError!void {
+) (GenerateSymbolError || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
const offset: u64 = prev_offset + ptr.byte_offset;
return switch (ptr.base_addr) {
- .nav => |nav| try lowerNavRef(bin_file, pt, nav, code, reloc_parent, offset),
- .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, code, reloc_parent, offset),
- .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), code, reloc_parent),
+ .nav => |nav| try lowerNavRef(bin_file, pt, nav, w, reloc_parent, offset),
+ .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, w, reloc_parent, offset),
+ .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), w, reloc_parent),
.eu_payload => |eu_ptr| try lowerPtr(
bin_file,
pt,
src_loc,
eu_ptr,
- code,
+ w,
reloc_parent,
offset + errUnionPayloadOffset(
Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu).errorUnionPayload(zcu),
zcu,
),
),
- .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, code, reloc_parent, offset),
+ .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, w, reloc_parent, offset),
.field => |field| {
const base_ptr = Value.fromInterned(field.base);
const base_ty = base_ptr.typeOf(zcu).childType(zcu);
@@ -764,7 +750,7 @@ fn lowerPtr(
},
else => unreachable,
};
- return lowerPtr(bin_file, pt, src_loc, field.base, code, reloc_parent, offset + field_off);
+ return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off);
},
.arr_elem, .comptime_field, .comptime_alloc => unreachable,
};
@@ -775,12 +761,11 @@ fn lowerUavRef(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
uav: InternPool.Key.Ptr.BaseAddr.Uav,
- code: *ArrayList(u8),
+ w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
offset: u64,
-) GenerateSymbolError!void {
+) (GenerateSymbolError || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
- const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const comp = lf.comp;
const target = &comp.root_mod.resolved_target.result;
@@ -790,10 +775,9 @@ fn lowerUavRef(
const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
log.debug("lowerUavRef: ty = {f}", .{uav_ty.fmt(pt)});
- try code.ensureUnusedCapacity(gpa, ptr_width_bytes);
if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) {
- code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes);
+ try w.splatByteAll(0xaa, ptr_width_bytes);
return;
}
@@ -804,29 +788,32 @@ fn lowerUavRef(
dev.check(link.File.Tag.wasm.devFeature());
const wasm = lf.cast(.wasm).?;
assert(reloc_parent == .none);
- try wasm.addUavReloc(code.items.len, uav.val, uav.orig_ty, @intCast(offset));
- code.appendNTimesAssumeCapacity(0, ptr_width_bytes);
+ try wasm.addUavReloc(w.end, uav.val, uav.orig_ty, @intCast(offset));
+ try w.splatByteAll(0, ptr_width_bytes);
return;
},
else => {},
}
- const uav_align = ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment;
+ const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
switch (try lf.lowerUav(pt, uav_val, uav_align, src_loc)) {
.sym_index => {},
.fail => |em| std.debug.panic("TODO rework lowerUav. internal error: {s}", .{em.msg}),
}
- const vaddr = try lf.getUavVAddr(uav_val, .{
+ const vaddr = lf.getUavVAddr(uav_val, .{
.parent = reloc_parent,
- .offset = code.items.len,
+ .offset = w.end,
.addend = @intCast(offset),
- });
+ }) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => |e| std.debug.panic("TODO rework lowerUav. internal error: {t}", .{e}),
+ };
const endian = target.cpu.arch.endian();
switch (ptr_width_bytes) {
- 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian),
- 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian),
- 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian),
+ 2 => try w.writeInt(u16, @intCast(vaddr), endian),
+ 4 => try w.writeInt(u32, @intCast(vaddr), endian),
+ 8 => try w.writeInt(u64, vaddr, endian),
else => unreachable,
}
}
@@ -835,10 +822,10 @@ fn lowerNavRef(
lf: *link.File,
pt: Zcu.PerThread,
nav_index: InternPool.Nav.Index,
- code: *ArrayList(u8),
+ w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
offset: u64,
-) GenerateSymbolError!void {
+) (GenerateSymbolError || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -848,10 +835,8 @@ fn lowerNavRef(
const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip));
const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";
- try code.ensureUnusedCapacity(gpa, ptr_width_bytes);
-
if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) {
- code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes);
+ try w.splatByteAll(0xaa, ptr_width_bytes);
return;
}
@@ -870,13 +855,13 @@ fn lowerNavRef(
} else {
try wasm.func_table_fixups.append(gpa, .{
.table_index = @enumFromInt(gop.index),
- .offset = @intCast(code.items.len),
+ .offset = @intCast(w.end),
});
}
} else {
if (is_obj) {
try wasm.out_relocs.append(gpa, .{
- .offset = @intCast(code.items.len),
+ .offset = @intCast(w.end),
.pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) },
.tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64,
.addend = @intCast(offset),
@@ -885,12 +870,12 @@ fn lowerNavRef(
try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1);
wasm.nav_fixups.appendAssumeCapacity(.{
.navs_exe_index = try wasm.refNavExe(nav_index),
- .offset = @intCast(code.items.len),
+ .offset = @intCast(w.end),
.addend = @intCast(offset),
});
}
}
- code.appendNTimesAssumeCapacity(0, ptr_width_bytes);
+ try w.splatByteAll(0, ptr_width_bytes);
return;
},
else => {},
@@ -898,14 +883,14 @@ fn lowerNavRef(
const vaddr = lf.getNavVAddr(pt, nav_index, .{
.parent = reloc_parent,
- .offset = code.items.len,
+ .offset = w.end,
.addend = @intCast(offset),
}) catch @panic("TODO rework getNavVAddr");
const endian = target.cpu.arch.endian();
switch (ptr_width_bytes) {
- 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian),
- 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian),
- 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian),
+ 2 => try w.writeInt(u16, @intCast(vaddr), endian),
+ 4 => try w.writeInt(u32, @intCast(vaddr), endian),
+ 8 => try w.writeInt(u64, vaddr, endian),
else => unreachable,
}
}
@@ -962,6 +947,16 @@ pub fn genNavRef(
},
.link_once => unreachable,
}
+ } else if (lf.cast(.elf2)) |elf| {
+ return .{ .sym_index = @intFromEnum(elf.navSymbol(zcu, nav_index) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => |e| return .{ .fail = try ErrorMsg.create(
+ zcu.gpa,
+ src_loc,
+ "linker failed to create a nav: {t}",
+ .{e},
+ ) },
+ }) };
} else if (lf.cast(.macho)) |macho_file| {
const zo = macho_file.getZigObject().?;
switch (linkage) {