winch_codegen/codegen/
builtin.rs1use crate::{
4 CallingConvention, Result,
5 abi::{ABI, ABISig},
6 codegen::env::ptr_type_from_ptr_size,
7};
8use std::sync::Arc;
9use wasmtime_environ::{BuiltinFunctionIndex, PtrSize, VMOffsets, WasmValType};
10
11#[derive(Copy, Clone)]
12pub(crate) enum BuiltinType {
13 Builtin(BuiltinFunctionIndex),
15}
16
17impl BuiltinType {
18 pub fn builtin(idx: BuiltinFunctionIndex) -> Self {
21 Self::Builtin(idx)
22 }
23}
24
25#[derive(Clone)]
26pub struct BuiltinFunction {
27 inner: Arc<BuiltinFunctionInner>,
28}
29
30impl BuiltinFunction {
31 pub(crate) fn sig(&self) -> &ABISig {
32 &self.inner.sig
33 }
34
35 pub(crate) fn ty(&self) -> BuiltinType {
36 self.inner.ty
37 }
38}
39
40pub struct BuiltinFunctionInner {
42 sig: ABISig,
44 ty: BuiltinType,
46}
47
48macro_rules! declare_function_sig {
49 (
50 $(
51 $( #[$attr:meta] )*
52 $name:ident( $( $pname:ident: $param:ident ),* ) $( -> $result:ident )?;
53 )*
54 ) => {
55 pub struct BuiltinFunctions {
58 host_call_conv: CallingConvention,
60 wasm_call_conv: CallingConvention,
62 ptr_type: WasmValType,
64 $(
65 $( #[ $attr ] )*
66 $name: Option<BuiltinFunction>,
67 )*
68 }
69
70 #[expect(dead_code, reason = "not all functions used yet")]
71 impl BuiltinFunctions {
72 pub fn new<P: PtrSize>(
73 vmoffsets: &VMOffsets<P>,
74 host_call_conv: CallingConvention,
75 wasm_call_conv: CallingConvention,
76 ) -> Self {
77 let size = vmoffsets.ptr.size();
78 Self {
79 host_call_conv,
80 wasm_call_conv,
81 ptr_type: ptr_type_from_ptr_size(size),
82 $(
83 $( #[ $attr ] )*
84 $name: None,
85 )*
86 }
87 }
88
89 fn pointer(&self) -> WasmValType {
90 self.ptr_type
91 }
92
93 fn size(&self) -> WasmValType {
94 self.ptr_type
95 }
96
97 fn vmctx(&self) -> WasmValType {
98 self.pointer()
99 }
100
101 fn u32(&self) -> WasmValType {
102 WasmValType::I32
103 }
104
105 fn u8(&self) -> WasmValType {
106 WasmValType::I32
107 }
108
109 fn f32(&self) -> WasmValType {
110 WasmValType::F32
111 }
112
113 fn f64(&self) -> WasmValType {
114 WasmValType::F64
115 }
116
117 fn u64(&self) -> WasmValType {
118 WasmValType::I64
119 }
120
121 fn i8x16(&self) -> WasmValType {
122 WasmValType::V128
123 }
124
125 fn f32x4(&self) -> WasmValType {
126 WasmValType::V128
127 }
128
129 fn f64x2(&self) -> WasmValType {
130 WasmValType::V128
131 }
132
133 fn bool(&self) -> WasmValType {
134 WasmValType::I32
135 }
136
137 fn over_f64<A: ABI>(&self) -> Result<ABISig> {
138 A::sig_from(&[self.f64()], &[self.f64()], &self.host_call_conv)
139 }
140
141 fn over_f32<A: ABI>(&self) -> Result<ABISig> {
142 A::sig_from(&[self.f64()], &[self.f64()], &self.host_call_conv)
143 }
144
145 $(
146 $( #[ $attr ] )*
147 pub(crate) fn $name<A: ABI>(&mut self) -> Result<BuiltinFunction> {
148 if self.$name.is_none() {
149 let params = vec![ $(self.$param() ),* ];
150 let result = vec![ $(self.$result() )?];
151 let sig = A::sig_from(¶ms, &result, &self.wasm_call_conv)?;
152 let index = BuiltinFunctionIndex::$name();
153 let inner = Arc::new(BuiltinFunctionInner { sig, ty: BuiltinType::builtin(index) });
154 self.$name = Some(BuiltinFunction {
155 inner,
156 });
157 }
158
159 Ok(self.$name.as_ref().unwrap().clone())
160 }
161 )*
162 }
163 }
164}
165
166wasmtime_environ::foreach_builtin_function!(declare_function_sig);