1 use crate::isa::reg::Reg; 2 use smallvec::SmallVec; 3 use std::ops::{Add, BitAnd, Not, Sub}; 4 use wasmparser::{FuncType, ValType}; 5 6 pub(crate) mod addressing_mode; 7 pub(crate) mod local; 8 9 /// Trait implemented by a specific ISA and used to provide 10 /// information about alignment, parameter passing, usage of 11 /// specific registers, etc. 12 pub(crate) trait ABI { 13 /// The required stack alignment. 14 fn stack_align(&self) -> u8; 15 16 /// The offset to the argument base, relative to the frame pointer. 17 fn arg_base_offset(&self) -> u8; 18 19 /// Construct the ABI-specific signature from a WebAssembly 20 /// function type. 21 fn sig(&self, wasm_sig: &FuncType) -> ABISig; 22 23 /// Returns the number of bits in a word. 24 fn word_bits() -> u32; 25 26 /// Returns the number of bytes in a word. 27 fn word_bytes() -> u32 { 28 Self::word_bits() / 8 29 } 30 31 /// Returns the designated scratch register. 32 fn scratch_reg() -> Reg; 33 } 34 35 /// ABI-specific representation of a function argument. 36 #[derive(Debug)] 37 pub(crate) enum ABIArg { 38 /// A register argument. 39 Reg { 40 /// Type of the argument. 41 ty: ValType, 42 /// Register holding the argument. 43 reg: Reg, 44 }, 45 /// A stack argument. 46 Stack { 47 /// The type of the argument. 48 ty: ValType, 49 /// Offset of the argument relative to the frame pointer. 50 offset: u32, 51 }, 52 } 53 54 impl ABIArg { 55 /// Allocate a new register abi arg. 56 pub fn reg(reg: Reg, ty: ValType) -> Self { 57 Self::Reg { reg, ty } 58 } 59 60 /// Allocate a new stack abi arg. 61 pub fn stack_offset(offset: u32, ty: ValType) -> Self { 62 Self::Stack { ty, offset } 63 } 64 65 /// Is this abi arg in a register. 66 pub fn is_reg(&self) -> bool { 67 match *self { 68 ABIArg::Reg { .. } => true, 69 _ => false, 70 } 71 } 72 73 /// Get the register associated to this arg. 74 pub fn get_reg(&self) -> Option<Reg> { 75 match *self { 76 ABIArg::Reg { reg, .. } => Some(reg), 77 _ => None, 78 } 79 } 80 81 /// Get the type associated to this arg. 82 pub fn ty(&self) -> ValType { 83 match *self { 84 ABIArg::Reg { ty, .. } | ABIArg::Stack { ty, .. } => ty, 85 } 86 } 87 } 88 89 /// ABI-specific representation of the function result. 90 pub(crate) enum ABIResult { 91 Reg { 92 /// Type of the result. 93 ty: Option<ValType>, 94 /// Register to hold the result. 95 reg: Reg, 96 }, 97 } 98 99 impl ABIResult { 100 /// Create a register ABI result. 101 pub fn reg(ty: Option<ValType>, reg: Reg) -> Self { 102 Self::Reg { ty, reg } 103 } 104 105 /// Get the result reg. 106 pub fn result_reg(&self) -> Reg { 107 match self { 108 Self::Reg { reg, .. } => *reg, 109 } 110 } 111 112 /// Checks if the result is void. 113 pub fn is_void(&self) -> bool { 114 match self { 115 Self::Reg { ty, .. } => ty.is_none(), 116 } 117 } 118 } 119 120 /// An ABI-specific representation of a function signature. 121 pub(crate) struct ABISig { 122 /// Function parameters. 123 pub params: SmallVec<[ABIArg; 6]>, 124 pub result: ABIResult, 125 } 126 127 /// Returns the size in bytes of a given WebAssembly type. 128 pub(crate) fn ty_size(ty: &ValType) -> u32 { 129 match *ty { 130 ValType::I32 | ValType::F32 => 4, 131 ValType::I64 | ValType::F64 => 8, 132 _ => panic!(), 133 } 134 } 135 136 /// Align a value up to the given power-of-two-alignment. 137 // See https://sites.google.com/site/theoryofoperatingsystems/labs/malloc/align8 138 pub(crate) fn align_to<N>(value: N, alignment: N) -> N 139 where 140 N: Not<Output = N> 141 + BitAnd<N, Output = N> 142 + Add<N, Output = N> 143 + Sub<N, Output = N> 144 + From<u8> 145 + Copy, 146 { 147 let alignment_mask = alignment - 1.into(); 148 (value + alignment_mask) & !alignment_mask 149 } 150