This also paves the way for unifying TargetIsa and MachBackend, since now they map one to one. In theory the two traits could be merged, which would be nice to limit the number of total concepts. Also they have quite different responsibilities, so it might be fine to keep them separate. Interestingly, this PR started as removing RegInfo from the TargetIsa trait since the adapter returned a dummy value there. From the fallout, noticed that all Display implementations didn't needed an ISA anymore (since these were only used to render ISA specific registers). Also the whole family of RegInfo / ValueLoc / RegUnit was exclusively used for the old backend, and these could be removed. Notably, some IR instructions needed to be removed, because they were using RegUnit too: this was the oddball of regfill / regmove / regspill / copy_special, which were IR instructions inserted by the old regalloc. Fare thee well!
134 lines
3.6 KiB
Rust
134 lines
3.6 KiB
Rust
//! 32-bit ARM Instruction Set Architecture.
|
|
|
|
use crate::ir::condcodes::IntCC;
|
|
use crate::ir::Function;
|
|
use crate::isa::Builder as IsaBuilder;
|
|
use crate::machinst::{
|
|
compile, MachBackend, MachCompileResult, MachTextSectionBuilder, TargetIsaAdapter,
|
|
TextSectionBuilder, VCode,
|
|
};
|
|
use crate::result::CodegenResult;
|
|
use crate::settings;
|
|
|
|
use alloc::{boxed::Box, vec::Vec};
|
|
use regalloc::{PrettyPrint, RealRegUniverse};
|
|
use target_lexicon::{Architecture, ArmArchitecture, Triple};
|
|
|
|
// New backend:
|
|
mod abi;
|
|
mod inst;
|
|
mod lower;
|
|
mod lower_inst;
|
|
|
|
use inst::{create_reg_universe, EmitInfo};
|
|
|
|
/// An ARM32 backend.
|
|
pub struct Arm32Backend {
|
|
triple: Triple,
|
|
flags: settings::Flags,
|
|
reg_universe: RealRegUniverse,
|
|
}
|
|
|
|
impl Arm32Backend {
|
|
/// Create a new ARM32 backend with the given (shared) flags.
|
|
pub fn new_with_flags(triple: Triple, flags: settings::Flags) -> Arm32Backend {
|
|
let reg_universe = create_reg_universe();
|
|
Arm32Backend {
|
|
triple,
|
|
flags,
|
|
reg_universe,
|
|
}
|
|
}
|
|
|
|
fn compile_vcode(
|
|
&self,
|
|
func: &Function,
|
|
flags: settings::Flags,
|
|
) -> CodegenResult<VCode<inst::Inst>> {
|
|
// This performs lowering to VCode, register-allocates the code, computes
|
|
// block layout and finalizes branches. The result is ready for binary emission.
|
|
let emit_info = EmitInfo::new(flags.clone());
|
|
let abi = Box::new(abi::Arm32ABICallee::new(func, flags)?);
|
|
compile::compile::<Arm32Backend>(func, self, abi, emit_info)
|
|
}
|
|
}
|
|
|
|
impl MachBackend for Arm32Backend {
|
|
fn compile_function(
|
|
&self,
|
|
func: &Function,
|
|
want_disasm: bool,
|
|
) -> CodegenResult<MachCompileResult> {
|
|
let flags = self.flags();
|
|
let vcode = self.compile_vcode(func, flags.clone())?;
|
|
let (buffer, bb_starts, bb_edges) = vcode.emit();
|
|
let frame_size = vcode.frame_size();
|
|
let stackslot_offsets = vcode.stackslot_offsets().clone();
|
|
|
|
let disasm = if want_disasm {
|
|
Some(vcode.show_rru(Some(&create_reg_universe())))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let buffer = buffer.finish();
|
|
|
|
Ok(MachCompileResult {
|
|
buffer,
|
|
frame_size,
|
|
disasm,
|
|
value_labels_ranges: Default::default(),
|
|
stackslot_offsets,
|
|
bb_starts,
|
|
bb_edges,
|
|
})
|
|
}
|
|
|
|
fn name(&self) -> &'static str {
|
|
"arm32"
|
|
}
|
|
|
|
fn triple(&self) -> Triple {
|
|
self.triple.clone()
|
|
}
|
|
|
|
fn flags(&self) -> &settings::Flags {
|
|
&self.flags
|
|
}
|
|
|
|
fn isa_flags(&self) -> Vec<settings::Value> {
|
|
Vec::new()
|
|
}
|
|
|
|
fn reg_universe(&self) -> &RealRegUniverse {
|
|
&self.reg_universe
|
|
}
|
|
|
|
fn unsigned_add_overflow_condition(&self) -> IntCC {
|
|
// Carry flag set.
|
|
IntCC::UnsignedGreaterThanOrEqual
|
|
}
|
|
|
|
fn text_section_builder(&self, num_funcs: u32) -> Box<dyn TextSectionBuilder> {
|
|
Box::new(MachTextSectionBuilder::<inst::Inst>::new(num_funcs))
|
|
}
|
|
}
|
|
|
|
/// Create a new `isa::Builder`.
|
|
pub fn isa_builder(triple: Triple) -> IsaBuilder {
|
|
assert!(match triple.architecture {
|
|
Architecture::Arm(ArmArchitecture::Arm)
|
|
| Architecture::Arm(ArmArchitecture::Armv7)
|
|
| Architecture::Arm(ArmArchitecture::Armv6) => true,
|
|
_ => false,
|
|
});
|
|
IsaBuilder {
|
|
triple,
|
|
setup: settings::builder(),
|
|
constructor: |triple, shared_flags, _| {
|
|
let backend = Arm32Backend::new_with_flags(triple, shared_flags);
|
|
Box::new(TargetIsaAdapter::new(backend))
|
|
},
|
|
}
|
|
}
|