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