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