Skip to content

Commit 10ed802

Browse files
committed
Add -Z llvm_module_flag
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.
1 parent b66fe58 commit 10ed802

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

compiler/rustc_codegen_llvm/src/context.rs

+18
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,24 @@ pub unsafe fn create_module<'ll>(
368368
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
369369
);
370370

371+
// Add module flags specified via -Z llvm_module_flag
372+
for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
373+
let key = format!("{key}\0");
374+
let behavior = match behavior.as_str() {
375+
"error" => llvm::LLVMModFlagBehavior::Error,
376+
"warning" => llvm::LLVMModFlagBehavior::Warning,
377+
"require" => llvm::LLVMModFlagBehavior::Require,
378+
"override" => llvm::LLVMModFlagBehavior::Override,
379+
"append" => llvm::LLVMModFlagBehavior::Append,
380+
"appendunique" => llvm::LLVMModFlagBehavior::AppendUnique,
381+
"max" => llvm::LLVMModFlagBehavior::Max,
382+
"min" => llvm::LLVMModFlagBehavior::Min,
383+
// We already checked this during option parsing
384+
_ => unreachable!(),
385+
};
386+
llvm::LLVMRustAddModuleFlag(llmod, behavior, key.as_ptr().cast(), *value)
387+
}
388+
371389
llmod
372390
}
373391

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ fn test_unstable_options_tracking_hash() {
794794
tracked!(instrument_xray, Some(InstrumentXRay::default()));
795795
tracked!(link_directives, false);
796796
tracked!(link_only, true);
797+
tracked!(llvm_module_flag, vec![("bar".to_string(), 123, "max".to_string())]);
797798
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
798799
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
799800
tracked!(maximal_hir_to_mir_coverage, true);

compiler/rustc_session/src/options.rs

+30
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ mod desc {
428428
"one of supported execution strategies (`same-thread`, or `cross-thread`)";
429429
pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`";
430430
pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`";
431+
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`)";
431432
}
432433

433434
mod parse {
@@ -1310,6 +1311,33 @@ mod parse {
13101311
};
13111312
true
13121313
}
1314+
1315+
pub(crate) fn parse_llvm_module_flag(
1316+
slot: &mut Vec<(String, u32, String)>,
1317+
v: Option<&str>,
1318+
) -> bool {
1319+
let elements = v.unwrap_or_default().split(':').collect::<Vec<_>>();
1320+
let [key, md_type, value, behavior] = elements.as_slice() else {
1321+
return false;
1322+
};
1323+
if *md_type != "u32" {
1324+
// Currently we only support u32 metadata flags, but require the
1325+
// type for forward-compatibility.
1326+
return false;
1327+
}
1328+
let Ok(value) = value.parse::<u32>() else {
1329+
return false;
1330+
};
1331+
let behavior = behavior.to_lowercase();
1332+
let all_behaviors =
1333+
["error", "warning", "require", "override", "append", "appendunique", "max", "min"];
1334+
if !all_behaviors.contains(&behavior.as_str()) {
1335+
return false;
1336+
}
1337+
1338+
slot.push((key.to_string(), value, behavior));
1339+
true
1340+
}
13131341
}
13141342

13151343
options! {
@@ -1625,6 +1653,8 @@ options! {
16251653
"link native libraries in the linker invocation (default: yes)"),
16261654
link_only: bool = (false, parse_bool, [TRACKED],
16271655
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
1656+
llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED],
1657+
"a list of module flags to pass to LLVM (space separated)"),
16281658
llvm_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
16291659
"a list LLVM plugins to enable (space separated)"),
16301660
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# `llvm-module-flag`
2+
3+
---------------------
4+
5+
This flag allows adding a key/value to the `!llvm.module.flags` metadata in the
6+
LLVM-IR for a compiled Rust module. The syntax is
7+
8+
`-Z llvm_module_flag=<name>:<type>:<value>:<behavior>`
9+
10+
Currently only u32 values are supported but the type is required to be specified
11+
for forward compatibility. The `behavior` element must match one of the named
12+
LLVM [metadata behaviors](https://llvm.org/docs/LangRef.html#module-flags-metadata)

tests/codegen/llvm_module_flags.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Test for -Z llvm_module_flags
2+
// compile-flags: -Z llvm_module_flag=foo:u32:123:error -Z llvm_module_flag=bar:u32:42:max
3+
4+
fn main() {}
5+
6+
// CHECK: !{i32 1, !"foo", i32 123}
7+
// CHECK: !{i32 7, !"bar", i32 42}

0 commit comments

Comments
 (0)