Multi-value return support.

This commit is contained in:
Chris Fallin
2020-05-27 14:01:49 -07:00
parent 34eb170232
commit 615362068f
10 changed files with 269 additions and 56 deletions

View File

@@ -12,6 +12,12 @@ pub trait ABIBody {
/// The instruction type for the ISA associated with this ABI.
type I: VCodeInst;
/// How many temps are needed?
fn needed_tmps(&self) -> usize;
/// Initialize, providing the requersted temps.
fn init_with_tmps(&mut self, tmps: &[Writable<Reg>]);
/// Get the settings controlling this function's compilation.
fn flags(&self) -> &settings::Flags;
@@ -34,6 +40,13 @@ pub trait ABIBody {
/// register.
fn gen_copy_arg_to_reg(&self, idx: usize, into_reg: Writable<Reg>) -> Self::I;
/// Generate any setup instructions needed to save values to the
/// return-value area. This is usually used when were are multiple return
/// values or an otherwise large return value that must be passed on the
/// stack; typically the ABI specifies an extra hidden argument that is a
/// pointer to that memory.
fn gen_retval_area_setup(&self) -> Vec<Self::I>;
/// Generate an instruction which copies a source register to a return value slot.
fn gen_copy_reg_to_retval(
&self,

View File

@@ -6,6 +6,7 @@ use crate::entity::SecondaryMap;
use crate::fx::{FxHashMap, FxHashSet};
use crate::inst_predicates::{has_side_effect_or_load, is_constant_64bit};
use crate::ir::instructions::BranchInfo;
use crate::ir::types::I64;
use crate::ir::{
ArgumentExtension, Block, Constant, ConstantData, ExternalName, Function, GlobalValueData,
Inst, InstructionData, MemFlags, Opcode, Signature, SourceLoc, Type, Value, ValueDef,
@@ -382,6 +383,9 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
let insn = self.vcode.abi().gen_copy_arg_to_reg(i, reg);
self.emit(insn);
}
for insn in self.vcode.abi().gen_retval_area_setup().into_iter() {
self.emit(insn);
}
}
}
@@ -648,6 +652,12 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
pub fn lower<B: LowerBackend<MInst = I>>(mut self, backend: &B) -> CodegenResult<VCode<I>> {
debug!("about to lower function: {:?}", self.f);
// Initialize the ABI object with any temps it needs.
let tmps: SmallVec<[Writable<Reg>; 4]> = (0..self.vcode.abi().needed_tmps())
.map(|_| self.alloc_tmp(RegClass::I64, I64))
.collect();
self.vcode.abi().init_with_tmps(&tmps[..]);
// Get the pinned reg here (we only parameterize this function on `B`,
// not the whole `Lower` impl).
self.pinned_reg = backend.maybe_pinned_reg();