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