mirror of
https://github.com/ziglang/zig.git
synced 2024-12-12 14:16:59 +00:00
15ff891f04
* pad out (non-packed) struct fields when lowering to bytes to be saved in the binary - prior to this change, fields would be saved at non-aligned addresses leading to wrong accesses * add a matching test case to `behavior/struct.zig` tests * fix offset to field calculation in `struct_field_ptr` on `x86_64`
510 lines
24 KiB
Zig
510 lines
24 KiB
Zig
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
const mem = std.mem;
|
|
const math = std.math;
|
|
const assert = std.debug.assert;
|
|
const Air = @import("Air.zig");
|
|
const Zir = @import("Zir.zig");
|
|
const Liveness = @import("Liveness.zig");
|
|
const Type = @import("type.zig").Type;
|
|
const Value = @import("value.zig").Value;
|
|
const TypedValue = @import("TypedValue.zig");
|
|
const link = @import("link.zig");
|
|
const Module = @import("Module.zig");
|
|
const Compilation = @import("Compilation.zig");
|
|
const ErrorMsg = Module.ErrorMsg;
|
|
const Target = std.Target;
|
|
const Allocator = mem.Allocator;
|
|
const trace = @import("tracy.zig").trace;
|
|
const DW = std.dwarf;
|
|
const leb128 = std.leb;
|
|
const log = std.log.scoped(.codegen);
|
|
const build_options = @import("build_options");
|
|
const RegisterManager = @import("register_manager.zig").RegisterManager;
|
|
|
|
pub const FnResult = union(enum) {
|
|
/// The `code` parameter passed to `generateSymbol` has the value appended.
|
|
appended: void,
|
|
fail: *ErrorMsg,
|
|
};
|
|
pub const Result = union(enum) {
|
|
/// The `code` parameter passed to `generateSymbol` has the value appended.
|
|
appended: void,
|
|
/// The value is available externally, `code` is unused.
|
|
externally_managed: []const u8,
|
|
fail: *ErrorMsg,
|
|
};
|
|
|
|
pub const GenerateSymbolError = error{
|
|
OutOfMemory,
|
|
Overflow,
|
|
/// A Decl that this symbol depends on had a semantic analysis failure.
|
|
AnalysisFail,
|
|
};
|
|
|
|
pub const DebugInfoOutput = union(enum) {
|
|
dwarf: struct {
|
|
dbg_line: *std.ArrayList(u8),
|
|
dbg_info: *std.ArrayList(u8),
|
|
dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable,
|
|
},
|
|
/// the plan9 debuginfo output is a bytecode with 4 opcodes
|
|
/// assume all numbers/variables are bytes
|
|
/// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset
|
|
/// x when x < 65 -> add x to line offset
|
|
/// x when x < 129 -> subtract 64 from x and subtract it from the line offset
|
|
/// x -> subtract 129 from x, multiply it by the quanta of the instruction size
|
|
/// (1 on x86_64), and add it to the pc
|
|
/// after every opcode, add the quanta of the instruction size to the pc
|
|
plan9: struct {
|
|
/// the actual opcodes
|
|
dbg_line: *std.ArrayList(u8),
|
|
/// what line the debuginfo starts on
|
|
/// this helps because the linker might have to insert some opcodes to make sure that the line count starts at the right amount for the next decl
|
|
start_line: *?u32,
|
|
/// what the line count ends on after codegen
|
|
/// this helps because the linker might have to insert some opcodes to make sure that the line count starts at the right amount for the next decl
|
|
end_line: *u32,
|
|
/// the last pc change op
|
|
/// This is very useful for adding quanta
|
|
/// to it if its not actually the last one.
|
|
pcop_change_index: *?u32,
|
|
},
|
|
none,
|
|
};
|
|
|
|
pub fn generateFunction(
|
|
bin_file: *link.File,
|
|
src_loc: Module.SrcLoc,
|
|
func: *Module.Fn,
|
|
air: Air,
|
|
liveness: Liveness,
|
|
code: *std.ArrayList(u8),
|
|
debug_output: DebugInfoOutput,
|
|
) GenerateSymbolError!FnResult {
|
|
switch (bin_file.options.target.cpu.arch) {
|
|
.wasm32 => unreachable, // has its own code path
|
|
.wasm64 => unreachable, // has its own code path
|
|
.arm,
|
|
.armeb,
|
|
=> return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
.aarch64,
|
|
.aarch64_be,
|
|
.aarch64_32,
|
|
=> return @import("arch/aarch64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.arc => return Function(.arc).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.avr => return Function(.avr).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.bpfel => return Function(.bpfel).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.bpfeb => return Function(.bpfeb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.hexagon => return Function(.hexagon).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.mips => return Function(.mips).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.mipsel => return Function(.mipsel).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.mips64 => return Function(.mips64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.mips64el => return Function(.mips64el).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.msp430 => return Function(.msp430).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.powerpc => return Function(.powerpc).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.powerpc64 => return Function(.powerpc64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.powerpc64le => return Function(.powerpc64le).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.r600 => return Function(.r600).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.amdgcn => return Function(.amdgcn).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.riscv32 => return Function(.riscv32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
.riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.sparc => return Function(.sparc).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.sparcv9 => return Function(.sparcv9).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.sparcel => return Function(.sparcel).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.s390x => return Function(.s390x).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.tce => return Function(.tce).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.tcele => return Function(.tcele).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.thumb => return Function(.thumb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.thumbeb => return Function(.thumbeb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.i386 => return Function(.i386).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
.x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.xcore => return Function(.xcore).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.nvptx => return Function(.nvptx).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.nvptx64 => return Function(.nvptx64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.le32 => return Function(.le32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.le64 => return Function(.le64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.amdil => return Function(.amdil).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.amdil64 => return Function(.amdil64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.hsail => return Function(.hsail).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.hsail64 => return Function(.hsail64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.spir => return Function(.spir).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.spir64 => return Function(.spir64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.kalimba => return Function(.kalimba).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.shave => return Function(.shave).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.lanai => return Function(.lanai).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.renderscript32 => return Function(.renderscript32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.renderscript64 => return Function(.renderscript64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
//.ve => return Function(.ve).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
|
|
else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
|
|
}
|
|
}
|
|
|
|
pub fn generateSymbol(
|
|
bin_file: *link.File,
|
|
src_loc: Module.SrcLoc,
|
|
typed_value: TypedValue,
|
|
code: *std.ArrayList(u8),
|
|
debug_output: DebugInfoOutput,
|
|
) GenerateSymbolError!Result {
|
|
const tracy = trace(@src());
|
|
defer tracy.end();
|
|
|
|
if (typed_value.val.isUndefDeep()) {
|
|
const target = bin_file.options.target;
|
|
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
|
|
try code.appendNTimes(0xaa, abi_size);
|
|
return Result{ .appended = {} };
|
|
}
|
|
|
|
switch (typed_value.ty.zigTypeTag()) {
|
|
.Fn => {
|
|
return Result{
|
|
.fail = try ErrorMsg.create(
|
|
bin_file.allocator,
|
|
src_loc,
|
|
"TODO implement generateSymbol function pointers",
|
|
.{},
|
|
),
|
|
};
|
|
},
|
|
.Array => switch (typed_value.val.tag()) {
|
|
.bytes => {
|
|
// TODO populate .debug_info for the array
|
|
const payload = typed_value.val.castTag(.bytes).?;
|
|
if (typed_value.ty.sentinel()) |sentinel| {
|
|
try code.ensureUnusedCapacity(payload.data.len + 1);
|
|
code.appendSliceAssumeCapacity(payload.data);
|
|
switch (try generateSymbol(bin_file, src_loc, .{
|
|
.ty = typed_value.ty.elemType(),
|
|
.val = sentinel,
|
|
}, code, debug_output)) {
|
|
.appended => return Result{ .appended = {} },
|
|
.externally_managed => |slice| {
|
|
code.appendSliceAssumeCapacity(slice);
|
|
return Result{ .appended = {} };
|
|
},
|
|
.fail => |em| return Result{ .fail = em },
|
|
}
|
|
} else {
|
|
return Result{ .externally_managed = payload.data };
|
|
}
|
|
},
|
|
.array => {
|
|
// TODO populate .debug_info for the array
|
|
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, .{
|
|
.ty = elem_ty,
|
|
.val = elem_val,
|
|
}, code, debug_output)) {
|
|
.appended => {},
|
|
.externally_managed => |slice| {
|
|
code.appendSliceAssumeCapacity(slice);
|
|
return Result{ .appended = {} };
|
|
},
|
|
.fail => |em| return Result{ .fail = em },
|
|
}
|
|
}
|
|
return Result{ .appended = {} };
|
|
},
|
|
else => return Result{
|
|
.fail = try ErrorMsg.create(
|
|
bin_file.allocator,
|
|
src_loc,
|
|
"TODO implement generateSymbol for array type value: {s}",
|
|
.{@tagName(typed_value.val.tag())},
|
|
),
|
|
},
|
|
},
|
|
.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);
|
|
},
|
|
.decl_ref => {
|
|
const decl = typed_value.val.castTag(.decl_ref).?.data;
|
|
return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output);
|
|
},
|
|
.slice => {
|
|
// TODO populate .debug_info for the slice
|
|
const slice = typed_value.val.castTag(.slice).?.data;
|
|
|
|
// generate ptr
|
|
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
|
|
const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
|
|
switch (try generateSymbol(bin_file, src_loc, .{
|
|
.ty = slice_ptr_field_type,
|
|
.val = slice.ptr,
|
|
}, code, debug_output)) {
|
|
.appended => {},
|
|
.externally_managed => |external_slice| {
|
|
code.appendSliceAssumeCapacity(external_slice);
|
|
},
|
|
.fail => |em| return Result{ .fail = em },
|
|
}
|
|
|
|
// generate length
|
|
switch (try generateSymbol(bin_file, src_loc, .{
|
|
.ty = Type.initTag(.usize),
|
|
.val = slice.len,
|
|
}, code, debug_output)) {
|
|
.appended => {},
|
|
.externally_managed => |external_slice| {
|
|
code.appendSliceAssumeCapacity(external_slice);
|
|
},
|
|
.fail => |em| return Result{ .fail = em },
|
|
}
|
|
|
|
return Result{ .appended = {} };
|
|
},
|
|
else => return Result{
|
|
.fail = try ErrorMsg.create(
|
|
bin_file.allocator,
|
|
src_loc,
|
|
"TODO implement generateSymbol for pointer type value: '{s}'",
|
|
.{@tagName(typed_value.val.tag())},
|
|
),
|
|
},
|
|
},
|
|
.Int => {
|
|
// TODO populate .debug_info for the integer
|
|
const endian = bin_file.options.target.cpu.arch.endian();
|
|
const info = typed_value.ty.intInfo(bin_file.options.target);
|
|
if (info.bits <= 8) {
|
|
const x = @intCast(u8, typed_value.val.toUnsignedInt());
|
|
try code.append(x);
|
|
return Result{ .appended = {} };
|
|
}
|
|
if (info.bits > 64) {
|
|
return Result{
|
|
.fail = try ErrorMsg.create(
|
|
bin_file.allocator,
|
|
src_loc,
|
|
"TODO implement generateSymbol for big ints ('{}')",
|
|
.{typed_value.ty},
|
|
),
|
|
};
|
|
}
|
|
switch (info.signedness) {
|
|
.unsigned => {
|
|
if (info.bits <= 16) {
|
|
const x = @intCast(u16, typed_value.val.toUnsignedInt());
|
|
mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
|
|
} else if (info.bits <= 32) {
|
|
const x = @intCast(u32, typed_value.val.toUnsignedInt());
|
|
mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
|
|
} else {
|
|
const x = typed_value.val.toUnsignedInt();
|
|
mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
|
|
}
|
|
},
|
|
.signed => {
|
|
if (info.bits <= 16) {
|
|
const x = @intCast(i16, typed_value.val.toSignedInt());
|
|
mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
|
|
} else if (info.bits <= 32) {
|
|
const x = @intCast(i32, typed_value.val.toSignedInt());
|
|
mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
|
|
} else {
|
|
const x = typed_value.val.toSignedInt();
|
|
mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
|
|
}
|
|
},
|
|
}
|
|
return Result{ .appended = {} };
|
|
},
|
|
.Enum => {
|
|
// TODO populate .debug_info for the enum
|
|
var int_buffer: Value.Payload.U64 = undefined;
|
|
const int_val = typed_value.enumToInt(&int_buffer);
|
|
|
|
const target = bin_file.options.target;
|
|
const info = typed_value.ty.intInfo(target);
|
|
if (info.bits <= 8) {
|
|
const x = @intCast(u8, int_val.toUnsignedInt());
|
|
try code.append(x);
|
|
return Result{ .appended = {} };
|
|
}
|
|
if (info.bits > 64) {
|
|
return Result{
|
|
.fail = try ErrorMsg.create(
|
|
bin_file.allocator,
|
|
src_loc,
|
|
"TODO implement generateSymbol for big int enums ('{}')",
|
|
.{typed_value.ty},
|
|
),
|
|
};
|
|
}
|
|
const endian = target.cpu.arch.endian();
|
|
switch (info.signedness) {
|
|
.unsigned => {
|
|
if (info.bits <= 16) {
|
|
const x = @intCast(u16, int_val.toUnsignedInt());
|
|
mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
|
|
} else if (info.bits <= 32) {
|
|
const x = @intCast(u32, int_val.toUnsignedInt());
|
|
mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
|
|
} else {
|
|
const x = int_val.toUnsignedInt();
|
|
mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
|
|
}
|
|
},
|
|
.signed => {
|
|
if (info.bits <= 16) {
|
|
const x = @intCast(i16, int_val.toSignedInt());
|
|
mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
|
|
} else if (info.bits <= 32) {
|
|
const x = @intCast(i32, int_val.toSignedInt());
|
|
mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
|
|
} else {
|
|
const x = int_val.toSignedInt();
|
|
mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
|
|
}
|
|
},
|
|
}
|
|
return Result{ .appended = {} };
|
|
},
|
|
.Bool => {
|
|
const x: u8 = @boolToInt(typed_value.val.toBool());
|
|
try code.append(x);
|
|
return Result{ .appended = {} };
|
|
},
|
|
.Struct => {
|
|
// TODO debug info
|
|
const struct_obj = typed_value.ty.castTag(.@"struct").?.data;
|
|
if (struct_obj.layout == .Packed) {
|
|
return Result{
|
|
.fail = try ErrorMsg.create(
|
|
bin_file.allocator,
|
|
src_loc,
|
|
"TODO implement generateSymbol for packed struct",
|
|
.{},
|
|
),
|
|
};
|
|
}
|
|
|
|
const struct_begin = code.items.len;
|
|
const field_vals = typed_value.val.castTag(.@"struct").?.data;
|
|
for (field_vals) |field_val, index| {
|
|
const field_ty = typed_value.ty.structFieldType(index);
|
|
if (!field_ty.hasRuntimeBits()) continue;
|
|
|
|
switch (try generateSymbol(bin_file, src_loc, .{
|
|
.ty = field_ty,
|
|
.val = field_val,
|
|
}, code, debug_output)) {
|
|
.appended => {},
|
|
.externally_managed => |external_slice| {
|
|
code.appendSliceAssumeCapacity(external_slice);
|
|
},
|
|
.fail => |em| return Result{ .fail = em },
|
|
}
|
|
const unpadded_field_end = code.items.len - struct_begin;
|
|
|
|
// Pad struct members if required
|
|
const target = bin_file.options.target;
|
|
const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);
|
|
const padding = try math.cast(usize, padded_field_end - unpadded_field_end);
|
|
|
|
if (padding > 0) {
|
|
try code.writer().writeByteNTimes(0, padding);
|
|
}
|
|
}
|
|
|
|
return Result{ .appended = {} };
|
|
},
|
|
.Union => {
|
|
// TODO generateSymbol for unions
|
|
const target = bin_file.options.target;
|
|
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
|
|
try code.writer().writeByteNTimes(0xaa, abi_size);
|
|
|
|
return Result{ .appended = {} };
|
|
},
|
|
.Optional => {
|
|
// TODO generateSymbol for optionals
|
|
const target = bin_file.options.target;
|
|
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
|
|
try code.writer().writeByteNTimes(0xaa, abi_size);
|
|
|
|
return Result{ .appended = {} };
|
|
},
|
|
else => |t| {
|
|
return Result{
|
|
.fail = try ErrorMsg.create(
|
|
bin_file.allocator,
|
|
src_loc,
|
|
"TODO implement generateSymbol for type '{s}'",
|
|
.{@tagName(t)},
|
|
),
|
|
};
|
|
},
|
|
}
|
|
}
|
|
|
|
fn lowerDeclRef(
|
|
bin_file: *link.File,
|
|
src_loc: Module.SrcLoc,
|
|
typed_value: TypedValue,
|
|
decl: *Module.Decl,
|
|
code: *std.ArrayList(u8),
|
|
debug_output: DebugInfoOutput,
|
|
) GenerateSymbolError!Result {
|
|
if (typed_value.ty.isSlice()) {
|
|
// generate ptr
|
|
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
|
|
const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
|
|
switch (try generateSymbol(bin_file, src_loc, .{
|
|
.ty = slice_ptr_field_type,
|
|
.val = typed_value.val,
|
|
}, code, debug_output)) {
|
|
.appended => {},
|
|
.externally_managed => |external_slice| {
|
|
code.appendSliceAssumeCapacity(external_slice);
|
|
},
|
|
.fail => |em| return Result{ .fail = em },
|
|
}
|
|
|
|
// generate length
|
|
var slice_len: Value.Payload.U64 = .{
|
|
.base = .{ .tag = .int_u64 },
|
|
.data = typed_value.val.sliceLen(),
|
|
};
|
|
switch (try generateSymbol(bin_file, src_loc, .{
|
|
.ty = Type.initTag(.usize),
|
|
.val = Value.initPayload(&slice_len.base),
|
|
}, code, debug_output)) {
|
|
.appended => {},
|
|
.externally_managed => |external_slice| {
|
|
code.appendSliceAssumeCapacity(external_slice);
|
|
},
|
|
.fail => |em| return Result{ .fail = em },
|
|
}
|
|
|
|
return Result{ .appended = {} };
|
|
}
|
|
|
|
if (decl.analysis != .complete) return error.AnalysisFail;
|
|
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 endian = bin_file.options.target.cpu.arch.endian();
|
|
switch (bin_file.options.target.cpu.arch.ptrBitWidth()) {
|
|
16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian),
|
|
32 => mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, vaddr), endian),
|
|
64 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian),
|
|
else => unreachable,
|
|
}
|
|
|
|
return Result{ .appended = {} };
|
|
}
|