Skip to main content

Flags

Struct Flags 

Source
pub struct Flags(/* private fields */);
Expand description

The flags on one instruction.

A bitset rather than a struct of bools, because it rides along in the instruction table and two bytes there is two bytes per instruction in every function in the program.

Implementations§

Source§

impl Flags

Source

pub const NONE: Self

No flags, which is what -O0 and -fwrapv and a plain unsigned addition all produce.

Source

pub const NSW: Self

No signed wrap. Signed overflow is undefined, so the optimizer may assume it does not happen. -fwrapv stops the frontend setting this and nothing else changes.

Source

pub const NUW: Self

No unsigned wrap. Set only where the frontend knows it from the source, since C’s unsigned arithmetic wraps by definition and most unsigned arithmetic does not get this.

Source

pub const EXACT: Self

The shift or division is exact, so no bits are discarded and no remainder is dropped.

Source

pub const NNAN: Self

No NaN operands or results.

Source

pub const NINF: Self

No infinite operands or results.

Source

pub const NSZ: Self

The sign of a zero does not matter.

Source

pub const ARCP: Self

A division may become a multiplication by the reciprocal.

Source

pub const CONTRACT: Self

A multiplication and an addition may be contracted into one rounding.

Source

pub const REASSOC: Self

The operation may be reassociated, which is the one that changes results the most.

Source

pub const VOLATILE: Self

The access is volatile, so it happens exactly once and is never moved or merged.

Source

pub const NOALIAS: Self

The result does not alias anything else reachable, which is what restrict gives.

Source

pub const NOFREE: Self

Nothing this call reaches ends the lifetime of any storage.

The nofree summary of spec/safe-memory/07-check-elimination.md section 7.5, written onto the call site by a module-level analysis rather than by the frontend. A pass carrying what an earlier safety check established keeps it across a call that has this and gives it up across a call that does not.

Source

pub const STATIC: Self

The bytes this safety check is about lie inside one object of static storage duration whose extent this module knows.

Section 7.2 of spec/safe-memory/07-check-elimination.md puts the frontend first of the four sources of a discharge, because most accesses in real C are to a local or a global at a constant offset and how big either one is is not something anybody has to work out. The local half is read straight off the alloca by the pass that removes the check. The global half is this flag, because a global’s size lives on the module and a pass is given one function, so a module-level analysis works it out before the pipeline starts and writes it onto the check.

A fact rather than a licence, like Flags::NOFREE and unlike everything above it. It says what is true of the bytes, and whether that is enough for the check to go is a rule.

Source

pub const HANDED: Self

The bytes this safety check is about lie inside one object that every call to this function hands it, and whose extent this module knows.

The same shape as Flags::STATIC and the next of the four sources section 7.2 lists, which is section 7.5’s summaries. A pointer that arrived as a parameter is a pointer nothing in the function can say anything about, and it is where most of the checks a real program keeps are. What can be said about it is said by the callers: if every call to a function only this module can call passes a frame slot or a global with at least so many bytes left in it, then the parameter has at least so many bytes wherever it is used.

Worked out over the module before the pipeline starts, for the reason Flags::STATIC gives: a call site is in a different function from the parameter it is about, and a pass is given one function.

It says the same two things Flags::STATIC says, an extent and a lifetime, because the objects it is ever about are a caller’s frame slot or a global and both of those are alive for as long as the call runs. A fact rather than a licence, in the same way.

Source

pub const HEAP: Self

This call hands back either null or one fresh storage instance of at least as many bytes as its last argument asks for.

The third of the objects whose extent is known without anybody having checked it, after the two Flags::STATIC and Flags::HANDED are about. malloc(n) states the same fact an alloca states, with a different instruction stating it, and the null half is why a program has to test what it gets: a null pointer is inside no object at all, so a bounds check on one is a check that is supposed to fail.

On the call rather than on the checks, which is the shape Flags::NOFREE has and not the shape the two flags above have. What has to be worked out before the pipeline starts is only which function this call names, because resolving a name takes the interner and a pass is handed a function and no names. Everything else, which is how many bytes and where the program has tested for null, is read out of the function by the pass that removes the check, and has to be: before anything has folded, malloc(16) is a call to malloc of a sign extension of a thirty two bit sixteen.

What it says is an extent, and never a lifetime, which is the difference from the two flags above. A global and a caller’s frame slot are alive for as long as the call runs, and an object on the heap is alive until something frees it, which may well be this same function. So a free between the allocation and the access leaves the lifetime check standing to report the use after free.

A fact rather than a licence, in the way Flags::NOFREE is.

Source

pub const ALIGNED: Self

The address the check this is on is about starts where the access assumes it does.

The alignment conjunct of judgement J1 rides on check_bounds, which spec/safe-memory/06-instrumentation.md section 6.3 settled, so a check that goes takes the test of it away with it and crate::discharge will not take one out until something has answered it. Mostly it answers itself, off the alloca or the allocation the address was computed from and the steps taken from there. This is the case it cannot: how aligned a global is lives on the module and a pass is given one function, which is the reason Flags::STATIC exists and the same reason repeated.

It says the address and not the object. A global aligned to sixteen read four bytes in at a width of four is one of these and the same global read one byte in is not, so what was worked out before the pipeline started is the offset as well as the object.

A fact rather than a licence, in the way Flags::STATIC is.

Source

pub const FAST: Self

Every fast-math flag, which is what -ffast-math sets on an expression.

Source

pub const fn bits(self) -> u16

The underlying bits, for the printer and for hashing an instruction.

Source

pub const fn is_empty(self) -> bool

Whether nothing is set.

Source

pub const fn contains(self, other: Self) -> bool

Whether every flag in other is set here.

Source

pub const fn union(self, other: Self) -> Self

Both sets.

Source

pub const fn intersection(self, other: Self) -> Self

The flags in both sets.

This is what a rewrite does when it replaces two instructions with one: a licence granted on one of them and not the other is not a licence over the result.

Source

pub const fn without(self, other: Self) -> Self

This set without the flags in other.

Source

pub const fn legal_on(opcode: Opcode) -> Self

The flags that mean anything on that opcode.

Anything outside this is a verifier failure rather than something ignored, because a flag on an instruction that does not read it is a flag somebody meant to put somewhere else.

Source

pub fn iter(self) -> impl Iterator<Item = (Self, &'static str)>

Every flag that is set, with its name, in the order the printer writes them.

Source

pub fn from_name(name: &str) -> Option<Self>

The flag with that name, if there is one.

Trait Implementations§

Source§

impl BitOr for Flags

Source§

type Output = Flags

The resulting type after applying the | operator.
Source§

fn bitor(self, other: Self) -> Self

Performs the | operation. Read more
Source§

impl BitOrAssign for Flags

Source§

fn bitor_assign(&mut self, other: Self)

Performs the |= operation. Read more
Source§

impl Clone for Flags

Source§

fn clone(&self) -> Flags

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 Flags

Source§

impl Debug for Flags

Source§

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

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

impl Default for Flags

Source§

fn default() -> Flags

Returns the “default value” for a type. Read more
Source§

impl Display for Flags

Source§

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

The suffix form the textual IR uses, add.nsw, with a leading dot on each flag and nothing at all when the set is empty.

Source§

impl Eq for Flags

Source§

impl Hash for Flags

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Flags

Source§

fn eq(&self, other: &Flags) -> 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 Flags

Auto Trait Implementations§

§

impl Freeze for Flags

§

impl RefUnwindSafe for Flags

§

impl Send for Flags

§

impl Sync for Flags

§

impl Unpin for Flags

§

impl UnsafeUnpin for Flags

§

impl UnwindSafe for Flags

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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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.