wasmer_compiler_cranelift/translator/
translation_utils.rs1use crate::func_environ::FuncEnvironment;
4use crate::translator::EXN_REF_TYPE;
5use cranelift_codegen::{
6 binemit::Reloc,
7 cursor::FuncCursor,
8 ir::{self, AbiParam, InstBuilder},
9 isa::TargetFrontendConfig,
10};
11use cranelift_frontend::FunctionBuilder;
12use wasmer_compiler::{
13 types::relocation::RelocationKind,
14 wasmparser::{self, RefType},
15};
16use wasmer_types::{FunctionType, LibCall, Type, WasmError, WasmResult};
17
18pub(crate) fn materialize_global_value(
20 pos: &mut FuncCursor<'_>,
21 pointer_type: ir::Type,
22 global_value: ir::GlobalValue,
23) -> ir::Value {
24 match pos.func.global_values[global_value] {
25 ir::GlobalValueData::VMContext => pos
26 .func
27 .special_param(ir::ArgumentPurpose::VMContext)
28 .expect("missing vmctx parameter"),
29 ir::GlobalValueData::IAddImm {
30 base,
31 offset,
32 global_type,
33 } => {
34 let base = materialize_global_value(pos, global_type, base);
35 pos.ins().iadd_imm_s(base, i64::from(offset))
36 }
37 ir::GlobalValueData::Load {
38 base,
39 offset,
40 global_type,
41 flags,
42 } => {
43 let base = materialize_global_value(pos, pointer_type, base);
44 let flags = pos.func.dfg.mem_flags[flags];
45 pos.ins().load(global_type, flags, base, offset)
46 }
47 ir::GlobalValueData::Symbol { tls, .. } => {
48 if tls {
49 pos.ins().tls_value(pointer_type, global_value)
50 } else {
51 pos.ins().symbol_value(pointer_type, global_value)
52 }
53 }
54 ir::GlobalValueData::DynScaleTargetConst { .. } => {
55 unreachable!("dynamic vector-scale global values are not created by Wasmer")
56 }
57 }
58}
59
60pub fn signature_to_cranelift_ir(
62 signature: &FunctionType,
63 target_config: TargetFrontendConfig,
64) -> ir::Signature {
65 let mut sig = ir::Signature::new(target_config.default_call_conv);
66 sig.params.extend(signature.params().iter().map(|&ty| {
67 let cret_arg: ir::Type = type_to_irtype(ty, target_config)
68 .expect("only numeric types are supported in function signatures");
69 AbiParam::new(cret_arg)
70 }));
71 sig.returns.extend(signature.results().iter().map(|&ty| {
72 let cret_arg: ir::Type = type_to_irtype(ty, target_config)
73 .expect("only numeric types are supported in function signatures");
74 AbiParam::new(cret_arg)
75 }));
76 sig.params.insert(
78 0,
79 AbiParam::special(target_config.pointer_type(), ir::ArgumentPurpose::VMContext),
80 );
81 sig
82}
83
84pub fn reference_type(target_config: TargetFrontendConfig) -> WasmResult<ir::Type> {
86 Ok(target_config.pointer_type())
87}
88
89pub fn type_to_irtype(ty: Type, target_config: TargetFrontendConfig) -> WasmResult<ir::Type> {
91 match ty {
92 Type::I32 => Ok(ir::types::I32),
93 Type::I64 => Ok(ir::types::I64),
94 Type::F32 => Ok(ir::types::F32),
95 Type::F64 => Ok(ir::types::F64),
96 Type::V128 => Ok(ir::types::I8X16),
97 Type::ExternRef | Type::FuncRef => reference_type(target_config),
98 Type::ExceptionRef => Ok(EXN_REF_TYPE),
99 }
101}
102
103pub fn irlibcall_to_libcall(libcall: ir::LibCall) -> LibCall {
105 match libcall {
106 ir::LibCall::Probestack => LibCall::Probestack,
107 ir::LibCall::CeilF32 => LibCall::CeilF32,
108 ir::LibCall::CeilF64 => LibCall::CeilF64,
109 ir::LibCall::FloorF32 => LibCall::FloorF32,
110 ir::LibCall::FloorF64 => LibCall::FloorF64,
111 ir::LibCall::TruncF32 => LibCall::TruncF32,
112 ir::LibCall::TruncF64 => LibCall::TruncF64,
113 ir::LibCall::NearestF32 => LibCall::NearestF32,
114 ir::LibCall::NearestF64 => LibCall::NearestF64,
115 _ => panic!("Unsupported libcall"),
116 }
117}
118
119pub fn irreloc_to_relocationkind(reloc: Reloc) -> RelocationKind {
121 match reloc {
122 Reloc::Abs4 => RelocationKind::Abs4,
123 Reloc::Abs8 => RelocationKind::Abs8,
124 Reloc::X86PCRel4 => RelocationKind::PCRel4,
125 Reloc::X86CallPCRel4 => RelocationKind::X86CallPCRel4,
126 Reloc::X86CallPLTRel4 => RelocationKind::X86CallPLTRel4,
127 Reloc::X86GOTPCRel4 => RelocationKind::X86GOTPCRel4,
128 Reloc::Arm64Call => RelocationKind::Arm64Call,
129 Reloc::RiscvCallPlt => RelocationKind::RiscvCall,
130 _ => panic!("The relocation {reloc} is not yet supported."),
131 }
132}
133
134pub fn block_with_params<'a>(
136 builder: &mut FunctionBuilder,
137 params: impl Iterator<Item = &'a wasmparser::ValType>,
138 environ: &FuncEnvironment<'_>,
139) -> WasmResult<ir::Block> {
140 let block = builder.create_block();
141 for ty in params.into_iter() {
142 match ty {
143 wasmparser::ValType::I32 => {
144 builder.append_block_param(block, ir::types::I32);
145 }
146 wasmparser::ValType::I64 => {
147 builder.append_block_param(block, ir::types::I64);
148 }
149 wasmparser::ValType::F32 => {
150 builder.append_block_param(block, ir::types::F32);
151 }
152 wasmparser::ValType::F64 => {
153 builder.append_block_param(block, ir::types::F64);
154 }
155 wasmparser::ValType::Ref(ty) => {
156 if ty.is_extern_ref() || ty.is_func_ref() {
157 builder.append_block_param(block, environ.reference_type());
158 } else if ty == &RefType::EXNREF || ty == &RefType::EXN {
159 builder.append_block_param(block, EXN_REF_TYPE);
161 } else {
162 return Err(WasmError::Unsupported(format!(
163 "unsupported reference type: {ty:?}"
164 )));
165 }
166 }
167 wasmparser::ValType::V128 => {
168 builder.append_block_param(block, ir::types::I8X16);
169 }
170 }
171 }
172 Ok(block)
173}
174
175pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
177 ir::immediates::Ieee32::with_bits(x.bits())
178}
179
180pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
182 ir::immediates::Ieee64::with_bits(x.bits())
183}
184
185pub fn get_vmctx_value_label() -> ir::ValueLabel {
187 const VMCTX_LABEL: u32 = 0xffff_fffe;
188 ir::ValueLabel::from_u32(VMCTX_LABEL)
189}