Skip to main content

CallRegs

Struct CallRegs 

Source
pub struct CallRegs {
Show 24 fields pub int_class: RegClass, pub sse_class: RegClass, pub int_args: &'static [PhysReg], pub sse_args: &'static [PhysReg], pub shared_positions: bool, pub int_returns: &'static [PhysReg], pub sse_returns: &'static [PhysReg], pub x87_returns: &'static [PhysReg], pub int_saved: &'static [PhysReg], pub sse_saved: &'static [PhysReg], pub int_order: &'static [PhysReg], pub sse_order: &'static [PhysReg], pub stack_pointer: PhysReg, pub frame_pointer: PhysReg, pub vector_count: Option<PhysReg>, pub red_zone: u32, pub shadow: u32, pub stack_align: u32, pub return_address: u32, pub word: u32, pub dwarf: &'static [&'static [u16]], pub dwarf_return_address: u16, pub guard: Option<Guard>, pub trace: Option<Trace>,
}
Expand description

Which registers a calling convention gives which job.

This is the second half of a target description and it is separate from RegFile because the two do not vary together. x86-64 has one register file and two conventions over it, and they disagree about nearly everything below: rdi is where the first argument arrives on SysV and a register a callee has to preserve on Windows, and a Windows caller reserves thirty two bytes below the call that a SysV caller does not.

The allocation order is here rather than on a class because it is a consequence of what a call clobbers. A value that does not live across a call belongs in a register the callee is free to destroy, because putting it in a preserved one costs a push and a pop in the prologue of whichever function ends up owning it.

Every register named here is a register of the file the same target describes, and each list is in the order the convention uses them, so the fourth integer argument is int_args[3] and nothing has to count.

Fields§

§int_class: RegClass

The class the general purpose registers named here are in.

A register is a number inside its class, so a list of them says nothing about which registers they are without this. Everything else could get the class from the operand it came off, and a frame cannot, because a saved register is not an operand of anything.

§sse_class: RegClass

The class the vector registers named here are in.

§int_args: &'static [PhysReg]

The general purpose registers integer arguments arrive in, in order.

§sse_args: &'static [PhysReg]

The vector registers floating point arguments arrive in, in order.

Whether an argument’s position counts against both lists or only against its own is CallRegs::shared_positions.

§shared_positions: bool

Whether an argument’s position counts against both argument lists or only against its own.

False on SysV, which counts each separately, so a double after six integers is still in xmm0. True on Windows, which counts one position for both, so a double in the third position is in xmm2 and r8 is skipped.

§int_returns: &'static [PhysReg]

The general purpose registers an integer return value comes back in.

§sse_returns: &'static [PhysReg]

The vector registers a floating point return value comes back in.

§x87_returns: &'static [PhysReg]

The x87 registers a long double comes back in, which is empty on a target whose long double is a double.

§int_saved: &'static [PhysReg]

The general purpose registers a call leaves alone, so a value in one survives it.

§sse_saved: &'static [PhysReg]

The vector registers a call leaves alone, which is none of them on SysV.

§int_order: &'static [PhysReg]

The general purpose registers the allocator may hand out, in the order it prefers them.

The stack pointer is never in this list, and neither is the frame pointer, which a target could allocate when nothing needs a frame and which nothing here does yet.

§sse_order: &'static [PhysReg]

The vector registers the allocator may hand out, in the order it prefers them.

§stack_pointer: PhysReg

The stack pointer.

§frame_pointer: PhysReg

The frame pointer, which is the register a prologue puts the old stack pointer in.

§vector_count: Option<PhysReg>

Where a variadic call says how many vector registers it passed arguments in, when the convention makes it say.

SysV puts the count in al and a variadic callee reads it to decide whether to save the vector argument registers at all, which is what makes a call to printf with no floating point argument cheap.

§red_zone: u32

How many bytes below the stack pointer a leaf function may use without moving it.

A hundred and twenty eight on SysV and nothing on Windows. It is nothing in kernel code on either, because an interrupt handler runs on the interrupted stack and writes over exactly this, which is what -mno-red-zone is for.

§shadow: u32

How many bytes a caller reserves below the call for the callee to spill its register arguments into, which is thirty two on Windows and nothing on SysV.

§stack_align: u32

What the stack pointer has to be a multiple of at the instruction that makes a call.

Sixteen on every convention here, and it is a real obligation rather than a preference, because a callee is entitled to use an aligned vector store on its own frame and gets a fault rather than a wrong answer when a caller got this wrong.

§return_address: u32

How many bytes the call instruction itself pushes before the callee starts running.

Eight on x86-64, where the return address is on the stack, and nothing on a machine that leaves it in a register. It is what makes the stack pointer misaligned on entry by exactly one word, which every frame layout has to undo.

§word: u32

How many bytes one general purpose register takes when it is saved on the stack.

§dwarf: &'static [&'static [u16]]

What DWARF calls each register, one list per class in the order the file numbers the classes, and inside a list in the order the class numbers its registers.

The two numberings are a real difference and not a formality. On x86-64 the machine puts rcx at one and DWARF puts rdx there, so a table written with the machine’s numbers is well formed and describes the wrong registers, which is a backtrace with plausible nonsense in it rather than an error. Shorter than the file when the classes at the end are ones DWARF has no column for, and empty on a target nobody has written this down for yet.

§dwarf_return_address: u16

The column an unwind table files the return address under.

Not a register on x86-64, where it is sixteen and rip is not a register anything can name, and a real one on a machine that returns through a link register.

§guard: Option<Guard>

Where the word a stack protector’s canary is copied from lives, on a convention that has somewhere to put one.

Here rather than beside the frame instructions because it is a fact about the runtime the code is linked against rather than about the machine. The two x86-64 conventions share every instruction the check is made of and disagree about this.

§trace: Option<Trace>

What a profiler’s hook is called on this platform, on one that has one.

Here for the same reason CallRegs::guard is: the names are the runtime’s rather than the machine’s, and the two x86-64 conventions write the same call instruction and disagree about what goes in it.

Implementations§

Source§

impl CallRegs

Source

pub fn dwarf(&self, class: RegClass, reg: PhysReg) -> Option<u16>

The number DWARF gives that register, or None for one it has no column for.

The x87 stack is the case that answers None on x86-64, and it is not an omission: a register whose name means whichever one is on top of the stack is not one a table can have a column for. Nothing saves one across a call either, so nothing ever asks.

Source

pub fn preserves_int(&self, reg: PhysReg) -> bool

Whether a call preserves that general purpose register.

Source

pub fn preserves_sse(&self, reg: PhysReg) -> bool

Whether a call preserves that vector register.

Trait Implementations§

Source§

impl Clone for CallRegs

Source§

fn clone(&self) -> CallRegs

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for CallRegs

Source§

impl Debug for CallRegs

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Eq for CallRegs

Source§

impl PartialEq for CallRegs

Source§

fn eq(&self, other: &CallRegs) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for CallRegs

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.