1747ad3c4Slazypassion //! Binary machine code emission.
2747ad3c4Slazypassion //!
3747ad3c4Slazypassion //! The `binemit` module contains code for translating Cranelift's intermediate representation into
4747ad3c4Slazypassion //! binary machine code.
5747ad3c4Slazypassion 
6747ad3c4Slazypassion use core::fmt;
79e884b44SArtur Jamro #[cfg(feature = "enable-serde")]
89ec02f9dSChristopher Serr use serde_derive::{Deserialize, Serialize};
9747ad3c4Slazypassion 
10747ad3c4Slazypassion /// Offset in bytes from the beginning of the function.
11747ad3c4Slazypassion ///
12747ad3c4Slazypassion /// Cranelift can be used as a cross compiler, so we don't want to use a type like `usize` which
13747ad3c4Slazypassion /// depends on the *host* platform, not the *target* platform.
14747ad3c4Slazypassion pub type CodeOffset = u32;
15747ad3c4Slazypassion 
16747ad3c4Slazypassion /// Addend to add to the symbol value.
17747ad3c4Slazypassion pub type Addend = i64;
18747ad3c4Slazypassion 
19747ad3c4Slazypassion /// Relocation kinds for every ISA
20d3815a03SArtur Jamro #[derive(Copy, Clone, Debug, PartialEq, Eq)]
219e884b44SArtur Jamro #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
22747ad3c4Slazypassion pub enum Reloc {
23747ad3c4Slazypassion     /// absolute 4-byte
24747ad3c4Slazypassion     Abs4,
25747ad3c4Slazypassion     /// absolute 8-byte
26747ad3c4Slazypassion     Abs8,
27747ad3c4Slazypassion     /// x86 PC-relative 4-byte
28747ad3c4Slazypassion     X86PCRel4,
29747ad3c4Slazypassion     /// x86 call to PC-relative 4-byte
30747ad3c4Slazypassion     X86CallPCRel4,
31747ad3c4Slazypassion     /// x86 call to PLT-relative 4-byte
32747ad3c4Slazypassion     X86CallPLTRel4,
33747ad3c4Slazypassion     /// x86 GOT PC-relative 4-byte
34747ad3c4Slazypassion     X86GOTPCRel4,
35c5bc368cSAfonso Bordado     /// The 32-bit offset of the target from the beginning of its section.
36c5bc368cSAfonso Bordado     /// Equivalent to `IMAGE_REL_AMD64_SECREL`.
37c5bc368cSAfonso Bordado     /// See: [PE Format](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format)
38c5bc368cSAfonso Bordado     X86SecRel,
39747ad3c4Slazypassion     /// Arm32 call target
40747ad3c4Slazypassion     Arm32Call,
41875d2758SChris Fallin     /// Arm64 call target. Encoded as bottom 26 bits of instruction. This
42875d2758SChris Fallin     /// value is sign-extended, multiplied by 4, and added to the PC of
43875d2758SChris Fallin     /// the call instruction to form the destination address.
44747ad3c4Slazypassion     Arm64Call,
45e1cc1a67SUlrich Weigand     /// s390x PC-relative 4-byte offset
46e1cc1a67SUlrich Weigand     S390xPCRel32Dbl,
47be36dd6bSUlrich Weigand     /// s390x PC-relative 4-byte offset to PLT
48be36dd6bSUlrich Weigand     S390xPLTRel32Dbl,
490a1bb3baSbjorn3 
500a1bb3baSbjorn3     /// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol.
510a1bb3baSbjorn3     ElfX86_64TlsGd,
520a1bb3baSbjorn3 
530a1bb3baSbjorn3     /// Mach-O x86_64 32 bit signed PC relative offset to a `__thread_vars` entry.
540a1bb3baSbjorn3     MachOX86_64Tlv,
55b8ad99e4SAfonso Bordado 
56c3decdf9SNathan Whitaker     /// Mach-O Aarch64 TLS
57c3decdf9SNathan Whitaker     /// PC-relative distance to the page of the TLVP slot.
58c3decdf9SNathan Whitaker     MachOAarch64TlsAdrPage21,
59c3decdf9SNathan Whitaker 
60c3decdf9SNathan Whitaker     /// Mach-O Aarch64 TLS
61c3decdf9SNathan Whitaker     /// Offset within page of TLVP slot.
62c3decdf9SNathan Whitaker     MachOAarch64TlsAdrPageOff12,
63c3decdf9SNathan Whitaker 
64ccaf2bfaSAfonso Bordado     /// Aarch64 TLSDESC Adr Page21
65ccaf2bfaSAfonso Bordado     /// 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)
66ccaf2bfaSAfonso Bordado     Aarch64TlsDescAdrPage21,
67b8ad99e4SAfonso Bordado 
68ccaf2bfaSAfonso Bordado     /// Aarch64 TLSDESC Ld64 Lo12
69ccaf2bfaSAfonso Bordado     /// 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)
70ccaf2bfaSAfonso Bordado     Aarch64TlsDescLd64Lo12,
71ccaf2bfaSAfonso Bordado 
72ccaf2bfaSAfonso Bordado     /// Aarch64 TLSDESC Add Lo12
73ccaf2bfaSAfonso Bordado     /// 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)
74ccaf2bfaSAfonso Bordado     Aarch64TlsDescAddLo12,
75ccaf2bfaSAfonso Bordado 
76ccaf2bfaSAfonso Bordado     /// Aarch64 TLSDESC Call
77ccaf2bfaSAfonso Bordado     /// 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)
78ccaf2bfaSAfonso Bordado     Aarch64TlsDescCall,
7950fcab29SUlrich Weigand 
80eabd43a1SAfonso Bordado     /// AArch64 GOT Page
81cd97c9f1SMrmaxmeier     /// Set the immediate value of an ADRP to bits 32:12 of X; check that –2^32 <= X < 2^32
82eabd43a1SAfonso Bordado     /// 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)
83eabd43a1SAfonso Bordado     Aarch64AdrGotPage21,
84eabd43a1SAfonso Bordado 
8510d2cbc5SAlex Crichton     /// Equivalent of `R_AARCH64_ADR_PREL_PG_HI21`.
8610d2cbc5SAlex Crichton     Aarch64AdrPrelPgHi21,
8710d2cbc5SAlex Crichton     /// Equivalent of `R_AARCH64_ADD_ABS_LO12_NC`.
8810d2cbc5SAlex Crichton     Aarch64AddAbsLo12Nc,
8910d2cbc5SAlex Crichton 
90eabd43a1SAfonso Bordado     /// AArch64 GOT Low bits
91eabd43a1SAfonso Bordado 
92eabd43a1SAfonso Bordado     /// Set the LD/ST immediate field to bits 11:3 of X. No overflow check; check that X&7 = 0
93eabd43a1SAfonso Bordado     /// 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)
94eabd43a1SAfonso Bordado     Aarch64Ld64GotLo12Nc,
95eabd43a1SAfonso Bordado 
96ecc1b794SAfonso Bordado     /// RISC-V Call PLT: 32-bit PC-relative function call, macros call, tail (PIC)
97ecc1b794SAfonso Bordado     ///
98ecc1b794SAfonso Bordado     /// Despite having PLT in the name, this relocation is also used for normal calls.
99ecc1b794SAfonso Bordado     /// The non-PLT version of this relocation has been deprecated.
100ecc1b794SAfonso Bordado     ///
101ecc1b794SAfonso Bordado     /// This is the `R_RISCV_CALL_PLT` relocation from the RISC-V ELF psABI document.
102d38d387aSAlex Crichton     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#procedure-calls>
103ecc1b794SAfonso Bordado     RiscvCallPlt,
104cdecc858Syuyang-ok 
105b23f534cSAfonso Bordado     /// RISC-V TLS GD: High 20 bits of 32-bit PC-relative TLS GD GOT reference,
106b23f534cSAfonso Bordado     ///
107b23f534cSAfonso Bordado     /// This is the `R_RISCV_TLS_GD_HI20` relocation from the RISC-V ELF psABI document.
108d38d387aSAlex Crichton     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#global-dynamic>
109b23f534cSAfonso Bordado     RiscvTlsGdHi20,
110b23f534cSAfonso Bordado 
111b23f534cSAfonso Bordado     /// Low 12 bits of a 32-bit PC-relative relocation (I-Type instruction)
112b23f534cSAfonso Bordado     ///
113b23f534cSAfonso Bordado     /// This is the `R_RISCV_PCREL_LO12_I` relocation from the RISC-V ELF psABI document.
114d38d387aSAlex Crichton     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
115b23f534cSAfonso Bordado     RiscvPCRelLo12I,
116b23f534cSAfonso Bordado 
117ecc1b794SAfonso Bordado     /// High 20 bits of a 32-bit PC-relative GOT offset relocation
118ecc1b794SAfonso Bordado     ///
119ecc1b794SAfonso Bordado     /// This is the `R_RISCV_GOT_HI20` relocation from the RISC-V ELF psABI document.
120d38d387aSAlex Crichton     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
121ecc1b794SAfonso Bordado     RiscvGotHi20,
122ecc1b794SAfonso Bordado 
123*13b300deSAlex Crichton     /// High 20 bits of a 32-bit PC-relative offset relocation
124*13b300deSAlex Crichton     ///
125*13b300deSAlex Crichton     /// This is the `R_RISCV_PCREL_HI20` relocation from the RISC-V ELF psABI document.
126*13b300deSAlex Crichton     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
127*13b300deSAlex Crichton     RiscvPCRelHi20,
128*13b300deSAlex Crichton 
12950fcab29SUlrich Weigand     /// s390x TLS GD64 - 64-bit offset of tls_index for GD symbol in GOT
13050fcab29SUlrich Weigand     S390xTlsGd64,
13150fcab29SUlrich Weigand     /// s390x TLS GDCall - marker to enable optimization of TLS calls
13250fcab29SUlrich Weigand     S390xTlsGdCall,
133438fc938SAlex Crichton 
13462276749SAlex Crichton     /// Pulley - a relocation which is a pc-relative offset.
13562276749SAlex Crichton     PulleyPcRel,
13662276749SAlex Crichton 
137438fc938SAlex Crichton     /// Pulley - call a host function indirectly where the embedder resolving
1382f7b0f58SAlex Crichton     /// this relocation needs to fill the 8-bit immediate that's part of the
1392f7b0f58SAlex Crichton     /// `call_indirect_host` opcode (an opaque identifier used by the host).
140438fc938SAlex Crichton     PulleyCallIndirectHost,
141747ad3c4Slazypassion }
142747ad3c4Slazypassion 
143747ad3c4Slazypassion impl fmt::Display for Reloc {
144747ad3c4Slazypassion     /// Display trait implementation drops the arch, since its used in contexts where the arch is
145747ad3c4Slazypassion     /// already unambiguous, e.g. clif syntax with isa specified. In other contexts, use Debug.
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result146747ad3c4Slazypassion     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147747ad3c4Slazypassion         match *self {
1489f506692SPeter Huene             Self::Abs4 => write!(f, "Abs4"),
1499f506692SPeter Huene             Self::Abs8 => write!(f, "Abs8"),
150e1cc1a67SUlrich Weigand             Self::S390xPCRel32Dbl => write!(f, "PCRel32Dbl"),
151be36dd6bSUlrich Weigand             Self::S390xPLTRel32Dbl => write!(f, "PLTRel32Dbl"),
1529f506692SPeter Huene             Self::X86PCRel4 => write!(f, "PCRel4"),
1539f506692SPeter Huene             Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
1549f506692SPeter Huene             Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
1559f506692SPeter Huene             Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
156c5bc368cSAfonso Bordado             Self::X86SecRel => write!(f, "SecRel"),
15759e18b7dSbjorn3             Self::Arm32Call | Self::Arm64Call => write!(f, "Call"),
158ecc1b794SAfonso Bordado             Self::RiscvCallPlt => write!(f, "RiscvCallPlt"),
159b23f534cSAfonso Bordado             Self::RiscvTlsGdHi20 => write!(f, "RiscvTlsGdHi20"),
160ecc1b794SAfonso Bordado             Self::RiscvGotHi20 => write!(f, "RiscvGotHi20"),
161*13b300deSAlex Crichton             Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"),
162b23f534cSAfonso Bordado             Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
1630a1bb3baSbjorn3             Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
1640a1bb3baSbjorn3             Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
165c3decdf9SNathan Whitaker             Self::MachOAarch64TlsAdrPage21 => write!(f, "MachOAarch64TlsAdrPage21"),
166c3decdf9SNathan Whitaker             Self::MachOAarch64TlsAdrPageOff12 => write!(f, "MachOAarch64TlsAdrPageOff12"),
167ccaf2bfaSAfonso Bordado             Self::Aarch64TlsDescAdrPage21 => write!(f, "Aarch64TlsDescAdrPage21"),
168ccaf2bfaSAfonso Bordado             Self::Aarch64TlsDescLd64Lo12 => write!(f, "Aarch64TlsDescLd64Lo12"),
169ccaf2bfaSAfonso Bordado             Self::Aarch64TlsDescAddLo12 => write!(f, "Aarch64TlsDescAddLo12"),
170ccaf2bfaSAfonso Bordado             Self::Aarch64TlsDescCall => write!(f, "Aarch64TlsDescCall"),
171eabd43a1SAfonso Bordado             Self::Aarch64AdrGotPage21 => write!(f, "Aarch64AdrGotPage21"),
172eabd43a1SAfonso Bordado             Self::Aarch64Ld64GotLo12Nc => write!(f, "Aarch64AdrGotLo12Nc"),
17310d2cbc5SAlex Crichton             Self::Aarch64AdrPrelPgHi21 => write!(f, "Aarch64AdrPrelPgHi21"),
17410d2cbc5SAlex Crichton             Self::Aarch64AddAbsLo12Nc => write!(f, "Aarch64AddAbsLo12Nc"),
17550fcab29SUlrich Weigand             Self::S390xTlsGd64 => write!(f, "TlsGd64"),
17650fcab29SUlrich Weigand             Self::S390xTlsGdCall => write!(f, "TlsGdCall"),
17762276749SAlex Crichton             Self::PulleyPcRel => write!(f, "PulleyPcRel"),
178438fc938SAlex Crichton             Self::PulleyCallIndirectHost => write!(f, "PulleyCallIndirectHost"),
179747ad3c4Slazypassion         }
180747ad3c4Slazypassion     }
181747ad3c4Slazypassion }
182747ad3c4Slazypassion 
183420850adSLars T Hansen /// Container for information about a vector of compiled code and its supporting read-only data.
184420850adSLars T Hansen ///
185420850adSLars T Hansen /// The code starts at offset 0 and is followed optionally by relocatable jump tables and copyable
186420850adSLars T Hansen /// (raw binary) read-only data.  Any padding between sections is always part of the section that
187420850adSLars T Hansen /// precedes the boundary between the sections.
1888a9b1a90SBenjamin Bouvier #[derive(Debug, PartialEq)]
189420850adSLars T Hansen pub struct CodeInfo {
190420850adSLars T Hansen     /// Number of bytes in total.
191420850adSLars T Hansen     pub total_size: CodeOffset,
192420850adSLars T Hansen }
193