1 use crate::{ 2 abi::{ABI, wasm_sig}, 3 codegen::{BuiltinFunctions, CodeGen, CodeGenContext, FuncEnv, TypeConverter}, 4 }; 5 6 use crate::frame::{DefinedLocals, Frame}; 7 use crate::isa::x64::masm::MacroAssembler as X64Masm; 8 use crate::isa::{Builder, TargetIsa}; 9 use crate::masm::MacroAssembler; 10 use crate::regalloc::RegAlloc; 11 use crate::stack::Stack; 12 use anyhow::Result; 13 use cranelift_codegen::settings::{self, Flags}; 14 use cranelift_codegen::{Final, MachBufferFinalized, isa::x64::settings as x64_settings}; 15 use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder}; 16 use target_lexicon::Triple; 17 use wasmparser::{FuncValidator, FunctionBody, ValidatorResources}; 18 use wasmtime_cranelift::CompiledFunction; 19 use wasmtime_environ::{ModuleTranslation, ModuleTypesBuilder, Tunables, VMOffsets, WasmFuncType}; 20 21 use self::regs::{fpr_bit_set, gpr_bit_set}; 22 23 mod abi; 24 mod address; 25 mod asm; 26 mod masm; 27 // Not all the fpr and gpr constructors are used at the moment; 28 // in that sense, this directive is a temporary measure to avoid 29 // dead code warnings. 30 #[expect(dead_code, reason = "not everything used yet, will be in the future")] 31 mod regs; 32 33 /// Create an ISA builder. 34 pub(crate) fn isa_builder(triple: Triple) -> Builder { 35 Builder::new( 36 triple, 37 x64_settings::builder(), 38 |triple, shared_flags, settings| { 39 // TODO: Once enabling/disabling flags is allowed, and once features like SIMD are supported 40 // ensure compatibility between shared flags and ISA flags. 41 let isa_flags = x64_settings::Flags::new(&shared_flags, settings); 42 let isa = X64::new(triple, shared_flags, isa_flags); 43 Ok(Box::new(isa)) 44 }, 45 ) 46 } 47 48 /// x64 ISA. 49 pub(crate) struct X64 { 50 /// The target triple. 51 triple: Triple, 52 /// ISA specific flags. 53 isa_flags: x64_settings::Flags, 54 /// Shared flags. 55 shared_flags: Flags, 56 } 57 58 impl X64 { 59 /// Create a x64 ISA. 60 pub fn new(triple: Triple, shared_flags: Flags, isa_flags: x64_settings::Flags) -> Self { 61 Self { 62 isa_flags, 63 shared_flags, 64 triple, 65 } 66 } 67 } 68 69 impl TargetIsa for X64 { 70 fn name(&self) -> &'static str { 71 "x64" 72 } 73 74 fn triple(&self) -> &Triple { 75 &self.triple 76 } 77 78 fn flags(&self) -> &settings::Flags { 79 &self.shared_flags 80 } 81 82 fn isa_flags(&self) -> Vec<settings::Value> { 83 self.isa_flags.iter().collect() 84 } 85 86 fn compile_function( 87 &self, 88 sig: &WasmFuncType, 89 body: &FunctionBody, 90 translation: &ModuleTranslation, 91 types: &ModuleTypesBuilder, 92 builtins: &mut BuiltinFunctions, 93 validator: &mut FuncValidator<ValidatorResources>, 94 tunables: &Tunables, 95 ) -> Result<CompiledFunction> { 96 let pointer_bytes = self.pointer_bytes(); 97 let vmoffsets = VMOffsets::new(pointer_bytes, &translation.module); 98 99 let mut body = body.get_binary_reader(); 100 let mut masm = X64Masm::new( 101 pointer_bytes, 102 self.shared_flags.clone(), 103 self.isa_flags.clone(), 104 )?; 105 let stack = Stack::new(); 106 107 let abi_sig = wasm_sig::<abi::X64ABI>(sig)?; 108 109 let env = FuncEnv::new( 110 &vmoffsets, 111 translation, 112 types, 113 builtins, 114 self, 115 abi::X64ABI::ptr_type(), 116 ); 117 let type_converter = TypeConverter::new(env.translation, env.types); 118 let defined_locals = 119 DefinedLocals::new::<abi::X64ABI>(&type_converter, &mut body, validator)?; 120 let frame = Frame::new::<abi::X64ABI>(&abi_sig, &defined_locals)?; 121 let regalloc = RegAlloc::from(gpr_bit_set(), fpr_bit_set()); 122 let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets); 123 let codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig); 124 125 let mut body_codegen = codegen.emit_prologue()?; 126 127 body_codegen.emit(body, validator)?; 128 let base = body_codegen.source_location.base; 129 130 let names = body_codegen.env.take_name_map(); 131 Ok(CompiledFunction::new( 132 masm.finalize(base)?, 133 names, 134 self.function_alignment(), 135 )) 136 } 137 138 fn text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder> { 139 Box::new(MachTextSectionBuilder::<cranelift_codegen::isa::x64::Inst>::new(num_funcs)) 140 } 141 142 fn function_alignment(&self) -> u32 { 143 // See `cranelift_codegen`'s value of this for more information. 144 16 145 } 146 147 fn emit_unwind_info( 148 &self, 149 buffer: &MachBufferFinalized<Final>, 150 kind: cranelift_codegen::isa::unwind::UnwindInfoKind, 151 ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>> { 152 Ok(cranelift_codegen::isa::x64::emit_unwind_info(buffer, kind)?) 153 } 154 155 fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> { 156 Some(cranelift_codegen::isa::x64::create_cie()) 157 } 158 159 fn page_size_align_log2(&self) -> u8 { 160 12 161 } 162 } 163