Skip to content

Commit

Permalink
Add -Z llvm_module_flag
Browse files Browse the repository at this point in the history
Allow adding values to the `!llvm.module.flags` metadata for a generated
module.  The syntax is

`-Z llvm_module_flag=<name>:<type>:<value>:<behavior>`

Currently only u32 values are supported but the type is required to be
specified for forward compatibility.  The `behavior` element must match
one of the named LLVM metadata behaviors.viors.

This flag is expected to be perma-unstable.
  • Loading branch information
paulmenage committed Oct 8, 2023
1 parent bf9a1c8 commit 892f482
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 0 deletions.
18 changes: 18 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,24 @@ pub unsafe fn create_module<'ll>(
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
);

// Add module flags specified via -Z llvm_module_flag
for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
let key = format!("{key}\0");
let behavior = match behavior.as_str() {
"error" => llvm::LLVMModFlagBehavior::Error,
"warning" => llvm::LLVMModFlagBehavior::Warning,
"require" => llvm::LLVMModFlagBehavior::Require,
"override" => llvm::LLVMModFlagBehavior::Override,
"append" => llvm::LLVMModFlagBehavior::Append,
"appendunique" => llvm::LLVMModFlagBehavior::AppendUnique,
"max" => llvm::LLVMModFlagBehavior::Max,
"min" => llvm::LLVMModFlagBehavior::Min,
// We already checked this during option parsing
_ => unreachable!(),
};
llvm::LLVMRustAddModuleFlag(llmod, behavior, key.as_ptr().cast(), *value)
}

llmod
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(instrument_xray, Some(InstrumentXRay::default()));
tracked!(link_directives, false);
tracked!(link_only, true);
tracked!(llvm_module_flag, Some("bar:u32:123:max"));
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
tracked!(maximal_hir_to_mir_coverage, true);
Expand Down
31 changes: 31 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ mod desc {
pub const parse_proc_macro_execution_strategy: &str =
"one of supported execution strategies (`same-thread`, or `cross-thread`)";
pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`";

pub const parse_llvm_module_flag: &str = "<key>:<type>:<value>:<behavior>. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)";
}

mod parse {
Expand Down Expand Up @@ -1263,6 +1265,33 @@ mod parse {
};
true
}

pub(crate) fn parse_llvm_module_flag(
slot: &mut Vec<(String, u32, String)>,
v: Option<&str>,
) -> bool {
let elements = v.unwrap_or_default().split(':').collect::<Vec<_>>();
let [key, md_type, value, behavior] = elements.as_slice() else {
return false;
};
if *md_type != "u32" {
// Currently we only support u32 metadata flags, but require the
// type for forward-compatibility.
return false;
}
let Ok(value) = value.parse::<u32>() else {
return false;
};
let behavior = behavior.to_lowercase();
let all_behaviors =
["error", "warning", "require", "override", "append", "appendunique", "max", "min"];
if !all_behaviors.contains(&behavior.as_str()) {
return false;
}

slot.push((key.to_string(), value, behavior));
true
}
}

options! {
Expand Down Expand Up @@ -1574,6 +1603,8 @@ options! {
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED],
"a list of module flags to pass to LLVM (space separated)"),
llvm_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list LLVM plugins to enable (space separated)"),
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
Expand Down
12 changes: 12 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/llvm-module-flag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# `llvm-module-flag`

---------------------

This flag allows adding a key/value to the `!llvm.module.flags` metadata in the
LLVM-IR for a compiled Rust module. The syntax is

`-Z llvm_module_flag=<name>:<type>:<value>:<behavior>`

Currently only u32 values are supported but the type is required to be specified
for forward compatibility. The `behavior` element must match one of the named
LLVM [metadata behaviors](https://llvm.org/docs/LangRef.html#module-flags-metadata)
7 changes: 7 additions & 0 deletions tests/codegen/llvm_module_flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Test for -Z llvm_module_flags
// compile-flags: -Z llvm_module_flag=foo:u32:123:error -Z llvm_module_flag=bar:u32:42:appendunique

fn main() {}

// CHECK: !{i32 1, !"foo", i32 123}
// CHECK: !{i32 6, !"bar", i32 42}

0 comments on commit 892f482

Please sign in to comment.