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