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.
isa_builder(triple: Triple) -> Builder28 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.
new(triple: Triple, shared_flags: Flags, isa_flags: aarch64_settings::Flags) -> Self52     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 {
name(&self) -> &'static str62     fn name(&self) -> &'static str {
63         "aarch64"
64     }
65 
triple(&self) -> &Triple66     fn triple(&self) -> &Triple {
67         &self.triple
68     }
69 
flags(&self) -> &settings::Flags70     fn flags(&self) -> &settings::Flags {
71         &self.shared_flags
72     }
73 
isa_flags(&self) -> Vec<settings::Value>74     fn isa_flags(&self) -> Vec<settings::Value> {
75         self.isa_flags.iter().collect()
76     }
77 
is_branch_protection_enabled(&self) -> bool78     fn is_branch_protection_enabled(&self) -> bool {
79         self.isa_flags.use_bti()
80     }
81 
compile_function( &self, sig: &WasmFuncType, body: &FunctionBody, translation: &ModuleTranslation, types: &ModuleTypesBuilder, builtins: &mut BuiltinFunctions, validator: &mut FuncValidator<ValidatorResources>, tunables: &Tunables, ) -> Result<CompiledFunction>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(
96             pointer_bytes,
97             self.shared_flags.clone(),
98             self.isa_flags.clone(),
99         )?;
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 regalloc = RegAlloc::from(gpr_bit_set(), fpr_bit_set());
116         let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets);
117         let codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig);
118 
119         let mut body_codegen = codegen.emit_prologue()?;
120         body_codegen.emit(body, validator)?;
121         let names = body_codegen.env.take_name_map();
122         let base = body_codegen.source_location.base;
123         Ok(CompiledFunction::new(
124             masm.finalize(base)?,
125             names,
126             self.function_alignment(),
127         ))
128     }
129 
text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder>130     fn text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder> {
131         Box::new(MachTextSectionBuilder::<
132             cranelift_codegen::isa::aarch64::inst::Inst,
133         >::new(num_funcs))
134     }
135 
function_alignment(&self) -> u32136     fn function_alignment(&self) -> u32 {
137         // See `cranelift_codegen::isa::TargetIsa::function_alignment`.
138         32
139     }
140 
emit_unwind_info( &self, _result: &MachBufferFinalized<Final>, _kind: cranelift_codegen::isa::unwind::UnwindInfoKind, ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>>141     fn emit_unwind_info(
142         &self,
143         _result: &MachBufferFinalized<Final>,
144         _kind: cranelift_codegen::isa::unwind::UnwindInfoKind,
145     ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>> {
146         // TODO: should fill this in with an actual implementation
147         Ok(None)
148     }
149 
page_size_align_log2(&self) -> u8150     fn page_size_align_log2(&self) -> u8 {
151         use target_lexicon::*;
152         match self.triple().operating_system {
153             OperatingSystem::MacOSX { .. }
154             | OperatingSystem::Darwin(_)
155             | OperatingSystem::IOS(_)
156             | OperatingSystem::TvOS(_) => {
157                 debug_assert_eq!(1 << 14, 0x4000);
158                 14
159             }
160             _ => {
161                 debug_assert_eq!(1 << 16, 0x10000);
162                 16
163             }
164         }
165     }
166 }
167