1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
mod memorysink;
mod relaxation;
mod shrink;
pub use self::memorysink::{MemoryCodeSink, RelocSink, TrapSink, NullTrapSink};
pub use self::relaxation::relax_branches;
pub use self::shrink::shrink_instructions;
pub use regalloc::RegDiversions;
use ir::{ExternalName, Function, Inst, JumpTable, SourceLoc, TrapCode};
use std::fmt;
pub type CodeOffset = u32;
pub type Addend = i64;
#[derive(Copy, Clone, Debug)]
pub enum Reloc {
Abs4,
Abs8,
X86PCRel4,
X86GOTPCRel4,
X86PLTRel4,
Arm32Call,
Arm64Call,
RiscvCall,
}
impl fmt::Display for Reloc {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Reloc::Abs4 => write!(f, "Abs4"),
Reloc::Abs8 => write!(f, "Abs8"),
Reloc::X86PCRel4 => write!(f, "PCRel4"),
Reloc::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
Reloc::X86PLTRel4 => write!(f, "PLTRel4"),
Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "Call"),
}
}
}
pub trait CodeSink {
fn offset(&self) -> CodeOffset;
fn put1(&mut self, u8);
fn put2(&mut self, u16);
fn put4(&mut self, u32);
fn put8(&mut self, u64);
fn reloc_ebb(&mut self, Reloc, CodeOffset);
fn reloc_external(&mut self, Reloc, &ExternalName, Addend);
fn reloc_jt(&mut self, Reloc, JumpTable);
fn trap(&mut self, TrapCode, SourceLoc);
}
#[cold]
pub fn bad_encoding(func: &Function, inst: Inst) -> ! {
panic!(
"Bad encoding {} for {}",
func.encodings[inst],
func.dfg.display_inst(inst, None)
);
}
pub fn emit_function<CS, EI>(func: &Function, emit_inst: EI, sink: &mut CS)
where
CS: CodeSink,
EI: Fn(&Function, Inst, &mut RegDiversions, &mut CS),
{
let mut divert = RegDiversions::new();
for ebb in func.layout.ebbs() {
divert.clear();
debug_assert_eq!(func.offsets[ebb], sink.offset());
for inst in func.layout.ebb_insts(ebb) {
emit_inst(func, inst, &mut divert, sink);
}
}
}