Skip to main content

Target

Struct Target 

Source
pub struct Target { /* private fields */ }
Expand description

A target: register file, classes, instructions, and the registers with fixed jobs.

Targets are static data; x86_64::TARGET is the one this release ships.

§Examples

use backend_lang::x86_64::{self, RSP, RBP, FLAGS};

let t = &x86_64::TARGET;
assert_eq!(t.name(), "x86-64");
assert_eq!(t.stack_pointer(), RSP);
assert_eq!(t.frame_pointer(), RBP);
assert_eq!(t.flags(), Some(FLAGS));

Implementations§

Source§

impl Target

Source

pub const fn new( name: &'static str, isa: Isa, regs: &'static [RegInfo], classes: &'static [ClassInfo], insts: &'static [InstDesc], config: TargetConfig, ) -> Target

Describes a target.

insts must begin with the Opcode::COPY and Opcode::PCOPY descriptions (see Target::generic_insts); registers’ classes must index classes; at most MAX_PREGS registers. The crate’s own targets are checked by its tests; a hand-made one that breaks these rules is caught by Function::verify as operands that fit no class.

§Examples

A variant of x86-64 without xchg, to make the parallel-move resolver break cycles through a scratch register instead:

use backend_lang::target::{MoveCaps, ImmRange, Target, TargetConfig};
use backend_lang::x86_64;

let base = &x86_64::TARGET;
let mut cfg = TargetConfig::of(base);
cfg.move_caps = MoveCaps::new(false, false, ImmRange::I32);
let no_swap = Target::new("x86-64-noswap", base.isa(), base.regs(), base.classes(), base.insts(), cfg);
assert!(!no_swap.move_caps().swap());
Source

pub const fn generic_insts() -> [InstDesc; 2]

The two generic descriptions every instruction table starts with, Opcode::COPY then Opcode::PCOPY.

§Examples
use backend_lang::target::{InstKind, Target};

let [copy, pcopy] = Target::generic_insts();
assert_eq!(copy.kind(), InstKind::Copy);
assert_eq!(pcopy.name(), "pcopy");
Source

pub const fn name(&self) -> &'static str

The target’s name.

§Examples
use backend_lang::x86_64;

assert_eq!(x86_64::TARGET.name(), "x86-64");
Source

pub const fn isa(&self) -> Isa

The ISA, which selects the encoder.

§Examples
use backend_lang::target::Isa;
use backend_lang::x86_64;

assert_eq!(x86_64::TARGET.isa(), Isa::X86_64);
Source

pub const fn regs(&self) -> &'static [RegInfo]

The register file, indexed by PReg::index.

§Examples
use backend_lang::x86_64;

assert_eq!(x86_64::TARGET.regs().len(), 33);
Source

pub fn reg(&self, reg: PReg) -> &RegInfo

One register’s description. An index the target does not have gets a placeholder named <invalid>, in no class.

§Examples
use backend_lang::PReg;
use backend_lang::x86_64::{self, RDI};

assert_eq!(x86_64::TARGET.reg(RDI).name(), "rdi");
assert_eq!(x86_64::TARGET.reg(PReg::new(100).unwrap()).name(), "<invalid>");
Source

pub fn has_reg(&self, reg: PReg) -> bool

Whether the target has a register with this index.

§Examples
use backend_lang::PReg;
use backend_lang::x86_64::{self, RAX};

assert!(x86_64::TARGET.has_reg(RAX));
assert!(!x86_64::TARGET.has_reg(PReg::new(100).unwrap()));
Source

pub const fn classes(&self) -> &'static [ClassInfo]

The class table, indexed by RegClass::index.

§Examples
use backend_lang::x86_64;

assert_eq!(x86_64::TARGET.classes().len(), 3);
Source

pub fn class(&self, class: RegClass) -> &ClassInfo

One class’s description. A class the target does not have gets an empty placeholder named <invalid>.

§Examples
use backend_lang::RegClass;
use backend_lang::x86_64::{self, GPR};

assert_eq!(x86_64::TARGET.class(GPR).name(), "gpr");
assert!(x86_64::TARGET.class(RegClass::new(9)).regs().is_empty());
Source

pub fn has_class(&self, class: RegClass) -> bool

Whether the target has this class.

§Examples
use backend_lang::RegClass;
use backend_lang::x86_64::{self, VEC};

assert!(x86_64::TARGET.has_class(VEC));
assert!(!x86_64::TARGET.has_class(RegClass::new(9)));
Source

pub const fn insts(&self) -> &'static [InstDesc]

The instruction table, indexed by Opcode::index.

§Examples
use backend_lang::x86_64;

assert!(x86_64::TARGET.insts().len() > 80);
Source

pub fn inst(&self, opcode: Opcode) -> Option<&'static InstDesc>

One instruction’s description, or None for an opcode the target does not have.

§Examples
use backend_lang::target::Opcode;
use backend_lang::x86_64::{self, op};

assert!(x86_64::TARGET.inst(op::LEA64).is_some());
assert!(x86_64::TARGET.inst(Opcode::new(60000)).is_none());
Source

pub fn opcode(&self, name: &str) -> Option<Opcode>

The opcode whose MIR name is name, by a scan of the table.

§Examples
use backend_lang::x86_64::{self, op};

assert_eq!(x86_64::TARGET.opcode("sub32"), Some(op::SUB32));
assert_eq!(x86_64::TARGET.opcode("frobnicate"), None);
Source

pub const fn stack_pointer(&self) -> PReg

The stack pointer.

§Examples
use backend_lang::x86_64::{self, RSP};

assert_eq!(x86_64::TARGET.stack_pointer(), RSP);
Source

pub const fn frame_pointer(&self) -> PReg

The frame pointer.

§Examples
use backend_lang::x86_64::{self, RBP};

assert_eq!(x86_64::TARGET.frame_pointer(), RBP);
Source

pub const fn flags(&self) -> Option<PReg>

The condition-flags register, modelled as a physical register so that flag producers and consumers are ordinary implicit definitions and uses.

§Examples
use backend_lang::x86_64::{self, FLAGS};

assert_eq!(x86_64::TARGET.flags(), Some(FLAGS));
Source

pub const fn addr_class(&self) -> RegClass

The class of memory operands’ base and index registers.

§Examples
use backend_lang::x86_64::{self, GPR};

assert_eq!(x86_64::TARGET.addr_class(), GPR);
Source

pub const fn move_caps(&self) -> MoveCaps

How values move on this target.

§Examples
use backend_lang::x86_64;

assert!(x86_64::TARGET.move_caps().swap());
Source

pub const fn max_mem_operands(&self) -> u8

The most memory operands one instruction may have (one on x86-64).

§Examples
use backend_lang::x86_64;

assert_eq!(x86_64::TARGET.max_mem_operands(), 1);
Source

pub const fn conds(&self) -> u8

The number of condition codes; a Cond operand is below it.

§Examples
use backend_lang::x86_64;

assert_eq!(x86_64::TARGET.conds(), 16);
Source

pub fn cond_name(&self, cond: CondCode) -> &'static str

A condition code’s name (<invalid> for one the target does not have).

§Examples
use backend_lang::mir::CondCode;
use backend_lang::x86_64;

assert_eq!(x86_64::TARGET.cond_name(CondCode::new(4)), "e");
assert_eq!(x86_64::TARGET.cond_name(CondCode::new(99)), "<invalid>");
Source

pub fn class_of(&self, reg: PReg) -> Option<RegClass>

The class of a physical register, or None if the target does not have it.

§Examples
use backend_lang::x86_64::{self, GPR, R8};

assert_eq!(x86_64::TARGET.class_of(R8), Some(GPR));

Trait Implementations§

Source§

impl Debug for Target

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.