1 use self::regs::{ALL_GPR, MAX_FPR, MAX_GPR, NON_ALLOCATABLE_GPR}; 2 use crate::isa::aarch64::regs::{ALL_FPR, NON_ALLOCATABLE_FPR}; 3 use crate::{ 4 abi::{wasm_sig, ABI}, 5 codegen::{CodeGen, CodeGenContext, FuncEnv, TypeConverter}, 6 frame::{DefinedLocals, Frame}, 7 isa::{Builder, TargetIsa}, 8 masm::MacroAssembler, 9 regalloc::RegAlloc, 10 regset::RegBitSet, 11 stack::Stack, 12 BuiltinFunctions, 13 }; 14 use anyhow::Result; 15 use cranelift_codegen::settings::{self, Flags}; 16 use cranelift_codegen::{isa::aarch64::settings as aarch64_settings, Final, MachBufferFinalized}; 17 use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder}; 18 use masm::MacroAssembler as Aarch64Masm; 19 use target_lexicon::Triple; 20 use wasmparser::{FuncValidator, FunctionBody, ValidatorResources}; 21 use wasmtime_cranelift::CompiledFunction; 22 use wasmtime_environ::{ModuleTranslation, ModuleTypesBuilder, VMOffsets, WasmFuncType}; 23 24 mod abi; 25 mod address; 26 mod asm; 27 mod masm; 28 mod regs; 29 30 /// Create an ISA from the given triple. 31 pub(crate) fn isa_builder(triple: Triple) -> Builder { 32 Builder::new( 33 triple, 34 aarch64_settings::builder(), 35 |triple, shared_flags, settings| { 36 let isa_flags = aarch64_settings::Flags::new(&shared_flags, settings); 37 let isa = Aarch64::new(triple, shared_flags, isa_flags); 38 Ok(Box::new(isa)) 39 }, 40 ) 41 } 42 43 /// Aarch64 ISA. 44 // Until Aarch64 emission is supported. 45 #[allow(dead_code)] 46 pub(crate) struct Aarch64 { 47 /// The target triple. 48 triple: Triple, 49 /// ISA specific flags. 50 isa_flags: aarch64_settings::Flags, 51 /// Shared flags. 52 shared_flags: Flags, 53 } 54 55 impl Aarch64 { 56 /// Create an Aarch64 ISA. 57 pub fn new(triple: Triple, shared_flags: Flags, isa_flags: aarch64_settings::Flags) -> Self { 58 Self { 59 isa_flags, 60 shared_flags, 61 triple, 62 } 63 } 64 } 65 66 impl TargetIsa for Aarch64 { 67 fn name(&self) -> &'static str { 68 "aarch64" 69 } 70 71 fn triple(&self) -> &Triple { 72 &self.triple 73 } 74 75 fn flags(&self) -> &settings::Flags { 76 &self.shared_flags 77 } 78 79 fn isa_flags(&self) -> Vec<settings::Value> { 80 self.isa_flags.iter().collect() 81 } 82 83 fn is_branch_protection_enabled(&self) -> bool { 84 self.isa_flags.use_bti() 85 } 86 87 fn compile_function( 88 &self, 89 sig: &WasmFuncType, 90 body: &FunctionBody, 91 translation: &ModuleTranslation, 92 types: &ModuleTypesBuilder, 93 builtins: &mut BuiltinFunctions, 94 validator: &mut FuncValidator<ValidatorResources>, 95 ) -> Result<CompiledFunction> { 96 let pointer_bytes = self.pointer_bytes(); 97 let vmoffsets = VMOffsets::new(pointer_bytes, &translation.module); 98 let mut body = body.get_binary_reader(); 99 let mut masm = Aarch64Masm::new(pointer_bytes, self.shared_flags.clone()); 100 let stack = Stack::new(); 101 let abi_sig = wasm_sig::<abi::Aarch64ABI>(sig); 102 103 let env = FuncEnv::new( 104 &vmoffsets, 105 translation, 106 types, 107 builtins, 108 self, 109 abi::Aarch64ABI::ptr_type(), 110 ); 111 let type_converter = TypeConverter::new(env.translation, env.types); 112 let defined_locals = 113 DefinedLocals::new::<abi::Aarch64ABI>(&type_converter, &mut body, validator)?; 114 let frame = Frame::new::<abi::Aarch64ABI>(&abi_sig, &defined_locals)?; 115 let gpr = RegBitSet::int( 116 ALL_GPR.into(), 117 NON_ALLOCATABLE_GPR.into(), 118 usize::try_from(MAX_GPR).unwrap(), 119 ); 120 let fpr = RegBitSet::float( 121 ALL_FPR.into(), 122 NON_ALLOCATABLE_FPR.into(), 123 usize::try_from(MAX_FPR).unwrap(), 124 ); 125 let regalloc = RegAlloc::from(gpr, fpr); 126 let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets); 127 let mut codegen = CodeGen::new(&mut masm, codegen_context, env, abi_sig); 128 129 codegen.emit(&mut body, validator)?; 130 let names = codegen.env.take_name_map(); 131 let base = codegen.source_location.base; 132 Ok(CompiledFunction::new( 133 masm.finalize(base), 134 names, 135 self.function_alignment(), 136 )) 137 } 138 139 fn text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder> { 140 Box::new(MachTextSectionBuilder::< 141 cranelift_codegen::isa::aarch64::inst::Inst, 142 >::new(num_funcs)) 143 } 144 145 fn function_alignment(&self) -> u32 { 146 // See `cranelift_codegen::isa::TargetIsa::function_alignment`. 147 32 148 } 149 150 fn emit_unwind_info( 151 &self, 152 _result: &MachBufferFinalized<Final>, 153 _kind: cranelift_codegen::isa::unwind::UnwindInfoKind, 154 ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>> { 155 // TODO: should fill this in with an actual implementation 156 Ok(None) 157 } 158 } 159