Coverage Report

Created: 2026-09-28 08:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}