aboutsummaryrefslogtreecommitdiff
path: root/src/arch/riscv64/CodeGen.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/riscv64/CodeGen.zig')
-rw-r--r--src/arch/riscv64/CodeGen.zig207
1 files changed, 110 insertions, 97 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index d4c7eb0c70..c6ac3255c6 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -217,7 +217,7 @@ const Self = @This();
pub fn generate(
bin_file: *link.File,
src_loc: Module.SrcLoc,
- module_fn: *Module.Fn,
+ module_fn_index: Module.Fn.Index,
air: Air,
liveness: Liveness,
code: *std.ArrayList(u8),
@@ -228,6 +228,7 @@ pub fn generate(
}
const mod = bin_file.options.module.?;
+ const module_fn = mod.funcPtr(module_fn_index);
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
assert(fn_owner_decl.has_tv);
const fn_type = fn_owner_decl.ty;
@@ -347,7 +348,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
}
fn gen(self: *Self) !void {
- const cc = self.fn_type.fnCallingConvention();
+ const mod = self.bin_file.options.module.?;
+ const cc = self.fn_type.fnCallingConvention(mod);
if (cc != .Naked) {
// TODO Finish function prologue and epilogue for riscv64.
@@ -470,13 +472,14 @@ fn gen(self: *Self) !void {
}
fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
+ const mod = self.bin_file.options.module.?;
+ const ip = &mod.intern_pool;
const air_tags = self.air.instructions.items(.tag);
for (body) |inst| {
// TODO: remove now-redundant isUnused calls from AIR handler functions
- if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
+ if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
continue;
- }
const old_air_bookkeeping = self.air_bookkeeping;
try self.ensureProcessDeathCapacity(Liveness.bpi);
@@ -656,8 +659,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.ptr_elem_val => try self.airPtrElemVal(inst),
.ptr_elem_ptr => try self.airPtrElemPtr(inst),
- .constant => unreachable, // excluded from function bodies
- .const_ty => unreachable, // excluded from function bodies
+ .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
.unreach => self.finishAirBookkeeping(),
.optional_payload => try self.airOptionalPayload(inst),
@@ -727,8 +729,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
/// Asserts there is already capacity to insert into top branch inst_table.
fn processDeath(self: *Self, inst: Air.Inst.Index) void {
- const air_tags = self.air.instructions.items(.tag);
- if (air_tags[inst] == .constant) return; // Constants are immortal.
+ assert(self.air.instructions.items(.tag)[inst] != .interned);
// When editing this function, note that the logic must synchronize with `reuseOperand`.
const prev_value = self.getResolvedInstValue(inst);
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
@@ -755,8 +756,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
tomb_bits >>= 1;
if (!dies) continue;
const op_int = @enumToInt(op);
- if (op_int < Air.Inst.Ref.typed_value_map.len) continue;
- const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
+ if (op_int < Air.ref_start_index) continue;
+ const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
self.processDeath(op_index);
}
const is_used = @truncate(u1, tomb_bits) == 0;
@@ -791,7 +792,7 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
if (abi_align > self.stack_align)
self.stack_align = abi_align;
// TODO find a free slot instead of always appending
- const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align);
+ const offset = mem.alignForward(u32, self.next_stack_offset, abi_align);
self.next_stack_offset = offset + abi_size;
if (self.next_stack_offset > self.max_end_stack)
self.max_end_stack = self.next_stack_offset;
@@ -804,29 +805,29 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
/// Use a pointer instruction as the basis for allocating stack memory.
fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
- const elem_ty = self.air.typeOfIndex(inst).elemType();
- const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
- const mod = self.bin_file.options.module.?;
+ const mod = self.bin_file.options.module.?;
+ const elem_ty = self.typeOfIndex(inst).childType(mod);
+ const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
};
// TODO swap this for inst.ty.ptrAlign
- const abi_align = elem_ty.abiAlignment(self.target.*);
+ const abi_align = elem_ty.abiAlignment(mod);
return self.allocMem(inst, abi_size, abi_align);
}
fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
- const elem_ty = self.air.typeOfIndex(inst);
- const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
- const mod = self.bin_file.options.module.?;
+ const mod = self.bin_file.options.module.?;
+ const elem_ty = self.typeOfIndex(inst);
+ const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
};
- const abi_align = elem_ty.abiAlignment(self.target.*);
+ const abi_align = elem_ty.abiAlignment(mod);
if (abi_align > self.stack_align)
self.stack_align = abi_align;
if (reg_ok) {
// Make sure the type can fit in a register before we try to allocate one.
- const ptr_bits = self.target.cpu.arch.ptrBitWidth();
+ const ptr_bits = self.target.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
if (abi_size <= ptr_bytes) {
if (self.register_manager.tryAllocReg(inst, gp)) |reg| {
@@ -845,7 +846,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
assert(reg == reg_mcv.register);
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
try branch.inst_table.put(self.gpa, inst, stack_mcv);
- try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
+ try self.genSetStack(self.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
}
/// Copies a value to a register without tracking the register. The register is not considered
@@ -862,7 +863,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
const reg = try self.register_manager.allocReg(reg_owner, gp);
- try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
+ try self.genSetReg(self.typeOfIndex(reg_owner), reg, mcv);
return MCValue{ .register = reg };
}
@@ -893,10 +894,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
if (self.liveness.isUnused(inst))
return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
- const operand_ty = self.air.typeOf(ty_op.operand);
+ const mod = self.bin_file.options.module.?;
+ const operand_ty = self.typeOf(ty_op.operand);
const operand = try self.resolveInst(ty_op.operand);
- const info_a = operand_ty.intInfo(self.target.*);
- const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);
+ const info_a = operand_ty.intInfo(mod);
+ const info_b = self.typeOfIndex(inst).intInfo(mod);
if (info_a.signedness != info_b.signedness)
return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
@@ -1068,18 +1070,18 @@ fn binOp(
lhs_ty: Type,
rhs_ty: Type,
) InnerError!MCValue {
+ const mod = self.bin_file.options.module.?;
switch (tag) {
// Arithmetic operations on integers and floats
.add,
.sub,
=> {
- switch (lhs_ty.zigTypeTag()) {
+ switch (lhs_ty.zigTypeTag(mod)) {
.Float => return self.fail("TODO binary operations on floats", .{}),
.Vector => return self.fail("TODO binary operations on vectors", .{}),
.Int => {
- const mod = self.bin_file.options.module.?;
assert(lhs_ty.eql(rhs_ty, mod));
- const int_info = lhs_ty.intInfo(self.target.*);
+ const int_info = lhs_ty.intInfo(mod);
if (int_info.bits <= 64) {
// TODO immediate operands
return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
@@ -1093,14 +1095,14 @@ fn binOp(
.ptr_add,
.ptr_sub,
=> {
- switch (lhs_ty.zigTypeTag()) {
+ switch (lhs_ty.zigTypeTag(mod)) {
.Pointer => {
const ptr_ty = lhs_ty;
- const elem_ty = switch (ptr_ty.ptrSize()) {
- .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
- else => ptr_ty.childType(),
+ const elem_ty = switch (ptr_ty.ptrSize(mod)) {
+ .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
+ else => ptr_ty.childType(mod),
};
- const elem_size = elem_ty.abiSize(self.target.*);
+ const elem_size = elem_ty.abiSize(mod);
if (elem_size == 1) {
const base_tag: Air.Inst.Tag = switch (tag) {
@@ -1125,8 +1127,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
- const lhs_ty = self.air.typeOf(bin_op.lhs);
- const rhs_ty = self.air.typeOf(bin_op.rhs);
+ const lhs_ty = self.typeOf(bin_op.lhs);
+ const rhs_ty = self.typeOf(bin_op.rhs);
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
@@ -1137,8 +1139,8 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
const lhs = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
- const lhs_ty = self.air.typeOf(bin_op.lhs);
- const rhs_ty = self.air.typeOf(bin_op.rhs);
+ const lhs_ty = self.typeOf(bin_op.lhs);
+ const rhs_ty = self.typeOf(bin_op.rhs);
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
@@ -1331,10 +1333,11 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
- const optional_ty = self.air.typeOfIndex(inst);
+ const mod = self.bin_file.options.module.?;
+ const optional_ty = self.typeOfIndex(inst);
// Optional with a zero-bit payload type is just a boolean true
- if (optional_ty.abiSize(self.target.*) == 1)
+ if (optional_ty.abiSize(mod) == 1)
break :result MCValue{ .immediate = 1 };
return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});
@@ -1498,7 +1501,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
}
fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
- const elem_ty = ptr_ty.elemType();
+ const mod = self.bin_file.options.module.?;
+ const elem_ty = ptr_ty.childType(mod);
switch (ptr) {
.none => unreachable,
.undef => unreachable,
@@ -1523,14 +1527,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
}
fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
+ const mod = self.bin_file.options.module.?;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const elem_ty = self.air.typeOfIndex(inst);
+ const elem_ty = self.typeOfIndex(inst);
const result: MCValue = result: {
- if (!elem_ty.hasRuntimeBits())
+ if (!elem_ty.hasRuntimeBits(mod))
break :result MCValue.none;
const ptr = try self.resolveInst(ty_op.operand);
- const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr();
+ const is_volatile = self.typeOf(ty_op.operand).isVolatilePtr(mod);
if (self.liveness.isUnused(inst) and !is_volatile)
break :result MCValue.dead;
@@ -1542,7 +1547,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
break :blk try self.allocRegOrMem(inst, true);
}
};
- try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand));
+ try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));
break :result dst_mcv;
};
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
@@ -1583,8 +1588,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const ptr = try self.resolveInst(bin_op.lhs);
const value = try self.resolveInst(bin_op.rhs);
- const ptr_ty = self.air.typeOf(bin_op.lhs);
- const value_ty = self.air.typeOf(bin_op.rhs);
+ const ptr_ty = self.typeOf(bin_op.lhs);
+ const value_ty = self.typeOf(bin_op.rhs);
try self.store(ptr, value, ptr_ty, value_ty);
@@ -1644,7 +1649,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
const arg_index = self.arg_index;
self.arg_index += 1;
- const ty = self.air.typeOfIndex(inst);
+ const ty = self.typeOfIndex(inst);
_ = ty;
const result = self.args[arg_index];
@@ -1698,9 +1703,10 @@ fn airFence(self: *Self) !void {
}
fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
+ const mod = self.bin_file.options.module.?;
if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{});
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
- const fn_ty = self.air.typeOf(pl_op.operand);
+ const fn_ty = self.typeOf(pl_op.operand);
const callee = pl_op.operand;
const extra = self.air.extraData(Air.Call, pl_op.payload);
const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
@@ -1713,7 +1719,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
for (info.args, 0..) |mc_arg, arg_i| {
const arg = args[arg_i];
- const arg_ty = self.air.typeOf(arg);
+ const arg_ty = self.typeOf(arg);
const arg_mcv = try self.resolveInst(args[arg_i]);
switch (mc_arg) {
@@ -1736,14 +1742,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
}
}
- if (self.air.value(callee)) |func_value| {
- if (func_value.castTag(.function)) |func_payload| {
- const func = func_payload.data;
+ if (try self.air.value(callee, mod)) |func_value| {
+ if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
const atom = elf_file.getAtom(atom_index);
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
const got_addr = @intCast(u32, atom.getOffsetTableAddress(elf_file));
- try self.genSetReg(Type.initTag(.usize), .ra, .{ .memory = got_addr });
+ try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
_ = try self.addInst(.{
.tag = .jalr,
.data = .{ .i_type = .{
@@ -1752,7 +1757,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
.imm12 = 0,
} },
});
- } else if (func_value.castTag(.extern_fn)) |_| {
+ } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
return self.fail("TODO implement calling extern functions", .{});
} else {
return self.fail("TODO implement calling bitcasted functions", .{});
@@ -1796,7 +1801,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
}
fn ret(self: *Self, mcv: MCValue) !void {
- const ret_ty = self.fn_type.fnReturnType();
+ const mod = self.bin_file.options.module.?;
+ const ret_ty = self.fn_type.fnReturnType(mod);
try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
// Just add space for an instruction, patch this later
const index = try self.addInst(.{
@@ -1825,10 +1831,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
if (self.liveness.isUnused(inst))
return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
- const ty = self.air.typeOf(bin_op.lhs);
+ const ty = self.typeOf(bin_op.lhs);
const mod = self.bin_file.options.module.?;
- assert(ty.eql(self.air.typeOf(bin_op.rhs), mod));
- if (ty.zigTypeTag() == .ErrorSet)
+ assert(ty.eql(self.typeOf(bin_op.rhs), mod));
+ if (ty.zigTypeTag(mod) == .ErrorSet)
return self.fail("TODO implement cmp for errors", .{});
const lhs = try self.resolveInst(bin_op.lhs);
@@ -1869,8 +1875,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
}
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
- const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
- const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
+ const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
+ const mod = self.bin_file.options.module.?;
+ const function = mod.funcPtr(ty_fn.func);
// TODO emit debug info for function change
_ = function;
return self.finishAir(inst, .dead, .{ .none, .none, .none });
@@ -1946,7 +1953,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
break :blk try self.allocRegOrMem(inst, true);
}
};
- try self.load(operand, operand_ptr, self.air.typeOf(un_op));
+ try self.load(operand, operand_ptr, self.typeOf(un_op));
break :result try self.isNull(operand);
};
return self.finishAir(inst, result, .{ un_op, .none, .none });
@@ -1973,7 +1980,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
break :blk try self.allocRegOrMem(inst, true);
}
};
- try self.load(operand, operand_ptr, self.air.typeOf(un_op));
+ try self.load(operand, operand_ptr, self.typeOf(un_op));
break :result try self.isNonNull(operand);
};
return self.finishAir(inst, result, .{ un_op, .none, .none });
@@ -2000,7 +2007,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
break :blk try self.allocRegOrMem(inst, true);
}
};
- try self.load(operand, operand_ptr, self.air.typeOf(un_op));
+ try self.load(operand, operand_ptr, self.typeOf(un_op));
break :result try self.isErr(operand);
};
return self.finishAir(inst, result, .{ un_op, .none, .none });
@@ -2027,7 +2034,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
break :blk try self.allocRegOrMem(inst, true);
}
};
- try self.load(operand, operand_ptr, self.air.typeOf(un_op));
+ try self.load(operand, operand_ptr, self.typeOf(un_op));
break :result try self.isNonErr(operand);
};
return self.finishAir(inst, result, .{ un_op, .none, .none });
@@ -2107,13 +2114,14 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
const block_data = self.blocks.getPtr(block).?;
- if (self.air.typeOf(operand).hasRuntimeBits()) {
+ const mod = self.bin_file.options.module.?;
+ if (self.typeOf(operand).hasRuntimeBits(mod)) {
const operand_mcv = try self.resolveInst(operand);
const block_mcv = block_data.mcv;
if (block_mcv == .none) {
block_data.mcv = operand_mcv;
} else {
- try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
+ try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
}
}
return self.brVoid(block);
@@ -2176,7 +2184,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
const arg_mcv = try self.resolveInst(input);
try self.register_manager.getReg(reg, null);
- try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
+ try self.genSetReg(self.typeOf(input), reg, arg_mcv);
}
{
@@ -2372,7 +2380,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
const dest = try self.allocRegOrMem(inst, true);
- try self.setRegOrMem(self.air.typeOfIndex(inst), dest, operand);
+ try self.setRegOrMem(self.typeOfIndex(inst), dest, operand);
break :result dest;
};
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
@@ -2489,8 +2497,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
}
fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
- const vector_ty = self.air.typeOfIndex(inst);
- const len = vector_ty.vectorLen();
+ const mod = self.bin_file.options.module.?;
+ const vector_ty = self.typeOfIndex(inst);
+ const len = vector_ty.vectorLen(mod);
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
const result: MCValue = res: {
@@ -2533,37 +2542,32 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
}
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
- // First section of indexes correspond to a set number of constant values.
- const ref_int = @enumToInt(inst);
- if (ref_int < Air.Inst.Ref.typed_value_map.len) {
- const tv = Air.Inst.Ref.typed_value_map[ref_int];
- if (!tv.ty.hasRuntimeBits()) {
- return MCValue{ .none = {} };
- }
- return self.genTypedValue(tv);
- }
+ const mod = self.bin_file.options.module.?;
// If the type has no codegen bits, no need to store it.
- const inst_ty = self.air.typeOf(inst);
- if (!inst_ty.hasRuntimeBits())
+ const inst_ty = self.typeOf(inst);
+ if (!inst_ty.hasRuntimeBits(mod))
return MCValue{ .none = {} };
- const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
+ const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
+ .ty = inst_ty,
+ .val = (try self.air.value(inst, mod)).?,
+ });
+
switch (self.air.instructions.items(.tag)[inst_index]) {
- .constant => {
+ .interned => {
// Constants have static lifetimes, so they are always memoized in the outer most table.
const branch = &self.branch_stack.items[0];
const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
if (!gop.found_existing) {
- const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl;
+ const interned = self.air.instructions.items(.data)[inst_index].interned;
gop.value_ptr.* = try self.genTypedValue(.{
.ty = inst_ty,
- .val = self.air.values[ty_pl.payload],
+ .val = interned.toValue(),
});
}
return gop.value_ptr.*;
},
- .const_ty => unreachable,
else => return self.getResolvedInstValue(inst_index),
}
}
@@ -2616,12 +2620,11 @@ const CallMCValues = struct {
/// Caller must call `CallMCValues.deinit`.
fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
- const cc = fn_ty.fnCallingConvention();
- const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
- defer self.gpa.free(param_types);
- fn_ty.fnParamTypes(param_types);
+ const mod = self.bin_file.options.module.?;
+ const fn_info = mod.typeToFunc(fn_ty).?;
+ const cc = fn_info.cc;
var result: CallMCValues = .{
- .args = try self.gpa.alloc(MCValue, param_types.len),
+ .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
// These undefined values must be populated before returning from this function.
.return_value = undefined,
.stack_byte_count = undefined,
@@ -2629,7 +2632,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
};
errdefer self.gpa.free(result.args);
- const ret_ty = fn_ty.fnReturnType();
+ const ret_ty = fn_ty.fnReturnType(mod);
switch (cc) {
.Naked => {
@@ -2649,8 +2652,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
var next_stack_offset: u32 = 0;
const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
- for (param_types, 0..) |ty, i| {
- const param_size = @intCast(u32, ty.abiSize(self.target.*));
+ for (fn_info.param_types, 0..) |ty, i| {
+ const param_size = @intCast(u32, ty.toType().abiSize(mod));
if (param_size <= 8) {
if (next_register < argument_registers.len) {
result.args[i] = .{ .register = argument_registers[next_register] };
@@ -2680,14 +2683,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}),
}
- if (ret_ty.zigTypeTag() == .NoReturn) {
+ if (ret_ty.zigTypeTag(mod) == .NoReturn) {
result.return_value = .{ .unreach = {} };
- } else if (!ret_ty.hasRuntimeBits()) {
+ } else if (!ret_ty.hasRuntimeBits(mod)) {
result.return_value = .{ .none = {} };
} else switch (cc) {
.Naked => unreachable,
.Unspecified, .C => {
- const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
+ const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
if (ret_ty_size <= 8) {
result.return_value = .{ .register = .a0 };
} else if (ret_ty_size <= 16) {
@@ -2731,3 +2734,13 @@ fn parseRegName(name: []const u8) ?Register {
}
return std.meta.stringToEnum(Register, name);
}
+
+fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
+ const mod = self.bin_file.options.module.?;
+ return self.air.typeOf(inst, &mod.intern_pool);
+}
+
+fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
+ const mod = self.bin_file.options.module.?;
+ return self.air.typeOfIndex(inst, &mod.intern_pool);
+}