Implement legalize_signature for RISC-V.

Add an abi module with code that is probably useful to all ISAs when
implementing this function.

Add a unit() method to RegClassData which can be used to index the
register units in a class.
This commit is contained in:
Jakob Stoklund Olesen
2017-03-02 16:01:56 -08:00
parent 07f459fb93
commit 42e7021865
7 changed files with 180 additions and 4 deletions

View File

@@ -108,6 +108,9 @@ pub struct RegClassData {
/// How many register units to allocate per register.
pub width: u8,
/// The first register unit in this class.
pub first: RegUnit,
/// Bit-mask of sub-classes of this register class, including itself.
///
/// Bits correspond to RC indexes.
@@ -142,6 +145,12 @@ impl RegClassData {
pub fn has_subclass<RCI: Into<RegClassIndex>>(&self, other: RCI) -> bool {
self.subclasses & (1 << other.into().0) != 0
}
/// Get a specific register unit in this class.
pub fn unit(&self, offset: usize) -> RegUnit {
let uoffset = offset * self.width as usize;
self.first + uoffset as RegUnit
}
}
/// A small reference to a register class.

View File

@@ -2,11 +2,79 @@
//!
//! This module implements the RISC-V calling convention through the primary `legalize_signature()`
//! entry point.
//!
//! This doesn't support the soft-float ABI at the moment.
use ir::Signature;
use abi::{ArgAction, ArgAssigner, legalize_args};
use ir::{Signature, ArgumentType, ArgumentLoc};
use isa::riscv::registers::{GPR, FPR};
use settings as shared_settings;
/// Legalize `sig` for RISC-V.
pub fn legalize_signature(_sig: &mut Signature, _flags: &shared_settings::Flags) {
// TODO: Actually do something.
struct Args {
pointer_bits: u16,
pointer_bytes: u32,
regs: u32,
offset: u32,
}
impl Args {
fn new(bits: u16) -> Args {
Args {
pointer_bits: bits,
pointer_bytes: bits as u32 / 8,
regs: 0,
offset: 0,
}
}
}
impl ArgAssigner for Args {
fn assign(&mut self, arg: &ArgumentType) -> ArgAction {
fn align(value: u32, to: u32) -> u32 {
(value + to - 1) & !(to - 1)
}
let ty = arg.value_type;
// Check for a legal type.
// RISC-V doesn't have SIMD at all, so break all vectors down.
if !ty.is_scalar() {
return ArgAction::Split;
}
// Large integers and booleans are broken down to fit in a register.
if !ty.is_float() && ty.bits() > self.pointer_bits {
// Align registers and stack to a multiple of two pointers.
self.regs = align(self.regs, 2);
self.offset = align(self.offset, 2 * self.pointer_bytes);
return ArgAction::Split;
}
if self.regs < 8 {
// Assign to a register.
let reg = if ty.is_float() {
FPR.unit(10 + self.regs as usize)
} else {
GPR.unit(10 + self.regs as usize)
};
self.regs += 1;
ArgAction::Assign(ArgumentLoc::Reg(reg))
} else {
// Assign a stack location.
let loc = ArgumentLoc::Stack(self.offset);
self.offset += self.pointer_bytes;
ArgAction::Assign(loc)
}
}
}
/// Legalize `sig` for RISC-V.
pub fn legalize_signature(sig: &mut Signature, flags: &shared_settings::Flags) {
let bits = if flags.is_64bit() { 64 } else { 32 };
let mut args = Args::new(bits);
legalize_args(&mut sig.argument_types, &mut args);
let mut rets = Args::new(bits);
legalize_args(&mut sig.return_types, &mut rets);
}