Skip to content

Commit

Permalink
improvement(compiler) Added basic arm64 declaration for singlepass
Browse files Browse the repository at this point in the history
  • Loading branch information
ptitSeb committed Jan 14, 2022
1 parent 8c9a2a0 commit 1e1032e
Show file tree
Hide file tree
Showing 4 changed files with 295 additions and 34 deletions.
294 changes: 294 additions & 0 deletions lib/compiler-singlepass/src/arm64_decl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
//! ARM64 structures.
use crate::common_decl::{MachineState, MachineValue, RegisterIndex};
use crate::location::CombinedRegister;
use crate::location::Reg as AbstractReg;
use std::collections::BTreeMap;
use wasmer_compiler::CallingConvention;
use wasmer_types::Type;

/// General-purpose registers.
#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum GPR {
X0 = 0,
X1 = 1,
X2 = 2,
X3 = 3,
X4 = 4,
X5 = 5,
X6 = 6,
X7 = 7,
X8 = 8,
X9 = 9,
X10 = 10,
X11 = 11,
X12 = 12,
X13 = 13,
X14 = 14,
X15 = 15,
X16 = 16,
X17 = 17,
X18 = 18,
X19 = 19,
X20 = 20,
X21 = 21,
X22 = 22,
X23 = 23,
X24 = 24,
X25 = 25,
X26 = 26,
X27 = 27,
X28 = 28,
X29 = 29,
X30 = 30,
XzrSp = 31,
}

/// NEON registers.
#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[allow(dead_code)]
pub enum NEON {
V0 = 0,
V1 = 1,
V2 = 2,
V3 = 3,
V4 = 4,
V5 = 5,
V6 = 6,
V7 = 7,
V8 = 8,
V9 = 9,
V10 = 10,
V11 = 11,
V12 = 12,
V13 = 13,
V14 = 14,
V15 = 15,
V16 = 16,
V17 = 17,
V18 = 18,
V19 = 19,
V20 = 20,
V21 = 21,
V22 = 22,
V23 = 23,
V24 = 24,
V25 = 25,
V26 = 26,
V27 = 27,
V28 = 28,
V29 = 29,
V30 = 30,
V31 = 31,
}

impl AbstractReg for GPR {
fn is_callee_save(self) -> bool {
self as usize > 18
}
fn is_reserved(self) -> bool {
match self.into_index() {
0..=16 | 19..=27 => false,
_ => true,
}
}
fn into_index(self) -> usize {
self as usize
}
fn from_index(n: usize) -> Result<GPR, ()> {
const REGS: [GPR; 32] = [
GPR::X0,
GPR::X1,
GPR::X2,
GPR::X3,
GPR::X4,
GPR::X5,
GPR::X6,
GPR::X7,
GPR::X8,
GPR::X9,
GPR::X10,
GPR::X11,
GPR::X12,
GPR::X13,
GPR::X14,
GPR::X15,
GPR::X16,
GPR::X17,
GPR::X18,
GPR::X19,
GPR::X20,
GPR::X21,
GPR::X22,
GPR::X23,
GPR::X24,
GPR::X25,
GPR::X26,
GPR::X27,
GPR::X28,
GPR::X29,
GPR::X30,
GPR::XzrSp,
];
match n {
0..=31 => Ok(REGS[n]),
_ => Err(()),
}
}
}

impl AbstractReg for NEON {
fn is_callee_save(self) -> bool {
self as usize > 16
}
fn is_reserved(self) -> bool {
false
}
fn into_index(self) -> usize {
self as usize
}
fn from_index(n: usize) -> Result<NEON, ()> {
const REGS: [NEON; 32] = [
NEON::V0,
NEON::V1,
NEON::V2,
NEON::V3,
NEON::V4,
NEON::V5,
NEON::V6,
NEON::V7,
NEON::V8,
NEON::V9,
NEON::V10,
NEON::V11,
NEON::V12,
NEON::V13,
NEON::V14,
NEON::V15,
NEON::V16,
NEON::V17,
NEON::V18,
NEON::V19,
NEON::V20,
NEON::V21,
NEON::V22,
NEON::V23,
NEON::V24,
NEON::V25,
NEON::V26,
NEON::V27,
NEON::V28,
NEON::V29,
NEON::V30,
NEON::V31,

];
match n {
0..=15 => Ok(REGS[n]),
_ => Err(()),
}
}
}

/// A machine register under the x86-64 architecture.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ARM64Register {
/// General-purpose registers.
GPR(GPR),
/// NEON (floating point/SIMD) registers.
NEON(NEON),
}

impl CombinedRegister for ARM64Register {
/// Returns the index of the register.
fn to_index(&self) -> RegisterIndex {
match *self {
ARM64Register::GPR(x) => RegisterIndex(x as usize),
ARM64Register::NEON(x) => RegisterIndex(x as usize + 64),
}
}
/// Convert from a GPR register
fn from_gpr(x: u16) -> Self {
ARM64Register::GPR(GPR::from_index(x as usize).unwrap())
}
/// Convert from an SIMD register
fn from_simd(x: u16) -> Self {
ARM64Register::NEON(NEON::from_index(x as usize).unwrap())
}

/// Converts a DWARF regnum to ARM64Register.
fn _from_dwarf_regnum(x: u16) -> Option<ARM64Register> {
Some(match x {
0..=31 => ARM64Register::GPR(GPR::from_index(x as usize).unwrap()),
64..=95 => ARM64Register::NEON(NEON::from_index(x as usize - 64).unwrap()),
_ => return None,
})
}
}

/// An allocator that allocates registers for function arguments according to the System V ABI.
#[derive(Default)]
pub struct ArgumentRegisterAllocator {
n_gprs: usize,
n_neons: usize,
}

impl ArgumentRegisterAllocator {
/// Allocates a register for argument type `ty`. Returns `None` if no register is available for this type.
pub fn next(&mut self, ty: Type, calling_convention: CallingConvention) -> Option<ARM64Register> {
match calling_convention {
CallingConvention::SystemV => {
static GPR_SEQ: &'static [GPR] =
&[GPR::X0, GPR::X1, GPR::X2, GPR::X3, GPR::X4, GPR::X5, GPR::X6, GPR::X7];
static NEON_SEQ: &'static [NEON] = &[
NEON::V0,
NEON::V1,
NEON::V2,
NEON::V3,
NEON::V4,
NEON::V5,
NEON::V6,
NEON::V7,
];
match ty {
Type::I32 | Type::I64 => {
if self.n_gprs < GPR_SEQ.len() {
let gpr = GPR_SEQ[self.n_gprs];
self.n_gprs += 1;
Some(ARM64Register::GPR(gpr))
} else {
None
}
}
Type::F32 | Type::F64 => {
if self.n_neons < NEON_SEQ.len() {
let neon = NEON_SEQ[self.n_neons];
self.n_neons += 1;
Some(ARM64Register::NEON(neon))
} else {
None
}
}
_ => todo!(
"ArgumentRegisterAllocator::next: Unsupported type: {:?}",
ty
),
}
}
_ => unimplemented!(),
}
}
}

/// Create a new `MachineState` with default values.
pub fn new_machine_state() -> MachineState {
MachineState {
stack_values: vec![],
register_values: vec![MachineValue::Undefined; 32 + 32],
prev_frame: BTreeMap::new(),
wasm_stack: vec![],
wasm_inst_offset: std::usize::MAX,
}
}
1 change: 1 addition & 0 deletions lib/compiler-singlepass/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod location;
mod machine;
mod machine_x64;
mod x64_decl;
mod arm64_decl;

pub use crate::compiler::SinglepassCompiler;
pub use crate::config::Singlepass;
5 changes: 0 additions & 5 deletions lib/compiler-singlepass/src/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,4 @@ pub trait CombinedRegister: Copy + Clone + Eq + PartialEq + Debug {
fn from_gpr(x: u16) -> Self;
/// Convert from an SIMD register
fn from_simd(x: u16) -> Self;
/// Returns the instruction prefix for move to stack
/// for example `movq %this_reg, ?(%rsp)` on x86_64
/// To build an instruction, append the memory location as a 32-bit
/// offset to the stack pointer to this prefix.
fn _prefix_mov_to_stack(&self) -> Option<&'static [u8]>;
}
29 changes: 0 additions & 29 deletions lib/compiler-singlepass/src/x64_decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,35 +166,6 @@ impl CombinedRegister for X64Register {
_ => return None,
})
}

/// Returns the instruction prefix for `movq %this_reg, ?(%rsp)`.
///
/// To build an instruction, append the memory location as a 32-bit
/// offset to the stack pointer to this prefix.
fn _prefix_mov_to_stack(&self) -> Option<&'static [u8]> {
Some(match *self {
X64Register::GPR(gpr) => match gpr {
GPR::RDI => &[0x48, 0x89, 0xbc, 0x24],
GPR::RSI => &[0x48, 0x89, 0xb4, 0x24],
GPR::RDX => &[0x48, 0x89, 0x94, 0x24],
GPR::RCX => &[0x48, 0x89, 0x8c, 0x24],
GPR::R8 => &[0x4c, 0x89, 0x84, 0x24],
GPR::R9 => &[0x4c, 0x89, 0x8c, 0x24],
_ => return None,
},
X64Register::XMM(xmm) => match xmm {
XMM::XMM0 => &[0x66, 0x0f, 0xd6, 0x84, 0x24],
XMM::XMM1 => &[0x66, 0x0f, 0xd6, 0x8c, 0x24],
XMM::XMM2 => &[0x66, 0x0f, 0xd6, 0x94, 0x24],
XMM::XMM3 => &[0x66, 0x0f, 0xd6, 0x9c, 0x24],
XMM::XMM4 => &[0x66, 0x0f, 0xd6, 0xa4, 0x24],
XMM::XMM5 => &[0x66, 0x0f, 0xd6, 0xac, 0x24],
XMM::XMM6 => &[0x66, 0x0f, 0xd6, 0xb4, 0x24],
XMM::XMM7 => &[0x66, 0x0f, 0xd6, 0xbc, 0x24],
_ => return None,
},
})
}
}

/// An allocator that allocates registers for function arguments according to the System V ABI.
Expand Down

0 comments on commit 1e1032e

Please sign in to comment.