Skip to main content

Program

Struct Program 

Source
pub struct Program {
Show 15 fields pub unit_id: u64, pub types: Types, pub objects: Vec<Object>, pub statics: Vec<StaticVar>, pub externs: Vec<ObjectId>, pub functions: Vec<Function>, pub calls: Vec<CallEdge>, pub typedefs: Vec<TypedefItem>, pub enum_constants: Vec<Enumerator>, pub strings: Vec<StrData>, pub link_libraries: Vec<String>, pub export: bool, pub cpu_supports: Vec<SourceRange>, pub no_std: bool, pub crate_path: String,
}
Expand description

Everything one translation unit generates.

Fields§

§unit_id: u64

A hash of the invocation site, used to build the synthetic item names that must not collide between two c99! blocks in one module.

§types: Types

Every derived and tagged type.

§objects: Vec<Object>

Every named object, indexed by ObjectId.

§statics: Vec<StaticVar>

The objects that become static mut items, in declaration order.

§externs: Vec<ObjectId>

The objects declared extern, in declaration order.

§functions: Vec<Function>

Every function, indexed by FuncId, in declaration order.

§calls: Vec<CallEdge>

Every direct call the unit’s bodies make; see CallEdge.

§typedefs: Vec<TypedefItem>

The file-scope typedefs, in declaration order.

§enum_constants: Vec<Enumerator>

The enum constants that become Rust const items, in order.

§strings: Vec<StrData>

Every string literal, indexed by StrId.

§link_libraries: Vec<String>

The libraries the unit must be linked against, named by #pragma cinrs link "…".

Filled in after semantic analysis: it is the preprocessor that reads the pragma, and nothing about the program itself depends on it.

§export: bool

Whether #pragma cinrs export asked for every function and object with external linkage to become a real C symbol.

Filled in after semantic analysis, for the same reason as Program::link_libraries.

§cpu_supports: Vec<SourceRange>

Every __builtin_cpu_supports the unit wrote, by where it was written.

It becomes ::std::is_x86_feature_detected!, and core has no CPU detection at all — so a unit that said #pragma cinrs no_std cannot have one. The pragma is only known after semantic analysis, which is why the sites are collected rather than checked where they are met; see crate::sema::check_pragmas.

§no_std: bool

Whether #pragma cinrs no_std said the expansion goes into a #![no_std] crate.

Everything generated is core-only except the storage a variable length array and alloca need, which is a bump arena made of Vecs; this decides whether they are spelled ::std::vec::Vec or ::alloc::vec::Vec. Filled in after semantic analysis, for the same reason as Program::link_libraries.

§crate_path: String

The Rust path of the cinrs facade crate, which the generated code names when it needs the runtime: ::cinrs unless #pragma cinrs crate "…" said otherwise.

Only a unit that uses a complex type spells it at all. Filled in after semantic analysis, for the same reason as Program::link_libraries.

Implementations§

Source§

impl Program

Source

pub fn object(&self, id: ObjectId) -> &Object

Looks an object up.

§Panics

Panics if id did not come from this program.

Source

pub fn function(&self, id: FuncId) -> &Function

Looks a function up.

§Panics

Panics if id did not come from this program.

Source

pub fn string(&self, id: StrId) -> &StrData

Looks a string literal up.

§Panics

Panics if id did not come from this program.

Source

pub fn extern_object_name(&self, symbol: &str) -> String

The hidden Rust name an externally linked object is declared under.

Only an object. A function the unit merely declares is generated under its own C name, like everything else the unit spells, so that #include <zlib.h> is enough for Rust to call crc32; an object is not, and the difference is Rust’s rule for patterns rather than a matter of taste.

A glob-imported function cannot change the meaning of Rust code that does not mention it: a function is not a pattern, so let read = 1; beside a unit that declares read is still a new binding. A glob imported static can. Rust resolves a binding pattern against the value namespace first, and a static there is not a name a let may shadow:

error[E0530]: let bindings cannot shadow statics

— which is what let stdout = std::io::stdout(); would become next to a block that includes <stdio.h>, and let timezone = … next to one that includes glibc’s <time.h>. optarg, optind and environ are the same story. So a declared-only object keeps a name of its own, __cinrs_<unit>_<symbol>, and Rust reaches it the way C code does in the same situation: through an accessor written in the block, FILE *get_stdout(void) { return stdout; }.

The C code in the unit is unaffected either way — it refers to the object by its C name, and this is only the Rust side of that.

A module of its own for the extern block would have avoided the question altogether, but a module cannot see the struct items of the block it is written in, which an extern declaration taking a struct needs.

A $ in the C name — an identifier character here, and one Rust has no spelling for — is written crate::codegen::DOLLAR; the symbol the declaration links by is a #[link_name] string and keeps the $.

Source

pub fn has_externs(&self) -> bool

Whether anything at all has to go into the extern block.

An x86 intrinsic does not count: it is declared like any other function and generated as a call to core::arch, so a unit whose only declarations came from <immintrin.h> needs no block at all.

Trait Implementations§

Source§

impl Clone for Program

Source§

fn clone(&self) -> Self

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 Debug for Program

Source§

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

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

impl Default for Program

Source§

fn default() -> Self

Returns the “default value” for a type. 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> 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.