mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
riscv: implement slices
This commit is contained in:
parent
350ad90cee
commit
3bf008a3d0
@ -775,14 +775,14 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
|
||||
}
|
||||
|
||||
if (builtin.zig_backend == .stage2_riscv64) {
|
||||
// asm volatile ("ecall"
|
||||
// :
|
||||
// : [number] "{a7}" (64),
|
||||
// [arg1] "{a0}" (1),
|
||||
// [arg2] "{a1}" (@intFromPtr(msg.ptr)),
|
||||
// [arg3] "{a2}" (msg.len),
|
||||
// : "rcx", "r11", "memory"
|
||||
// );
|
||||
asm volatile ("ecall"
|
||||
:
|
||||
: [number] "{a7}" (64),
|
||||
[arg1] "{a0}" (1),
|
||||
[arg2] "{a1}" (@intFromPtr(msg.ptr)),
|
||||
[arg3] "{a2}" (msg.len),
|
||||
: "rcx", "r11", "memory"
|
||||
);
|
||||
std.posix.exit(127);
|
||||
}
|
||||
|
||||
|
@ -122,9 +122,10 @@ const MCValue = union(enum) {
|
||||
/// A pointer-sized integer that fits in a register.
|
||||
/// If the type is a pointer, this is the pointer address in virtual address space.
|
||||
immediate: u64,
|
||||
/// The value is in memory at an address not-yet-allocated by the linker.
|
||||
/// This traditionally corresponds to a relocation emitted in a relocatable object file.
|
||||
/// The value doesn't exist in memory yet.
|
||||
load_symbol: SymbolOffset,
|
||||
/// The address of the memory location not-yet-allocated by the linker.
|
||||
addr_symbol: SymbolOffset,
|
||||
/// The value is in a target-specific register.
|
||||
register: Register,
|
||||
/// The value is split across two registers
|
||||
@ -169,6 +170,7 @@ const MCValue = union(enum) {
|
||||
.indirect,
|
||||
.undef,
|
||||
.load_symbol,
|
||||
.addr_symbol,
|
||||
.air_ref,
|
||||
=> false,
|
||||
|
||||
@ -188,10 +190,14 @@ const MCValue = union(enum) {
|
||||
.immediate,
|
||||
.ptr_stack_offset,
|
||||
.register_offset,
|
||||
.register_pair,
|
||||
.register,
|
||||
.undef,
|
||||
.air_ref,
|
||||
.addr_symbol,
|
||||
=> unreachable, // not in memory
|
||||
|
||||
.load_symbol => |sym_off| .{ .addr_symbol = sym_off },
|
||||
.memory => |addr| .{ .immediate = addr },
|
||||
.stack_offset => |off| .{ .ptr_stack_offset = off },
|
||||
.indirect => |reg_off| switch (reg_off.off) {
|
||||
@ -219,6 +225,7 @@ const MCValue = union(enum) {
|
||||
.ptr_stack_offset => |off| .{ .stack_offset = off },
|
||||
.register => |reg| .{ .indirect = .{ .reg = reg } },
|
||||
.register_offset => |reg_off| .{ .indirect = reg_off },
|
||||
.addr_symbol => |sym_off| .{ .load_symbol = sym_off },
|
||||
};
|
||||
}
|
||||
|
||||
@ -235,6 +242,7 @@ const MCValue = union(enum) {
|
||||
.indirect,
|
||||
.stack_offset,
|
||||
.load_symbol,
|
||||
.addr_symbol,
|
||||
=> switch (off) {
|
||||
0 => mcv,
|
||||
else => unreachable, // not offsettable
|
||||
@ -801,6 +809,43 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
|
||||
try table.ensureUnusedCapacity(self.gpa, additional_count);
|
||||
}
|
||||
|
||||
fn splitType(self: *Self, ty: Type) ![2]Type {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
const classes = mem.sliceTo(&abi.classifySystemV(ty, mod), .none);
|
||||
var parts: [2]Type = undefined;
|
||||
if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
|
||||
part.* = switch (class) {
|
||||
.integer => switch (part_i) {
|
||||
0 => Type.u64,
|
||||
1 => part: {
|
||||
const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?;
|
||||
const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8));
|
||||
break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) {
|
||||
1 => elem_ty,
|
||||
else => |len| try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() }),
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => break,
|
||||
};
|
||||
} else if (parts[0].abiSize(mod) + parts[1].abiSize(mod) == ty.abiSize(mod)) return parts;
|
||||
return std.debug.panic("TODO implement splitType for {}", .{ty.fmt(mod)});
|
||||
}
|
||||
|
||||
fn symbolIndex(self: *Self) !u32 {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
const decl_index = mod.funcOwnerDeclIndex(self.func_index);
|
||||
return switch (self.bin_file.tag) {
|
||||
.elf => blk: {
|
||||
const elf_file = self.bin_file.cast(link.File.Elf).?;
|
||||
const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
|
||||
break :blk atom_index;
|
||||
},
|
||||
else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}),
|
||||
};
|
||||
}
|
||||
|
||||
fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: Alignment) !u32 {
|
||||
self.stack_align = self.stack_align.max(abi_align);
|
||||
// TODO find a free slot instead of always appending
|
||||
@ -1610,40 +1655,41 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
|
||||
fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||
const mcv = try self.resolveInst(ty_op.operand);
|
||||
break :result try self.slicePtr(mcv);
|
||||
const result = result: {
|
||||
const src_mcv = try self.resolveInst(ty_op.operand);
|
||||
if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
|
||||
|
||||
const dst_mcv = try self.allocRegOrMem(inst, true);
|
||||
const dst_ty = self.typeOfIndex(inst);
|
||||
try self.genCopy(dst_ty, dst_mcv, src_mcv);
|
||||
break :result dst_mcv;
|
||||
};
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
|
||||
fn slicePtr(self: *Self, mcv: MCValue) !MCValue {
|
||||
switch (mcv) {
|
||||
.dead, .unreach, .none => unreachable,
|
||||
.register => unreachable, // a slice doesn't fit in one register
|
||||
.stack_offset => |off| {
|
||||
return MCValue{ .stack_offset = off };
|
||||
},
|
||||
.memory => |addr| {
|
||||
return MCValue{ .memory = addr };
|
||||
},
|
||||
else => return self.fail("TODO slicePtr {s}", .{@tagName(mcv)}),
|
||||
}
|
||||
}
|
||||
|
||||
fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||
const ptr_bits = 64;
|
||||
const ptr_bytes = @divExact(ptr_bits, 8);
|
||||
const mcv = try self.resolveInst(ty_op.operand);
|
||||
switch (mcv) {
|
||||
.dead, .unreach, .none => unreachable,
|
||||
.register => unreachable, // a slice doesn't fit in one register
|
||||
const src_mcv = try self.resolveInst(ty_op.operand);
|
||||
switch (src_mcv) {
|
||||
.stack_offset => |off| {
|
||||
break :result MCValue{ .stack_offset = off + ptr_bytes };
|
||||
const len_mcv: MCValue = .{ .stack_offset = off + 8 };
|
||||
if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
|
||||
|
||||
const dst_mcv = try self.allocRegOrMem(inst, true);
|
||||
try self.genCopy(Type.usize, dst_mcv, len_mcv);
|
||||
break :result dst_mcv;
|
||||
},
|
||||
else => return self.fail("TODO airSliceLen for {}", .{mcv}),
|
||||
.register_pair => |pair| {
|
||||
const len_mcv: MCValue = .{ .register = pair[1] };
|
||||
|
||||
if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
|
||||
|
||||
const dst_mcv = try self.allocRegOrMem(inst, true);
|
||||
try self.genCopy(Type.usize, dst_mcv, len_mcv);
|
||||
break :result dst_mcv;
|
||||
},
|
||||
else => return self.fail("TODO airSliceLen for {}", .{src_mcv}),
|
||||
}
|
||||
};
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
@ -1978,6 +2024,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
|
||||
.register,
|
||||
.register_offset,
|
||||
.ptr_stack_offset,
|
||||
.addr_symbol,
|
||||
=> try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),
|
||||
|
||||
.memory,
|
||||
@ -2019,11 +2066,6 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty:
|
||||
|
||||
log.debug("storing {}:{} in {}:{}", .{ value, value_ty.fmt(mod), pointer, ptr_ty.fmt(mod) });
|
||||
|
||||
if (value_ty.isSlice(mod)) {
|
||||
// cheat a bit by loading in two parts
|
||||
|
||||
}
|
||||
|
||||
switch (pointer) {
|
||||
.none => unreachable,
|
||||
.undef => unreachable,
|
||||
@ -2192,7 +2234,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
||||
|
||||
const dst_mcv = switch (src_mcv) {
|
||||
.register => |src_reg| dst: {
|
||||
try self.register_manager.getReg(src_reg, null);
|
||||
self.register_manager.getRegAssumeFree(src_reg, null);
|
||||
break :dst src_mcv;
|
||||
},
|
||||
.register_pair => |pair| dst: {
|
||||
for (pair) |reg| self.register_manager.getRegAssumeFree(reg, null);
|
||||
break :dst src_mcv;
|
||||
},
|
||||
else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}),
|
||||
@ -3056,6 +3102,8 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT
|
||||
|
||||
/// Sets the value without any modifications to register allocation metadata or stack allocation metadata.
|
||||
fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
|
||||
// There isn't anything to store
|
||||
if (dst_mcv == .none) return;
|
||||
|
||||
@ -3066,7 +3114,6 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
|
||||
|
||||
switch (dst_mcv) {
|
||||
.register => |reg| return self.genSetReg(ty, reg, src_mcv),
|
||||
.register_pair => |pair| return self.genSetRegPair(ty, pair, src_mcv),
|
||||
.register_offset => |dst_reg_off| try self.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) {
|
||||
.none,
|
||||
.unreach,
|
||||
@ -3084,7 +3131,47 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
|
||||
}),
|
||||
.stack_offset => |off| return self.genSetStack(ty, off, src_mcv),
|
||||
.memory => |addr| return self.genSetMem(ty, addr, src_mcv),
|
||||
else => return self.fail("TODO: genCopy {s} with {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
|
||||
.register_pair => |dst_regs| {
|
||||
const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) {
|
||||
.register_pair, .memory, .indirect, .stack_offset => null,
|
||||
.load_symbol => src: {
|
||||
const src_addr_reg, const src_addr_lock = try self.allocReg();
|
||||
errdefer self.register_manager.unlockReg(src_addr_lock);
|
||||
|
||||
try self.genSetReg(Type.usize, src_addr_reg, src_mcv.address());
|
||||
break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
|
||||
},
|
||||
.air_ref => |src_ref| return self.genCopy(
|
||||
ty,
|
||||
dst_mcv,
|
||||
try self.resolveInst(src_ref),
|
||||
),
|
||||
else => return self.fail("TODO implement genCopy for {s} of {}", .{
|
||||
@tagName(src_mcv), ty.fmt(mod),
|
||||
}),
|
||||
};
|
||||
defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
|
||||
|
||||
switch (ty.zigTypeTag(mod)) {
|
||||
.Optional => return,
|
||||
else => {},
|
||||
}
|
||||
|
||||
var part_disp: i32 = 0;
|
||||
for (dst_regs, try self.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {
|
||||
try self.genSetReg(dst_ty, dst_reg, switch (src_mcv) {
|
||||
.register_pair => |src_regs| .{ .register = src_regs[part_i] },
|
||||
.memory, .indirect, .stack_offset => src_mcv.address().offset(part_disp).deref(),
|
||||
.load_symbol => .{ .indirect = .{
|
||||
.reg = src_info.?.addr_reg,
|
||||
.off = part_disp,
|
||||
} },
|
||||
else => unreachable,
|
||||
});
|
||||
part_disp += @intCast(dst_ty.abiSize(mod));
|
||||
}
|
||||
},
|
||||
else => return std.debug.panic("TODO: genCopy {s} with {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3168,14 +3255,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_mcv: MCValue) Inner
|
||||
try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset });
|
||||
},
|
||||
.load_symbol => |sym_off| {
|
||||
const atom_index = atom: {
|
||||
const decl_index = mod.funcOwnerDeclIndex(self.func_index);
|
||||
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
|
||||
break :atom atom_index;
|
||||
} else return self.fail("TODO genSetStack for {s}", .{@tagName(self.bin_file.tag)});
|
||||
};
|
||||
const atom_index = try self.symbolIndex();
|
||||
|
||||
// setup the src pointer
|
||||
_ = try self.addInst(.{
|
||||
@ -3443,16 +3523,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
|
||||
.load_symbol => |sym_off| {
|
||||
assert(sym_off.off == 0);
|
||||
|
||||
const decl_index = mod.funcOwnerDeclIndex(self.func_index);
|
||||
const atom_index = try self.symbolIndex();
|
||||
|
||||
const atom_index = switch (self.bin_file.tag) {
|
||||
.elf => blk: {
|
||||
const elf_file = self.bin_file.cast(link.File.Elf).?;
|
||||
const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
|
||||
break :blk atom_index;
|
||||
},
|
||||
else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}),
|
||||
};
|
||||
_ = try self.addInst(.{
|
||||
.tag = .load_symbol,
|
||||
.data = .{
|
||||
@ -3485,27 +3557,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
|
||||
},
|
||||
});
|
||||
},
|
||||
else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
|
||||
}
|
||||
}
|
||||
.addr_symbol => |sym_off| {
|
||||
assert(sym_off.off == 0);
|
||||
|
||||
fn genSetRegPair(self: *Self, ty: Type, pair: [2]Register, src_mcv: MCValue) InnerError!void {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
const abi_size: u32 = @intCast(ty.abiSize(mod));
|
||||
const atom_index = try self.symbolIndex();
|
||||
|
||||
assert(abi_size > 8 and abi_size <= 16); // must fit only fit into two registers
|
||||
|
||||
switch (src_mcv) {
|
||||
.air_ref => |ref| return self.genSetRegPair(ty, pair, try self.resolveInst(ref)),
|
||||
.load_symbol => |sym_off| {
|
||||
_ = sym_off;
|
||||
// return self.fail("TODO: genSetRegPair load_symbol", .{});
|
||||
// commented out just for testing.
|
||||
|
||||
// plan here is to load the address into a temporary register and
|
||||
// copy into the pair.
|
||||
_ = try self.addInst(.{
|
||||
.tag = .load_symbol,
|
||||
.data = .{
|
||||
.payload = try self.addExtra(Mir.LoadSymbolPayload{
|
||||
.register = reg.id(),
|
||||
.atom_index = atom_index,
|
||||
.sym_index = sym_off.sym,
|
||||
}),
|
||||
},
|
||||
});
|
||||
},
|
||||
else => return self.fail("TODO: genSetRegPair {s}", .{@tagName(src_mcv)}),
|
||||
else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,7 +398,7 @@ fn mirPsuedo(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
|
||||
.j => {
|
||||
const offset = @as(i64, @intCast(emit.code_offset_mapping.get(data.inst).?)) - @as(i64, @intCast(emit.code.items.len));
|
||||
try emit.writeInstruction(Instruction.jal(.s0, @intCast(offset)));
|
||||
try emit.writeInstruction(Instruction.jal(.zero, @intCast(offset)));
|
||||
},
|
||||
|
||||
else => unreachable,
|
||||
@ -443,27 +443,40 @@ fn mirLoadSymbol(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const data = emit.mir.extraData(Mir.LoadSymbolPayload, payload).data;
|
||||
const reg = @as(Register, @enumFromInt(data.register));
|
||||
|
||||
const end_offset = @as(u32, @intCast(emit.code.items.len));
|
||||
const start_offset = @as(u32, @intCast(emit.code.items.len));
|
||||
try emit.writeInstruction(Instruction.lui(reg, 0));
|
||||
try emit.writeInstruction(Instruction.lw(reg, 0, reg));
|
||||
|
||||
switch (emit.bin_file.tag) {
|
||||
.elf => {
|
||||
const elf_file = emit.bin_file.cast(link.File.Elf).?;
|
||||
const atom_ptr = elf_file.symbol(data.atom_index).atom(elf_file).?;
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);
|
||||
const sym = elf_file.symbol(sym_index);
|
||||
|
||||
const hi_r_type = @intFromEnum(std.elf.R_RISCV.HI20);
|
||||
var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
|
||||
var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
|
||||
|
||||
if (sym.flags.needs_zig_got) {
|
||||
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
|
||||
|
||||
hi_r_type = Elf.R_ZIG_GOT_HI20;
|
||||
lo_r_type = Elf.R_ZIG_GOT_LO12;
|
||||
|
||||
// we need to deref once if we are getting from zig_got, as itll
|
||||
// reloc an address of the address in the got.
|
||||
try emit.writeInstruction(Instruction.ld(reg, 0, reg));
|
||||
} else {
|
||||
try emit.writeInstruction(Instruction.addi(reg, reg, 0));
|
||||
}
|
||||
|
||||
try atom_ptr.addReloc(elf_file, .{
|
||||
.r_offset = end_offset,
|
||||
.r_offset = start_offset,
|
||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | hi_r_type,
|
||||
.r_addend = 0,
|
||||
});
|
||||
|
||||
const lo_r_type = @intFromEnum(std.elf.R_RISCV.LO12_I);
|
||||
|
||||
try atom_ptr.addReloc(elf_file, .{
|
||||
.r_offset = end_offset + 4,
|
||||
.r_offset = start_offset + 4,
|
||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | lo_r_type,
|
||||
.r_addend = 0,
|
||||
});
|
||||
@ -587,6 +600,7 @@ const bits = @import("bits.zig");
|
||||
const abi = @import("abi.zig");
|
||||
const link = @import("../../link.zig");
|
||||
const Module = @import("../../Module.zig");
|
||||
const Elf = @import("../../link/Elf.zig");
|
||||
const ErrorMsg = Module.ErrorMsg;
|
||||
const assert = std.debug.assert;
|
||||
const Instruction = bits.Instruction;
|
||||
|
@ -118,7 +118,9 @@ pub const Inst = struct {
|
||||
/// function epilogue
|
||||
psuedo_epilogue,
|
||||
|
||||
// TODO: add description
|
||||
/// Loads the address of a value that hasn't yet been allocated in memory.
|
||||
///
|
||||
/// uses the Mir.LoadSymbolPayload payload.
|
||||
load_symbol,
|
||||
|
||||
// TODO: add description
|
||||
|
@ -5,7 +5,7 @@ const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
|
||||
const Type = @import("../../type.zig").Type;
|
||||
const Module = @import("../../Module.zig");
|
||||
|
||||
pub const Class = enum { memory, byval, integer, double_integer, fields };
|
||||
pub const Class = enum { memory, byval, integer, double_integer, fields, none };
|
||||
|
||||
pub fn classifyType(ty: Type, mod: *Module) Class {
|
||||
const target = mod.getTarget();
|
||||
@ -91,6 +91,37 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
|
||||
}
|
||||
}
|
||||
|
||||
/// There are a maximum of 8 possible return slots. Returned values are in
|
||||
/// the beginning of the array; unused slots are filled with .none.
|
||||
pub fn classifySystemV(ty: Type, mod: *Module) [8]Class {
|
||||
const memory_class = [_]Class{
|
||||
.memory, .none, .none, .none,
|
||||
.none, .none, .none, .none,
|
||||
};
|
||||
var result = [1]Class{.none} ** 8;
|
||||
switch (ty.zigTypeTag(mod)) {
|
||||
.Pointer => switch (ty.ptrSize(mod)) {
|
||||
.Slice => {
|
||||
result[0] = .integer;
|
||||
result[1] = .integer;
|
||||
return result;
|
||||
},
|
||||
else => {
|
||||
result[0] = .integer;
|
||||
return result;
|
||||
},
|
||||
},
|
||||
.Optional => {
|
||||
if (ty.isPtrLikeOptional(mod)) {
|
||||
result[0] = .integer;
|
||||
return result;
|
||||
}
|
||||
return memory_class;
|
||||
},
|
||||
else => return result,
|
||||
}
|
||||
}
|
||||
|
||||
pub const callee_preserved_regs = [_]Register{
|
||||
.s0, .s1, .s2, .s3, .s4, .s5, .s6, .s7, .s8, .s9, .s10, .s11,
|
||||
};
|
||||
|
@ -11132,6 +11132,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
|
||||
}
|
||||
return o.builder.structType(.normal, types[0..types_len]);
|
||||
},
|
||||
.none => unreachable,
|
||||
}
|
||||
},
|
||||
// TODO investigate C ABI for other architectures
|
||||
@ -11389,6 +11390,7 @@ const ParamTypeIterator = struct {
|
||||
it.llvm_index += it.types_len - 1;
|
||||
return .multiple_llvm_types;
|
||||
},
|
||||
.none => unreachable,
|
||||
}
|
||||
},
|
||||
// TODO investigate C ABI for other architectures
|
||||
|
@ -6409,6 +6409,8 @@ const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
|
||||
// TODO: add comptime check we don't clobber any reloc for any ISA
|
||||
pub const R_ZIG_GOT32: u32 = 0xff00;
|
||||
pub const R_ZIG_GOTPCREL: u32 = 0xff01;
|
||||
pub const R_ZIG_GOT_HI20: u32 = 0xff02;
|
||||
pub const R_ZIG_GOT_LO12: u32 = 0xff03;
|
||||
|
||||
fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
|
||||
return switch (cpu_arch) {
|
||||
|
@ -2025,7 +2025,15 @@ const riscv = struct {
|
||||
.SUB32,
|
||||
=> {},
|
||||
|
||||
else => try atom.reportUnhandledRelocError(rel, elf_file),
|
||||
else => |x| switch (@intFromEnum(x)) {
|
||||
Elf.R_ZIG_GOT_HI20,
|
||||
Elf.R_ZIG_GOT_LO12,
|
||||
=> {
|
||||
assert(symbol.flags.has_zig_got);
|
||||
},
|
||||
|
||||
else => try atom.reportUnhandledRelocError(rel, elf_file),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -2046,7 +2054,6 @@ const riscv = struct {
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
|
||||
_ = TP;
|
||||
_ = DTP;
|
||||
_ = ZIG_GOT;
|
||||
|
||||
switch (r_type) {
|
||||
.NONE => unreachable,
|
||||
@ -2136,7 +2143,22 @@ const riscv = struct {
|
||||
}
|
||||
},
|
||||
|
||||
else => try atom.reportUnhandledRelocError(rel, elf_file),
|
||||
else => |x| switch (@intFromEnum(x)) {
|
||||
// Zig custom relocations
|
||||
Elf.R_ZIG_GOT_HI20 => {
|
||||
assert(target.flags.has_zig_got);
|
||||
const disp: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow);
|
||||
riscv_util.writeInstU(code[r_offset..][0..4], disp);
|
||||
},
|
||||
|
||||
Elf.R_ZIG_GOT_LO12 => {
|
||||
assert(target.flags.has_zig_got);
|
||||
const value: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow);
|
||||
riscv_util.writeInstI(code[r_offset..][0..4], value);
|
||||
},
|
||||
|
||||
else => try atom.reportUnhandledRelocError(rel, elf_file),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user