xref: /wasmtime-44.0.1/winch/codegen/src/abi/mod.rs (revision 25bf8e0e)
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