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