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