Coverage Report

Created: 2026-09-28 08:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasmtime/cranelift/codegen/src/binemit/mod.rs
Line
Count
Source
1
//! Binary machine code emission.
2
//!
3
//! The `binemit` module contains code for translating Cranelift's intermediate representation into
4
//! binary machine code.
5
6
use core::fmt;
7
#[cfg(feature = "enable-serde")]
8
use serde_derive::{Deserialize, Serialize};
9
10
/// Offset in bytes from the beginning of the function.
11
///
12
/// Cranelift can be used as a cross compiler, so we don't want to use a type like `usize` which
13
/// depends on the *host* platform, not the *target* platform.
14
pub type CodeOffset = u32;
15
16
/// Addend to add to the symbol value.
17
pub type Addend = i64;
18
19
/// Relocation kinds for every ISA
20
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
21
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
22
pub enum Reloc {
23
    /// absolute 4-byte
24
    Abs4,
25
    /// absolute 8-byte
26
    Abs8,
27
    /// x86 PC-relative 4-byte
28
    X86PCRel4,
29
    /// x86 call to PC-relative 4-byte.
30
    ///
31
    /// This relocation is only ever applied to the displacement of a `call`
32
    /// or `jmp` instruction, never to address materialization (e.g. `lea`,
33
    /// which uses [`Reloc::X86PCRel4`] instead). Consumers may therefore
34
    /// redirect the control transfer through a veneer when the target is out
35
    /// of range of the 32-bit displacement.
36
    X86CallPCRel4,
37
    /// x86 call to PLT-relative 4-byte
38
    X86CallPLTRel4,
39
    /// x86 GOT PC-relative 4-byte
40
    X86GOTPCRel4,
41
    /// The 32-bit offset of the target from the beginning of its section.
42
    /// Equivalent to `IMAGE_REL_AMD64_SECREL`.
43
    /// See: [PE Format](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format)
44
    X86SecRel,
45
    /// Arm32 call target
46
    Arm32Call,
47
    /// Arm64 call target. Encoded as bottom 26 bits of instruction. This
48
    /// value is sign-extended, multiplied by 4, and added to the PC of
49
    /// the call instruction to form the destination address.
50
    Arm64Call,
51
    /// s390x PC-relative 4-byte offset
52
    S390xPCRel32Dbl,
53
    /// s390x PC-relative 4-byte offset to PLT
54
    S390xPLTRel32Dbl,
55
56
    /// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol.
57
    ElfX86_64TlsGd,
58
59
    /// Mach-O x86_64 32 bit signed PC relative offset to a `__thread_vars` entry.
60
    MachOX86_64Tlv,
61
62
    /// Mach-O Aarch64 TLS
63
    /// PC-relative distance to the page of the TLVP slot.
64
    MachOAarch64TlsAdrPage21,
65
66
    /// Mach-O Aarch64 TLS
67
    /// Offset within page of TLVP slot.
68
    MachOAarch64TlsAdrPageOff12,
69
70
    /// Aarch64 TLSDESC Adr Page21
71
    /// This is equivalent to `R_AARCH64_TLSDESC_ADR_PAGE21` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors)
72
    Aarch64TlsDescAdrPage21,
73
74
    /// Aarch64 TLSDESC Ld64 Lo12
75
    /// This is equivalent to `R_AARCH64_TLSDESC_LD64_LO12` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors)
76
    Aarch64TlsDescLd64Lo12,
77
78
    /// Aarch64 TLSDESC Add Lo12
79
    /// This is equivalent to `R_AARCH64_TLSGD_ADD_LO12` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors)
80
    Aarch64TlsDescAddLo12,
81
82
    /// Aarch64 TLSDESC Call
83
    /// This is equivalent to `R_AARCH64_TLSDESC_CALL` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors)
84
    Aarch64TlsDescCall,
85
86
    /// AArch64 GOT Page
87
    /// Set the immediate value of an ADRP to bits 32:12 of X; check that –2^32 <= X < 2^32
88
    /// This is equivalent to `R_AARCH64_ADR_GOT_PAGE` (311) in the  [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#static-aarch64-relocations)
89
    Aarch64AdrGotPage21,
90
91
    /// Equivalent of `R_AARCH64_ADR_PREL_PG_HI21`.
92
    Aarch64AdrPrelPgHi21,
93
    /// Equivalent of `R_AARCH64_ADD_ABS_LO12_NC`.
94
    Aarch64AddAbsLo12Nc,
95
96
    /// AArch64 GOT Low bits
97
98
    /// Set the LD/ST immediate field to bits 11:3 of X. No overflow check; check that X&7 = 0
99
    /// This is equivalent to `R_AARCH64_LD64_GOT_LO12_NC` (312) in the  [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#static-aarch64-relocations)
100
    Aarch64Ld64GotLo12Nc,
101
102
    /// RISC-V Call PLT: 32-bit PC-relative function call, macros call, tail (PIC)
103
    ///
104
    /// Despite having PLT in the name, this relocation is also used for normal calls.
105
    /// The non-PLT version of this relocation has been deprecated.
106
    ///
107
    /// This is the `R_RISCV_CALL_PLT` relocation from the RISC-V ELF psABI document.
108
    /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#procedure-calls>
109
    RiscvCallPlt,
110
111
    /// RISC-V TLS GD: High 20 bits of 32-bit PC-relative TLS GD GOT reference,
112
    ///
113
    /// This is the `R_RISCV_TLS_GD_HI20` relocation from the RISC-V ELF psABI document.
114
    /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#global-dynamic>
115
    RiscvTlsGdHi20,
116
117
    /// Low 12 bits of a 32-bit PC-relative relocation (I-Type instruction)
118
    ///
119
    /// This is the `R_RISCV_PCREL_LO12_I` relocation from the RISC-V ELF psABI document.
120
    /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
121
    RiscvPCRelLo12I,
122
123
    /// High 20 bits of a 32-bit PC-relative GOT offset relocation
124
    ///
125
    /// This is the `R_RISCV_GOT_HI20` relocation from the RISC-V ELF psABI document.
126
    /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
127
    RiscvGotHi20,
128
129
    /// High 20 bits of a 32-bit PC-relative offset relocation
130
    ///
131
    /// This is the `R_RISCV_PCREL_HI20` relocation from the RISC-V ELF psABI document.
132
    /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
133
    RiscvPCRelHi20,
134
135
    /// s390x TLS GD64 - 64-bit offset of tls_index for GD symbol in GOT
136
    S390xTlsGd64,
137
    /// s390x TLS GDCall - marker to enable optimization of TLS calls
138
    S390xTlsGdCall,
139
140
    /// Pulley - a relocation which is a pc-relative offset.
141
    PulleyPcRel,
142
143
    /// Pulley - call a host function indirectly where the embedder resolving
144
    /// this relocation needs to fill the 8-bit immediate that's part of the
145
    /// `call_indirect_host` opcode (an opaque identifier used by the host).
146
    PulleyCallIndirectHost,
147
}
148
149
impl fmt::Display for Reloc {
150
    /// Display trait implementation drops the arch, since its used in contexts where the arch is
151
    /// already unambiguous, e.g. clif syntax with isa specified. In other contexts, use Debug.
152
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153
0
        match *self {
154
0
            Self::Abs4 => write!(f, "Abs4"),
155
0
            Self::Abs8 => write!(f, "Abs8"),
156
0
            Self::S390xPCRel32Dbl => write!(f, "PCRel32Dbl"),
157
0
            Self::S390xPLTRel32Dbl => write!(f, "PLTRel32Dbl"),
158
0
            Self::X86PCRel4 => write!(f, "PCRel4"),
159
0
            Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
160
0
            Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
161
0
            Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
162
0
            Self::X86SecRel => write!(f, "SecRel"),
163
0
            Self::Arm32Call | Self::Arm64Call => write!(f, "Call"),
164
0
            Self::RiscvCallPlt => write!(f, "RiscvCallPlt"),
165
0
            Self::RiscvTlsGdHi20 => write!(f, "RiscvTlsGdHi20"),
166
0
            Self::RiscvGotHi20 => write!(f, "RiscvGotHi20"),
167
0
            Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"),
168
0
            Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
169
0
            Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
170
0
            Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
171
0
            Self::MachOAarch64TlsAdrPage21 => write!(f, "MachOAarch64TlsAdrPage21"),
172
0
            Self::MachOAarch64TlsAdrPageOff12 => write!(f, "MachOAarch64TlsAdrPageOff12"),
173
0
            Self::Aarch64TlsDescAdrPage21 => write!(f, "Aarch64TlsDescAdrPage21"),
174
0
            Self::Aarch64TlsDescLd64Lo12 => write!(f, "Aarch64TlsDescLd64Lo12"),
175
0
            Self::Aarch64TlsDescAddLo12 => write!(f, "Aarch64TlsDescAddLo12"),
176
0
            Self::Aarch64TlsDescCall => write!(f, "Aarch64TlsDescCall"),
177
0
            Self::Aarch64AdrGotPage21 => write!(f, "Aarch64AdrGotPage21"),
178
0
            Self::Aarch64Ld64GotLo12Nc => write!(f, "Aarch64AdrGotLo12Nc"),
179
0
            Self::Aarch64AdrPrelPgHi21 => write!(f, "Aarch64AdrPrelPgHi21"),
180
0
            Self::Aarch64AddAbsLo12Nc => write!(f, "Aarch64AddAbsLo12Nc"),
181
0
            Self::S390xTlsGd64 => write!(f, "TlsGd64"),
182
0
            Self::S390xTlsGdCall => write!(f, "TlsGdCall"),
183
0
            Self::PulleyPcRel => write!(f, "PulleyPcRel"),
184
0
            Self::PulleyCallIndirectHost => write!(f, "PulleyCallIndirectHost"),
185
        }
186
0
    }
187
}
188
189
/// Container for information about a vector of compiled code and its supporting read-only data.
190
///
191
/// The code starts at offset 0 and is followed optionally by relocatable jump tables and copyable
192
/// (raw binary) read-only data.  Any padding between sections is always part of the section that
193
/// precedes the boundary between the sections.
194
#[derive(Debug, PartialEq)]
195
pub struct CodeInfo {
196
    /// Number of bytes in total.
197
    pub total_size: CodeOffset,
198
}