Skip to main content

Options

Struct Options 

Source
#[non_exhaustive]
pub struct Options {
Show 44 fields pub target: Triple, pub opt_level: OptLevel, pub safety: Safety, pub emit: EmitKind, pub debug_info: bool, pub frame_pointer: bool, pub red_zone: bool, pub warnings_are_errors: bool, pub warnings: bool, pub error_limit: u32, pub std: Std, pub gnu_extensions: bool, pub pedantic: bool, pub permissive: bool, pub gnu89_inline: bool, pub visibility: Visibility, pub pic: Pic, pub interposition: bool, pub async_unwind_tables: bool, pub unwind_tables: bool, pub function_sections: bool, pub data_sections: bool, pub gnuc: GnucVersion, pub hosted: bool, pub builtins: bool, pub no_builtin: Vec<String>, pub defines: Vec<String>, pub undefines: Vec<String>, pub search: SearchPath, pub preincludes: Vec<Preinclude>, pub line_markers: bool, pub dumps: Dumps, pub deps: Deps, pub save_temps: SaveTemps, pub time: bool, pub passes: Vec<(String, bool)>, pub pass_fuel: Vec<(String, u32)>, pub pass_fuel_global: Option<u32>, pub pass_gates: Vec<(bool, String)>, pub dump_ir: Vec<String>, pub opt_info: Vec<String>, pub opt_info_file: Option<String>, pub verify_each: bool, pub rule_coverage: Option<String>,
}
Expand description

Everything a compilation was asked to do.

Options are a plain value with no interior mutability, so a caller can build one, clone it, tweak one field and run a second compilation, which is exactly what the differential testing in spec/15-testing.md needs.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§target: Triple

The target to generate code for.

§opt_level: OptLevel

The optimisation level.

§safety: Safety

How much of the memory safety monitor is on, from -fsafety=.

Off unless it was asked for. A program built without the flag is compiled by exactly the pipeline it was compiled by before the monitor existed, which is the only way the feature can be developed in the open without every build paying for it.

§emit: EmitKind

What to produce.

§debug_info: bool

Whether to emit debug information.

§frame_pointer: bool

Whether every function keeps a frame pointer, from -fno-omit-frame-pointer.

Off by default, which is what gcc does at every level above -O0 and what leaves the register free for the allocator. A profiler that walks the stack by following saved frame pointers needs it on, and so does any code a debugger has to unwind without unwind tables.

§red_zone: bool

Whether the red zone may be used, from -mno-red-zone turned around.

The 128 bytes below the stack pointer that the System V psABI promises no signal handler will touch, which lets a small leaf function keep its locals without moving the stack pointer at all. A kernel turns this off, because an interrupt taken on the kernel stack makes the promise false, and every kernel build in the wild passes -mno-red-zone for exactly that reason. A convention without a red zone ignores this.

§warnings_are_errors: bool

Whether warnings are errors.

§warnings: bool

Whether a warning is raised at all, which is -w turned around.

A build that passes this has decided it does not want to hear about anything that is not fatal, and the flag is dropped at the one place every diagnostic goes through rather than tested at each site that raises one. -w beats -Werror where both are given, because a warning that was never raised cannot be promoted.

§error_limit: u32

How many diagnostics to print before giving up. Past a certain point the output is noise from a single earlier mistake, and GCC’s default of no limit is not a kindness.

§std: Std

The dialect, from -std=.

§gnu_extensions: bool

Whether the GNU extensions are on, which is -std=gnu23 rather than -std=c23.

§pedantic: bool

Whether -pedantic was given, which is what turns a use of an extension from silence into a diagnostic. It is not the same knob as the dialect: -std=c17 -pedantic warns about a construct that -std=c17 alone accepts without a word.

§permissive: bool

Whether -fpermissive was given, which turns the rules gcc 14 promoted from errors back into warnings.

Six of them, all about code written before the language settled: a declaration with no type in it, a call to a function nothing declared, a parameter in an old style definition with no type, a pointer made from an integer, a pointer assigned from a pointer to something else, and a return whose value disagrees with what was promised. The flag says nothing about any other diagnostic, and it does not say to compile something different: a program it accepts is compiled the way the rule it broke says it means.

§gnu89_inline: bool

Whether the whole unit is under GNU’s reading of inline rather than C’s, which is -fgnu89-inline.

Under C’s reading a definition every file-scope declaration wrote inline for and none wrote extern for emits nothing, and under GNU’s it is the definition alone that decides and extern inline is the one that emits nothing. The C89 dialects are under GNU’s whatever this says, since that is where the older reading came from, so this is the flag a program written against it reaches for when it is being compiled under a later dialect.

§visibility: Visibility

What a name that nothing in the source said anything about reaches, from -fvisibility=.

§pic: Pic

Whether the object may end up in a shared library, from -fPIC and -fPIE.

§interposition: bool

Whether a definition in this unit may be replaced at load time by one in another object, from -fsemantic-interposition and -fno-semantic-interposition.

True is the honest answer and is gcc’s default, because that is what an exported name in a shared library means: the dynamic linker takes the first definition it finds in load order, so a function this unit defines and calls may not be the one that runs. Everything the optimizer reads off a body has to stop at a name like that.

False is a promise the build makes, and every distribution makes it, because otherwise a library cannot inline its own functions into each other. It is a promise rather than a deduction: nothing checks it, and a program that then interposes one of those names gets a mixture of the two definitions. It says nothing about -fPIE, where no name is replaceable to begin with, and it says nothing about how an address is reached, which is the separate question -fPIC decides.

§async_unwind_tables: bool

Whether a function is described to an unwinder at every instruction, from -fasynchronous-unwind-tables and -fno-asynchronous-unwind-tables.

True is the default, which is gcc’s wherever anything reads the table, and the reason is that the programs that read it are not the ones being compiled. C++ exceptions, backtrace, a profiler sampling a stack and a crash handler printing one all walk frames belonging to code that knew nothing about them, so a unit that opts out stops a walk that started somewhere else.

What asynchronous asks for on top of a table is that the answer is right at every instruction and not only where a call is, because a signal can arrive anywhere, including the middle of a prologue. Rows come off the prologue as it is built here, so that is the only kind of table there is to write and the weaker request below is answered with it.

False is for a build that knows nothing will ever walk it, which in practice is a kernel or a freestanding image, and what it saves is the section rather than any instruction.

§unwind_tables: bool

Whether a function is described to an unwinder at all, from -funwind-tables and -fno-unwind-tables.

The weaker of the two requests and off by default, because the one above is on and implies it. A table is written when either of them is standing, which is what Self::unwinds answers and is how gcc resolves a line that asks for a table and against an asynchronous one.

Neither of them is about anything but ELF. Mach-O and COFF have their own arrangements and neither is written yet, so on those targets nothing reads these.

§function_sections: bool

Whether each function gets a section of its own, from -ffunction-sections.

A linker can leave out a section nothing reaches and cannot leave out half of one, so this is what makes --gc-sections able to drop a function this file defines and nothing calls. A kernel and an embedded image are both linked that way and are both a good deal larger without it, and the cost is one section header per function.

§data_sections: bool

Whether each variable gets a section of its own, from -fdata-sections.

The same bargain for the data, and a separate flag because gcc has two of them: a build that wants one and not the other is a build that measured something. Splitting the data can cost more than it saves, since two variables a loop reads together are no longer certain to land in the same page.

§gnuc: GnucVersion

The GCC release claimed, from -fgnuc-version=.

§hosted: bool

Whether there is a standard library, which is -ffreestanding turned around.

§builtins: bool

Whether a call to a C library function written under its own plain name may be taken to mean that function, which is -fno-builtin turned around.

The names are reserved, so llabs is the library’s llabs and the compiler is allowed to know what it does. A program that means something else by one of them is the reason the flag exists, and -ffreestanding turns it off as well, because a freestanding program has no C library for the name to be the name of. The __builtin_ spellings are not affected by either, since the prefix is the program saying which function it means.

§no_builtin: Vec<String>

The names -fno-builtin-<name> took away one at a time, without the prefix.

A build that means its own memcpy and the library’s everything else writes this rather than the whole flag, which is what the kernel does for a handful of names.

§defines: Vec<String>

-D in command line order. FOO means FOO=1, as GCC has it.

§undefines: Vec<String>

-U in command line order, applied after the defines because -U wins.

§search: SearchPath

Where a header is looked for.

§preincludes: Vec<Preinclude>

What -imacros and -include named, in command line order.

§line_markers: bool

Whether -E writes line markers, which -P turns off.

§dumps: Dumps

What the -d family asks for.

§deps: Deps

What the -M family asks for.

§save_temps: SaveTemps

Whether the intermediate files are kept, from -save-temps.

§time: bool

Whether each step says how long it took, from -time.

§passes: Vec<(String, bool)>

What -f<pass> and -fno-<pass> said about an optimizer pass, in the order the command line said it, so that the last mention of a pass is the one that decides.

The pipeline the level chose is the starting point and this is what is added to and taken away from it. The names are checked against the pass list while the arguments are parsed, so anything in here is a pass the compiler has.

§pass_fuel: Vec<(String, u32)>

What -fpass-fuel=<pass>=<n> limited a pass to, by pass name.

A pass with an entry here performs exactly that many transformations and then stops transforming, which is what bisects a miscompilation to one rewrite. See section 9.10 of spec/09-optimizer.md.

§pass_fuel_global: Option<u32>

What -fpass-fuel-global=<n> limited the whole pipeline to, across every pass.

The outer of the two searches in section 4.5 of spec/optimizer/04-pass-manager.md. Halving this says which pass holds the bad rewrite, and halving -fpass-fuel for that pass says which rewrite it is. Where both are given, a pass is stopped by whichever of the two is tighter.

§pass_gates: Vec<(bool, String)>

What -fdisable-<pass>[=<range>] and -fenable-<pass>[=<range>] said, in the order the command line said it, with true for the enabling half.

A rule covers the functions it names and nothing else, and the last rule that covers a function is the one that decides for it, so the order has to survive. This is the second half of the bisection interface in section 41.6 of spec/optimizer/41-correctness.md: -fpass-fuel finds the rewrite and this finds the function. The pass names are checked against the pass list while the arguments are parsed.

§dump_ir: Vec<String>

What -fdump-ir= asked to see, as it was written, which is all, before-<pass> or after-<pass>.

§opt_info: Vec<String>

What -fopt-info asked to hear about, as the keywords were written, with the leading hyphen taken off, so a bare -fopt-info is the empty string in here.

The keywords are optimized, missed, note and all, and two flags add up rather than the second replacing the first. Checked while the arguments are parsed, so anything in here is a spelling the optimizer understands. See section 42.2 of spec/optimizer/42-measurement.md for why missed is the one that earns the feature.

§opt_info_file: Option<String>

Where -fopt-info=<file> sends the remarks, or None for standard error.

One file for the whole run rather than one per input, the way GCC does it, and the last one on the command line is the one that decides. A harness that wants the remarks kept away from the diagnostics gives a file, which is what the corpus in tamnd/rucc-corpus does with GCC so that a rejection can still be matched against the diagnostic stream.

§verify_each: bool

Whether the IR verifier runs after every pass that changed anything.

On in a debug build without being asked, since that is where a broken pass should be caught. -Zverify-each turns it on in a release build, which is what CI wants.

§rule_coverage: Option<String>

Where -Zrule-coverage=FILE writes which lowering rules fired, if it was given.

A measurement rather than a thing a build asks for, which is why it is spelled with a -Z the way an unstable option is everywhere else: it is here for the harness in tamnd/rucc-compat to union over a corpus and report, and nothing about the code that comes out changes when it is on. One file per run of the compiler, holding the whole rule set with the rules this run reached marked, whatever the run compiled and however many files it was.

Implementations§

Source§

impl Options

Source

pub fn new(target: Triple) -> Self

Default options for target.

Source

pub const fn unwinds(&self) -> bool

Whether a function in this unit is described to an unwinder.

Either request is answered with the same table, so what decides is whether either of them is standing. Asked here rather than worked out at the two places that write a table, since those two writing different answers for one function is what spec/11-asm-objects-debug.md section 11.1 says must not be possible.

Trait Implementations§

Source§

impl Clone for Options

Source§

fn clone(&self) -> Options

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 Options

Source§

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

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

impl Eq for Options

Source§

impl PartialEq for Options

Source§

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

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.