xref: /wasmtime-44.0.1/winch/codegen/src/isa/x64/mod.rs (revision b112bb85)
1 use crate::frame::{DefinedLocals, Frame};
2 use crate::isa::x64::masm::MacroAssembler as X64Masm;
3 use crate::isa::{Builder, TargetIsa};
4 use crate::masm::MacroAssembler;
5 use crate::regalloc::RegAlloc;
6 use crate::stack::Stack;
7 use crate::{
8     Result,
9     abi::{ABI, wasm_sig},
10     codegen::{BuiltinFunctions, CodeGen, CodeGenContext, FuncEnv, TypeConverter},
11 };
12 use cranelift_codegen::settings::{self, Flags};
13 use cranelift_codegen::{Final, MachBufferFinalized, isa::x64::settings as x64_settings};
14 use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder};
15 use target_lexicon::Triple;
16 use wasmparser::{FuncValidator, FunctionBody, ValidatorResources};
17 use wasmtime_cranelift::CompiledFunction;
18 use wasmtime_environ::{ModuleTranslation, ModuleTypesBuilder, Tunables, VMOffsets, WasmFuncType};
19 
20 use self::regs::{fpr_bit_set, gpr_bit_set};
21 
22 mod abi;
23 mod address;
24 mod asm;
25 mod masm;
26 // Not all the fpr and gpr constructors are used at the moment;
27 // in that sense, this directive is a temporary measure to avoid
28 // dead code warnings.
29 #[expect(dead_code, reason = "not everything used yet, will be in the future")]
30 mod regs;
31 
32 /// Create an ISA builder.
isa_builder(triple: Triple) -> Builder33 pub(crate) fn isa_builder(triple: Triple) -> Builder {
34     Builder::new(
35         triple,
36         x64_settings::builder(),
37         |triple, shared_flags, settings| {
38             // TODO: Once enabling/disabling flags is allowed, and once features like SIMD are supported
39             // ensure compatibility between shared flags and ISA flags.
40             let isa_flags = x64_settings::Flags::new(&shared_flags, settings);
41             let isa = X64::new(triple, shared_flags, isa_flags);
42             Ok(Box::new(isa))
43         },
44     )
45 }
46 
47 /// x64 ISA.
48 pub(crate) struct X64 {
49     /// The target triple.
50     triple: Triple,
51     /// ISA specific flags.
52     isa_flags: x64_settings::Flags,
53     /// Shared flags.
54     shared_flags: Flags,
55 }
56 
57 impl X64 {
58     /// Create a x64 ISA.
new(triple: Triple, shared_flags: Flags, isa_flags: x64_settings::Flags) -> Self59     pub fn new(triple: Triple, shared_flags: Flags, isa_flags: x64_settings::Flags) -> Self {
60         Self {
61             isa_flags,
62             shared_flags,
63             triple,
64         }
65     }
66 }
67 
68 impl TargetIsa for X64 {
name(&self) -> &'static str69     fn name(&self) -> &'static str {
70         "x64"
71     }
72 
triple(&self) -> &Triple73     fn triple(&self) -> &Triple {
74         &self.triple
75     }
76 
flags(&self) -> &settings::Flags77     fn flags(&self) -> &settings::Flags {
78         &self.shared_flags
79     }
80 
isa_flags(&self) -> Vec<settings::Value>81     fn isa_flags(&self) -> Vec<settings::Value> {
82         self.isa_flags.iter().collect()
83     }
84 
compile_function( &self, sig: &WasmFuncType, body: &FunctionBody, translation: &ModuleTranslation, types: &ModuleTypesBuilder, builtins: &mut BuiltinFunctions, validator: &mut FuncValidator<ValidatorResources>, tunables: &Tunables, ) -> Result<CompiledFunction>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 
98         let mut body = body.get_binary_reader();
99         let mut masm = X64Masm::new(
100             pointer_bytes,
101             self.shared_flags.clone(),
102             self.isa_flags.clone(),
103         )?;
104         let stack = Stack::new();
105 
106         let abi_sig = wasm_sig::<abi::X64ABI>(sig)?;
107 
108         let env = FuncEnv::new(
109             &vmoffsets,
110             translation,
111             types,
112             builtins,
113             self,
114             abi::X64ABI::ptr_type(),
115         );
116         let type_converter = TypeConverter::new(env.translation, env.types);
117         let defined_locals =
118             DefinedLocals::new::<abi::X64ABI>(&type_converter, &mut body, validator)?;
119         let frame = Frame::new::<abi::X64ABI>(&abi_sig, &defined_locals)?;
120         let regalloc = RegAlloc::from(gpr_bit_set(), fpr_bit_set());
121         let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets);
122         let codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig);
123 
124         let mut body_codegen = codegen.emit_prologue()?;
125 
126         body_codegen.emit(body, validator)?;
127         let base = body_codegen.source_location.base;
128 
129         let names = body_codegen.env.take_name_map();
130         Ok(CompiledFunction::new(
131             masm.finalize(base)?,
132             names,
133             self.function_alignment(),
134         ))
135     }
136 
text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder>137     fn text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder> {
138         Box::new(MachTextSectionBuilder::<cranelift_codegen::isa::x64::Inst>::new(num_funcs))
139     }
140 
function_alignment(&self) -> u32141     fn function_alignment(&self) -> u32 {
142         // See `cranelift_codegen`'s value of this for more information.
143         16
144     }
145 
emit_unwind_info( &self, buffer: &MachBufferFinalized<Final>, kind: cranelift_codegen::isa::unwind::UnwindInfoKind, ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>>146     fn emit_unwind_info(
147         &self,
148         buffer: &MachBufferFinalized<Final>,
149         kind: cranelift_codegen::isa::unwind::UnwindInfoKind,
150     ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>> {
151         Ok(cranelift_codegen::isa::x64::emit_unwind_info(buffer, kind)?)
152     }
153 
create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry>154     fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
155         Some(cranelift_codegen::isa::x64::create_cie())
156     }
157 
page_size_align_log2(&self) -> u8158     fn page_size_align_log2(&self) -> u8 {
159         12
160     }
161 }
162