/src/wasmtime/winch/codegen/src/isa/x64/mod.rs
Line | Count | Source |
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::{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. |
33 | 5.52k | pub(crate) fn isa_builder(triple: Triple) -> Builder { |
34 | 5.52k | Builder::new( |
35 | 5.52k | triple, |
36 | 5.52k | x64_settings::builder(), |
37 | 5.52k | |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 | 5.52k | let isa_flags = x64_settings::Flags::new(&shared_flags, settings); |
41 | 5.52k | let isa = X64::new(triple, shared_flags, isa_flags); |
42 | 5.52k | Ok(Box::new(isa)) |
43 | 5.52k | }, |
44 | | ) |
45 | 5.52k | } |
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. |
59 | 5.52k | pub fn new(triple: Triple, shared_flags: Flags, isa_flags: x64_settings::Flags) -> Self { |
60 | 5.52k | Self { |
61 | 5.52k | isa_flags, |
62 | 5.52k | shared_flags, |
63 | 5.52k | triple, |
64 | 5.52k | } |
65 | 5.52k | } |
66 | | } |
67 | | |
68 | | impl TargetIsa for X64 { |
69 | 0 | fn name(&self) -> &'static str { |
70 | 0 | "x64" |
71 | 0 | } |
72 | | |
73 | 123k | fn triple(&self) -> &Triple { |
74 | 123k | &self.triple |
75 | 123k | } |
76 | | |
77 | 203k | fn flags(&self) -> &settings::Flags { |
78 | 203k | &self.shared_flags |
79 | 203k | } |
80 | | |
81 | 12.2k | fn isa_flags(&self) -> Vec<settings::Value> { |
82 | 12.2k | self.isa_flags.iter().collect() |
83 | 12.2k | } |
84 | | |
85 | 63.8k | fn compile_function( |
86 | 63.8k | &self, |
87 | 63.8k | sig: &WasmFuncType, |
88 | 63.8k | body: &FunctionBody, |
89 | 63.8k | translation: &ModuleTranslation, |
90 | 63.8k | types: &ModuleTypesBuilder, |
91 | 63.8k | builtins: &mut BuiltinFunctions, |
92 | 63.8k | validator: &mut FuncValidator<ValidatorResources>, |
93 | 63.8k | tunables: &Tunables, |
94 | 63.8k | ) -> Result<(CompiledFunction, bool)> { |
95 | 63.8k | let pointer_bytes = self.pointer_bytes(); |
96 | 63.8k | let vmoffsets = VMOffsets::new(pointer_bytes, &translation.module); |
97 | | |
98 | 63.8k | let mut body = body.get_binary_reader(); |
99 | 63.8k | let mut masm = X64Masm::new( |
100 | 63.8k | pointer_bytes, |
101 | 63.8k | self.shared_flags.clone(), |
102 | 63.8k | self.isa_flags.clone(), |
103 | 0 | )?; |
104 | 63.8k | let stack = Stack::new(); |
105 | | |
106 | 63.8k | let abi_sig = wasm_sig::<abi::X64ABI>(sig)?; |
107 | | |
108 | 63.8k | let env = FuncEnv::new( |
109 | 63.8k | &vmoffsets, |
110 | 63.8k | translation, |
111 | 63.8k | types, |
112 | 63.8k | builtins, |
113 | 63.8k | self, |
114 | 63.8k | abi::X64ABI::ptr_type(), |
115 | | ); |
116 | 63.8k | let type_converter = TypeConverter::new(env.translation, env.types); |
117 | 63.8k | let defined_locals = |
118 | 63.8k | DefinedLocals::new::<abi::X64ABI>(&type_converter, &mut body, validator)?; |
119 | 63.8k | let frame = Frame::new::<abi::X64ABI>(&abi_sig, &defined_locals)?; |
120 | 63.8k | let regalloc = RegAlloc::from(gpr_bit_set(), fpr_bit_set()); |
121 | 63.8k | let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets); |
122 | 63.8k | let codegen = CodeGen::new( |
123 | 63.8k | tunables, |
124 | 63.8k | &mut masm, |
125 | 63.8k | codegen_context, |
126 | 63.8k | env, |
127 | 63.8k | abi_sig, |
128 | 63.8k | validator.features(), |
129 | 0 | )?; |
130 | | |
131 | 63.8k | let mut body_codegen = codegen.emit_prologue()?; |
132 | | |
133 | 63.8k | body_codegen.emit(body, validator)?; |
134 | 63.6k | let needs_gc_heap = body_codegen.needs_gc_heap; |
135 | 63.6k | let base = body_codegen.source_location.base; |
136 | | |
137 | 63.6k | let names = body_codegen.env.take_name_map(); |
138 | | Ok(( |
139 | 63.6k | CompiledFunction::new(masm.finalize(base)?, names, self.function_alignment()), |
140 | 63.6k | needs_gc_heap, |
141 | | )) |
142 | 63.8k | } |
143 | | |
144 | 0 | fn text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder> { |
145 | 0 | Box::new(MachTextSectionBuilder::<cranelift_codegen::isa::x64::Inst>::new(num_funcs)) |
146 | 0 | } |
147 | | |
148 | 63.6k | fn function_alignment(&self) -> u32 { |
149 | | // See `cranelift_codegen`'s value of this for more information. |
150 | 63.6k | 16 |
151 | 63.6k | } |
152 | | |
153 | 14.4k | fn emit_unwind_info( |
154 | 14.4k | &self, |
155 | 14.4k | buffer: &MachBufferFinalized, |
156 | 14.4k | kind: cranelift_codegen::isa::unwind::UnwindInfoKind, |
157 | 14.4k | ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>> { |
158 | 14.4k | Ok(cranelift_codegen::isa::x64::emit_unwind_info(buffer, kind)?) |
159 | 14.4k | } |
160 | | |
161 | 0 | fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> { |
162 | 0 | Some(cranelift_codegen::isa::x64::create_cie()) |
163 | 0 | } |
164 | | |
165 | 63.8k | fn page_size_align_log2(&self) -> u8 { |
166 | 63.8k | 12 |
167 | 63.8k | } |
168 | | } |