llvm_codegen/
assembler.rs1use crate::emit::{emit_object, Emitter, ObjectFile};
8use crate::isel::MachineFunction;
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
12pub struct McAssemblyReport {
13 pub section_count: usize,
15 pub symbol_count: usize,
17 pub reloc_count: usize,
19 pub bytes: usize,
21}
22
23#[derive(Clone, Debug)]
25pub struct AssembledObject {
26 pub object: ObjectFile,
28 pub bytes: Vec<u8>,
30 pub report: McAssemblyReport,
32}
33
34pub trait McAssembler {
36 fn assemble_object(&mut self, mf: &MachineFunction, emitter: &mut dyn Emitter) -> ObjectFile;
37
38 fn assemble(&mut self, mf: &MachineFunction, emitter: &mut dyn Emitter) -> AssembledObject {
39 let object = self.assemble_object(mf, emitter);
40 let bytes = object.to_bytes();
41 let reloc_count = object.sections.iter().map(|s| s.relocs.len()).sum();
42 let report = McAssemblyReport {
43 section_count: object.sections.len(),
44 symbol_count: object.symbols.len(),
45 reloc_count,
46 bytes: bytes.len(),
47 };
48 AssembledObject {
49 object,
50 bytes,
51 report,
52 }
53 }
54}
55
56#[derive(Clone, Copy, Debug, Default)]
58pub struct IntegratedAssembler;
59
60impl McAssembler for IntegratedAssembler {
61 fn assemble_object(&mut self, mf: &MachineFunction, emitter: &mut dyn Emitter) -> ObjectFile {
62 emit_object(mf, emitter)
63 }
64}
65
66pub fn assemble_object(mf: &MachineFunction, emitter: &mut dyn Emitter) -> ObjectFile {
68 IntegratedAssembler.assemble_object(mf, emitter)
69}
70
71pub fn assemble_bytes(mf: &MachineFunction, emitter: &mut dyn Emitter) -> Vec<u8> {
73 IntegratedAssembler.assemble(mf, emitter).bytes
74}
75
76pub fn assemble_with_report(mf: &MachineFunction, emitter: &mut dyn Emitter) -> AssembledObject {
78 IntegratedAssembler.assemble(mf, emitter)
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::emit::{ObjectFormat, Section, Symbol};
85 use crate::isel::{MachineBlock, MachineFunction};
86
87 struct NopEmitter;
88 impl Emitter for NopEmitter {
89 fn emit_function(&mut self, _mf: &MachineFunction) -> Section {
90 Section {
91 name: ".text".into(),
92 data: vec![0x90, 0xC3],
93 relocs: vec![],
94 debug_rows: vec![],
95 }
96 }
97 fn object_format(&self) -> ObjectFormat {
98 ObjectFormat::Elf
99 }
100 }
101
102 #[test]
103 fn integrated_assembler_produces_nonempty_bytes() {
104 let mut mf = MachineFunction::new("f".into());
105 mf.blocks.push(MachineBlock {
106 label: "entry".into(),
107 instrs: vec![],
108 });
109 let mut emitter = NopEmitter;
110 let assembled = assemble_with_report(&mf, &mut emitter);
111 assert!(!assembled.bytes.is_empty());
112 assert_eq!(
113 assembled.report.section_count,
114 assembled.object.sections.len()
115 );
116 }
117
118 #[test]
119 fn report_counts_sections_symbols_and_relocs() {
120 let object = ObjectFile {
121 format: ObjectFormat::Elf,
122 elf_machine: 62,
123 coff_machine: 0x8664,
124 sections: vec![Section {
125 name: ".text".into(),
126 data: vec![0xC3],
127 relocs: vec![],
128 debug_rows: vec![],
129 }],
130 symbols: vec![Symbol {
131 name: "f".into(),
132 section: 0,
133 offset: 0,
134 size: 1,
135 global: true,
136 }],
137 };
138 let bytes = object.to_bytes();
139 let report = McAssemblyReport {
140 section_count: object.sections.len(),
141 symbol_count: object.symbols.len(),
142 reloc_count: object.sections.iter().map(|s| s.relocs.len()).sum(),
143 bytes: bytes.len(),
144 };
145 assert_eq!(report.section_count, 1);
146 assert_eq!(report.symbol_count, 1);
147 assert_eq!(report.reloc_count, 0);
148 assert!(report.bytes > 0);
149 }
150}