Construct OutputType using macro and print [=FILENAME] help info

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
xizheyin 2025-04-20 19:52:26 +08:00
parent 4c20d17365
commit 6fe881c788
No known key found for this signature in database
GPG key ID: 0A0D90BE99CEDEAD
7 changed files with 243 additions and 127 deletions

View file

@ -568,122 +568,203 @@ impl FromStr for SplitDwarfKind {
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)]
#[derive(Encodable, Decodable)]
pub enum OutputType {
/// This is the optimized bitcode, which could be either pre-LTO or non-LTO bitcode,
/// depending on the specific request type.
Bitcode,
/// This is the summary or index data part of the ThinLTO bitcode.
ThinLinkBitcode,
Assembly,
LlvmAssembly,
Mir,
Metadata,
Object,
Exe,
DepInfo,
}
macro_rules! define_output_types {
(
$(
$(#[doc = $doc:expr])*
$Variant:ident => {
shorthand: $shorthand:expr,
extension: $extension:expr,
description: $description:expr,
default_filename: $default_filename:expr,
is_text: $is_text:expr,
compatible_with_cgus_and_single_output: $compatible:expr
}
),* $(,)?
) => {
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)]
#[derive(Encodable, Decodable)]
pub enum OutputType {
$(
$(#[doc = $doc])*
$Variant,
)*
}
impl StableOrd for OutputType {
const CAN_USE_UNSTABLE_SORT: bool = true;
// Trivial C-Style enums have a stable sort order across compilation sessions.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl StableOrd for OutputType {
const CAN_USE_UNSTABLE_SORT: bool = true;
impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
type KeyType = Self;
// Trivial C-Style enums have a stable sort order across compilation sessions.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
*self
impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
type KeyType = Self;
fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
*self
}
}
impl OutputType {
pub fn iter_all() -> impl Iterator<Item = OutputType> {
static ALL_VARIANTS: &[OutputType] = &[
$(
OutputType::$Variant,
)*
];
ALL_VARIANTS.iter().copied()
}
fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
match *self {
$(
OutputType::$Variant => $compatible,
)*
}
}
pub fn shorthand(&self) -> &'static str {
match *self {
$(
OutputType::$Variant => $shorthand,
)*
}
}
fn from_shorthand(shorthand: &str) -> Option<Self> {
match shorthand {
$(
s if s == $shorthand => Some(OutputType::$Variant),
)*
_ => None,
}
}
fn shorthands_display() -> String {
let shorthands = vec![
$(
format!("`{}`", $shorthand),
)*
];
shorthands.join(", ")
}
pub fn extension(&self) -> &'static str {
match *self {
$(
OutputType::$Variant => $extension,
)*
}
}
pub fn is_text_output(&self) -> bool {
match *self {
$(
OutputType::$Variant => $is_text,
)*
}
}
pub fn description(&self) -> &'static str {
match *self {
$(
OutputType::$Variant => $description,
)*
}
}
pub fn default_filename(&self) -> &'static str {
match *self {
$(
OutputType::$Variant => $default_filename,
)*
}
}
}
}
}
impl OutputType {
fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
match *self {
OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true,
OutputType::Bitcode
| OutputType::ThinLinkBitcode
| OutputType::Assembly
| OutputType::LlvmAssembly
| OutputType::Mir
| OutputType::Object => false,
}
}
pub fn shorthand(&self) -> &'static str {
match *self {
OutputType::Bitcode => "llvm-bc",
OutputType::ThinLinkBitcode => "thin-link-bitcode",
OutputType::Assembly => "asm",
OutputType::LlvmAssembly => "llvm-ir",
OutputType::Mir => "mir",
OutputType::Object => "obj",
OutputType::Metadata => "metadata",
OutputType::Exe => "link",
OutputType::DepInfo => "dep-info",
}
}
fn from_shorthand(shorthand: &str) -> Option<Self> {
Some(match shorthand {
"asm" => OutputType::Assembly,
"llvm-ir" => OutputType::LlvmAssembly,
"mir" => OutputType::Mir,
"llvm-bc" => OutputType::Bitcode,
"thin-link-bitcode" => OutputType::ThinLinkBitcode,
"obj" => OutputType::Object,
"metadata" => OutputType::Metadata,
"link" => OutputType::Exe,
"dep-info" => OutputType::DepInfo,
_ => return None,
})
}
fn shorthands_display() -> String {
format!(
"`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
OutputType::Bitcode.shorthand(),
OutputType::ThinLinkBitcode.shorthand(),
OutputType::Assembly.shorthand(),
OutputType::LlvmAssembly.shorthand(),
OutputType::Mir.shorthand(),
OutputType::Object.shorthand(),
OutputType::Metadata.shorthand(),
OutputType::Exe.shorthand(),
OutputType::DepInfo.shorthand(),
)
}
pub fn extension(&self) -> &'static str {
match *self {
OutputType::Bitcode => "bc",
OutputType::ThinLinkBitcode => "indexing.o",
OutputType::Assembly => "s",
OutputType::LlvmAssembly => "ll",
OutputType::Mir => "mir",
OutputType::Object => "o",
OutputType::Metadata => "rmeta",
OutputType::DepInfo => "d",
OutputType::Exe => "",
}
}
pub fn is_text_output(&self) -> bool {
match *self {
OutputType::Assembly
| OutputType::LlvmAssembly
| OutputType::Mir
| OutputType::DepInfo => true,
OutputType::Bitcode
| OutputType::ThinLinkBitcode
| OutputType::Object
| OutputType::Metadata
| OutputType::Exe => false,
}
}
define_output_types! {
Assembly => {
shorthand: "asm",
extension: "s",
description: "Generates a file with the crate's assembly code",
default_filename: "CRATE_NAME.s",
is_text: true,
compatible_with_cgus_and_single_output: false
},
#[doc = "This is the optimized bitcode, which could be either pre-LTO or non-LTO bitcode,"]
#[doc = "depending on the specific request type."]
Bitcode => {
shorthand: "llvm-bc",
extension: "bc",
description: "Generates a binary file containing the LLVM bitcode",
default_filename: "CRATE_NAME.bc",
is_text: false,
compatible_with_cgus_and_single_output: false
},
DepInfo => {
shorthand: "dep-info",
extension: "d",
description: "Generates a file with Makefile syntax that indicates all the source files that were loaded to generate the crate",
default_filename: "CRATE_NAME.d",
is_text: true,
compatible_with_cgus_and_single_output: true
},
Exe => {
shorthand: "link",
extension: "",
description: "Generates the crates specified by --crate-type. This is the default if --emit is not specified",
default_filename: "(platform and crate-type dependent)",
is_text: false,
compatible_with_cgus_and_single_output: true
},
LlvmAssembly => {
shorthand: "llvm-ir",
extension: "ll",
description: "Generates a file containing LLVM IR",
default_filename: "CRATE_NAME.ll",
is_text: true,
compatible_with_cgus_and_single_output: false
},
Metadata => {
shorthand: "metadata",
extension: "rmeta",
description: "Generates a file containing metadata about the crate",
default_filename: "libCRATE_NAME.rmeta",
is_text: false,
compatible_with_cgus_and_single_output: true
},
Mir => {
shorthand: "mir",
extension: "mir",
description: "Generates a file containing rustc's mid-level intermediate representation",
default_filename: "CRATE_NAME.mir",
is_text: true,
compatible_with_cgus_and_single_output: false
},
Object => {
shorthand: "obj",
extension: "o",
description: "Generates a native object file",
default_filename: "CRATE_NAME.o",
is_text: false,
compatible_with_cgus_and_single_output: false
},
#[doc = "This is the summary or index data part of the ThinLTO bitcode."]
ThinLinkBitcode => {
shorthand: "thin-link-bitcode",
extension: "indexing.o",
description: "Generates the ThinLTO summary as bitcode",
default_filename: "CRATE_NAME.indexing.o",
is_text: false,
compatible_with_cgus_and_single_output: false
},
}
/// The type of diagnostics output to generate.
@ -1570,6 +1651,18 @@ static PRINT_HELP: LazyLock<String> = LazyLock::new(|| {
)
});
static EMIT_HELP: LazyLock<String> = LazyLock::new(|| {
let mut result =
String::from("Comma separated list of types of output for the compiler to emit.\n");
result.push_str("Each TYPE has the default FILE name:\n");
for output in OutputType::iter_all() {
result.push_str(&format!("* {} - {}\n", output.shorthand(), output.default_filename()));
}
result
});
/// Returns all rustc command line options, including metadata for
/// each option, such as whether the option is stable.
pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
@ -1616,14 +1709,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
make_crate_type_option(),
opt(Stable, Opt, "", "crate-name", "Specify the name of the crate being built", "NAME"),
opt(Stable, Opt, "", "edition", &EDITION_STRING, EDITION_NAME_LIST),
opt(
Stable,
Multi,
"",
"emit",
"Comma separated list of types of output for the compiler to emit",
"[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]",
),
opt(Stable, Multi, "", "emit", &EMIT_HELP, "TYPE[=FILE]"),
opt(Stable, Multi, "", "print", &PRINT_HELP, "INFO[=FILE]"),
opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),