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, Tunables, 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 pub(crate) struct Aarch64 { 45 /// The target triple. 46 triple: Triple, 47 /// ISA specific flags. 48 isa_flags: aarch64_settings::Flags, 49 /// Shared flags. 50 shared_flags: Flags, 51 } 52 53 impl Aarch64 { 54 /// Create an Aarch64 ISA. 55 pub fn new(triple: Triple, shared_flags: Flags, isa_flags: aarch64_settings::Flags) -> Self { 56 Self { 57 isa_flags, 58 shared_flags, 59 triple, 60 } 61 } 62 } 63 64 impl TargetIsa for Aarch64 { 65 fn name(&self) -> &'static str { 66 "aarch64" 67 } 68 69 fn triple(&self) -> &Triple { 70 &self.triple 71 } 72 73 fn flags(&self) -> &settings::Flags { 74 &self.shared_flags 75 } 76 77 fn isa_flags(&self) -> Vec<settings::Value> { 78 self.isa_flags.iter().collect() 79 } 80 81 fn is_branch_protection_enabled(&self) -> bool { 82 self.isa_flags.use_bti() 83 } 84 85 fn compile_function( 86 &self, 87 sig: &WasmFuncType, 88 body: &FunctionBody, 89 translation: &ModuleTranslation, 90 types: &ModuleTypesBuilder, 91 builtins: &mut BuiltinFunctions, 92 validator: &mut FuncValidator<ValidatorResources>, 93 tunables: &Tunables, 94 ) -> Result<CompiledFunction> { 95 let pointer_bytes = self.pointer_bytes(); 96 let vmoffsets = VMOffsets::new(pointer_bytes, &translation.module); 97 let mut body = body.get_binary_reader(); 98 let mut masm = Aarch64Masm::new(pointer_bytes, self.shared_flags.clone()); 99 let stack = Stack::new(); 100 let abi_sig = wasm_sig::<abi::Aarch64ABI>(sig); 101 102 let env = FuncEnv::new( 103 &vmoffsets, 104 translation, 105 types, 106 builtins, 107 self, 108 abi::Aarch64ABI::ptr_type(), 109 ); 110 let type_converter = TypeConverter::new(env.translation, env.types); 111 let defined_locals = 112 DefinedLocals::new::<abi::Aarch64ABI>(&type_converter, &mut body, validator)?; 113 let frame = Frame::new::<abi::Aarch64ABI>(&abi_sig, &defined_locals)?; 114 let gpr = RegBitSet::int( 115 ALL_GPR.into(), 116 NON_ALLOCATABLE_GPR.into(), 117 usize::try_from(MAX_GPR).unwrap(), 118 ); 119 let fpr = RegBitSet::float( 120 ALL_FPR.into(), 121 NON_ALLOCATABLE_FPR.into(), 122 usize::try_from(MAX_FPR).unwrap(), 123 ); 124 let regalloc = RegAlloc::from(gpr, fpr); 125 let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets); 126 let codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig); 127 128 let mut body_codegen = codegen.emit_prologue()?; 129 body_codegen.emit(&mut body, validator)?; 130 let names = body_codegen.env.take_name_map(); 131 let base = body_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 fn page_size_align_log2(&self) -> u8 { 160 use target_lexicon::*; 161 match self.triple().operating_system { 162 OperatingSystem::MacOSX { .. } 163 | OperatingSystem::Darwin 164 | OperatingSystem::Ios 165 | OperatingSystem::Tvos => { 166 debug_assert_eq!(1 << 14, 0x4000); 167 14 168 } 169 _ => { 170 debug_assert_eq!(1 << 16, 0x10000); 171 16 172 } 173 } 174 } 175 } 176