Rollup merge of #132319 - Zalathar:add-module-flag, r=jieyouxu
cg_llvm: Clean up FFI calls for setting module flags This is a combination of several inter-related changes to how module flags are set: - Remove some unnecessary code for setting an `"LTOPostLink"` flag, which has been obsolete since LLVM 17. - Define our own enum instead of relying on enum values defined by LLVM's unstable C++ API. - Use safe wrapper functions to set module flags, instead of direct `unsafe` calls. - Consistently pass pointer/length strings instead of C strings. - Remove or shrink some `unsafe` blocks.
This commit is contained in:
commit
2707cd670c
@ -25,7 +25,6 @@
|
|||||||
use crate::back::write::{
|
use crate::back::write::{
|
||||||
self, CodegenDiagnosticsStage, DiagnosticHandlers, bitcode_section_name, save_temp_bitcode,
|
self, CodegenDiagnosticsStage, DiagnosticHandlers, bitcode_section_name, save_temp_bitcode,
|
||||||
};
|
};
|
||||||
use crate::common::AsCCharPtr;
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, LtoProcMacro,
|
DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, LtoProcMacro,
|
||||||
};
|
};
|
||||||
@ -602,23 +601,9 @@ pub(crate) fn run_pass_manager(
|
|||||||
// This code is based off the code found in llvm's LTO code generator:
|
// This code is based off the code found in llvm's LTO code generator:
|
||||||
// llvm/lib/LTO/LTOCodeGenerator.cpp
|
// llvm/lib/LTO/LTOCodeGenerator.cpp
|
||||||
debug!("running the pass manager");
|
debug!("running the pass manager");
|
||||||
unsafe {
|
|
||||||
if !llvm::LLVMRustHasModuleFlag(
|
|
||||||
module.module_llvm.llmod(),
|
|
||||||
"LTOPostLink".as_c_char_ptr(),
|
|
||||||
11,
|
|
||||||
) {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
module.module_llvm.llmod(),
|
|
||||||
llvm::LLVMModFlagBehavior::Error,
|
|
||||||
c"LTOPostLink".as_ptr(),
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
|
let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
|
||||||
let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
|
let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
|
||||||
write::llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage)?;
|
unsafe { write::llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage) }?;
|
||||||
}
|
|
||||||
debug!("lto done");
|
debug!("lto done");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -210,133 +210,111 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||||||
// If skipping the PLT is enabled, we need to add some module metadata
|
// If skipping the PLT is enabled, we need to add some module metadata
|
||||||
// to ensure intrinsic calls don't use it.
|
// to ensure intrinsic calls don't use it.
|
||||||
if !sess.needs_plt() {
|
if !sess.needs_plt() {
|
||||||
let avoid_plt = c"RtLibUseGOT".as_ptr();
|
llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "RtLibUseGOT", 1);
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
|
// Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
|
||||||
if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
|
if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
|
||||||
let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr();
|
llvm::add_module_flag_u32(
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
canonical_jump_tables,
|
"CFI Canonical Jump Tables",
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If we're normalizing integers with CFI, ensure LLVM generated functions do the same.
|
// If we're normalizing integers with CFI, ensure LLVM generated functions do the same.
|
||||||
// See https://github.com/llvm/llvm-project/pull/104826
|
// See https://github.com/llvm/llvm-project/pull/104826
|
||||||
if sess.is_sanitizer_cfi_normalize_integers_enabled() {
|
if sess.is_sanitizer_cfi_normalize_integers_enabled() {
|
||||||
let cfi_normalize_integers = c"cfi-normalize-integers".as_ptr();
|
llvm::add_module_flag_u32(
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
cfi_normalize_integers,
|
"cfi-normalize-integers",
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Enable LTO unit splitting if specified or if CFI is enabled. (See
|
// Enable LTO unit splitting if specified or if CFI is enabled. (See
|
||||||
// https://reviews.llvm.org/D53891.)
|
// https://reviews.llvm.org/D53891.)
|
||||||
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
|
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
|
||||||
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr();
|
llvm::add_module_flag_u32(
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
enable_split_lto_unit,
|
"EnableSplitLTOUnit",
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
|
// Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
|
||||||
if sess.is_sanitizer_kcfi_enabled() {
|
if sess.is_sanitizer_kcfi_enabled() {
|
||||||
let kcfi = c"kcfi".as_ptr();
|
llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Override, "kcfi", 1);
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add "kcfi-offset" module flag with -Z patchable-function-entry (See
|
// Add "kcfi-offset" module flag with -Z patchable-function-entry (See
|
||||||
// https://reviews.llvm.org/D141172).
|
// https://reviews.llvm.org/D141172).
|
||||||
let pfe =
|
let pfe =
|
||||||
PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry);
|
PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry);
|
||||||
if pfe.prefix() > 0 {
|
if pfe.prefix() > 0 {
|
||||||
let kcfi_offset = c"kcfi-offset".as_ptr();
|
llvm::add_module_flag_u32(
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
kcfi_offset,
|
"kcfi-offset",
|
||||||
pfe.prefix().into(),
|
pfe.prefix().into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||||
if sess.target.is_like_msvc {
|
if sess.target.is_like_msvc {
|
||||||
unsafe {
|
|
||||||
match sess.opts.cg.control_flow_guard {
|
match sess.opts.cg.control_flow_guard {
|
||||||
CFGuard::Disabled => {}
|
CFGuard::Disabled => {}
|
||||||
CFGuard::NoChecks => {
|
CFGuard::NoChecks => {
|
||||||
// Set `cfguard=1` module flag to emit metadata only.
|
// Set `cfguard=1` module flag to emit metadata only.
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::ModuleFlagMergeBehavior::Warning,
|
||||||
c"cfguard".as_ptr() as *const _,
|
"cfguard",
|
||||||
1,
|
1,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
CFGuard::Checks => {
|
CFGuard::Checks => {
|
||||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::ModuleFlagMergeBehavior::Warning,
|
||||||
c"cfguard".as_ptr() as *const _,
|
"cfguard",
|
||||||
2,
|
2,
|
||||||
)
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||||
if sess.target.arch == "aarch64" {
|
if sess.target.arch == "aarch64" {
|
||||||
unsafe {
|
llvm::add_module_flag_u32(
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::ModuleFlagMergeBehavior::Min,
|
||||||
c"branch-target-enforcement".as_ptr(),
|
"branch-target-enforcement",
|
||||||
bti.into(),
|
bti.into(),
|
||||||
);
|
);
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::ModuleFlagMergeBehavior::Min,
|
||||||
c"sign-return-address".as_ptr(),
|
"sign-return-address",
|
||||||
pac_ret.is_some().into(),
|
pac_ret.is_some().into(),
|
||||||
);
|
);
|
||||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::ModuleFlagMergeBehavior::Min,
|
||||||
c"sign-return-address-all".as_ptr(),
|
"sign-return-address-all",
|
||||||
pac_opts.leaf.into(),
|
pac_opts.leaf.into(),
|
||||||
);
|
);
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::ModuleFlagMergeBehavior::Min,
|
||||||
c"sign-return-address-with-bkey".as_ptr(),
|
"sign-return-address-with-bkey",
|
||||||
u32::from(pac_opts.key == PAuthKey::B),
|
u32::from(pac_opts.key == PAuthKey::B),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
bug!(
|
bug!(
|
||||||
"branch-protection used on non-AArch64 target; \
|
"branch-protection used on non-AArch64 target; \
|
||||||
@ -347,59 +325,46 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||||||
|
|
||||||
// Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
|
// Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
|
||||||
if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||||
unsafe {
|
llvm::add_module_flag_u32(
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
c"cf-protection-branch".as_ptr(),
|
"cf-protection-branch",
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||||
unsafe {
|
llvm::add_module_flag_u32(
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
c"cf-protection-return".as_ptr(),
|
"cf-protection-return",
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||||
unsafe {
|
llvm::add_module_flag_u32(
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Error,
|
llvm::ModuleFlagMergeBehavior::Error,
|
||||||
c"Virtual Function Elim".as_ptr(),
|
"Virtual Function Elim",
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
||||||
if sess.opts.unstable_opts.ehcont_guard {
|
if sess.opts.unstable_opts.ehcont_guard {
|
||||||
unsafe {
|
llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "ehcontguard", 1);
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
|
||||||
c"ehcontguard".as_ptr() as *const _,
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match sess.opts.unstable_opts.function_return {
|
match sess.opts.unstable_opts.function_return {
|
||||||
FunctionReturn::Keep => {}
|
FunctionReturn::Keep => {}
|
||||||
FunctionReturn::ThunkExtern => unsafe {
|
FunctionReturn::ThunkExtern => {
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
c"function_return_thunk_extern".as_ptr(),
|
"function_return_thunk_extern",
|
||||||
1,
|
1,
|
||||||
)
|
);
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
|
match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
|
||||||
@ -407,15 +372,12 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||||||
// Set up the small-data optimization limit for architectures that use
|
// Set up the small-data optimization limit for architectures that use
|
||||||
// an LLVM module flag to control this.
|
// an LLVM module flag to control this.
|
||||||
(Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => {
|
(Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => {
|
||||||
let flag = SmallCStr::new(flag.as_ref());
|
llvm::add_module_flag_u32(
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Error,
|
llvm::ModuleFlagMergeBehavior::Error,
|
||||||
flag.as_c_str().as_ptr(),
|
&flag,
|
||||||
threshold as u32,
|
threshold as u32,
|
||||||
)
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
@ -449,33 +411,29 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||||||
// If llvm_abiname is empty, emit nothing.
|
// If llvm_abiname is empty, emit nothing.
|
||||||
let llvm_abiname = &sess.target.options.llvm_abiname;
|
let llvm_abiname = &sess.target.options.llvm_abiname;
|
||||||
if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() {
|
if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() {
|
||||||
unsafe {
|
llvm::add_module_flag_str(
|
||||||
llvm::LLVMRustAddModuleFlagString(
|
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Error,
|
llvm::ModuleFlagMergeBehavior::Error,
|
||||||
c"target-abi".as_ptr(),
|
"target-abi",
|
||||||
llvm_abiname.as_c_char_ptr(),
|
llvm_abiname,
|
||||||
llvm_abiname.len(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Add module flags specified via -Z llvm_module_flag
|
// Add module flags specified via -Z llvm_module_flag
|
||||||
for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
|
for (key, value, merge_behavior) in &sess.opts.unstable_opts.llvm_module_flag {
|
||||||
let key = format!("{key}\0");
|
let merge_behavior = match merge_behavior.as_str() {
|
||||||
let behavior = match behavior.as_str() {
|
"error" => llvm::ModuleFlagMergeBehavior::Error,
|
||||||
"error" => llvm::LLVMModFlagBehavior::Error,
|
"warning" => llvm::ModuleFlagMergeBehavior::Warning,
|
||||||
"warning" => llvm::LLVMModFlagBehavior::Warning,
|
"require" => llvm::ModuleFlagMergeBehavior::Require,
|
||||||
"require" => llvm::LLVMModFlagBehavior::Require,
|
"override" => llvm::ModuleFlagMergeBehavior::Override,
|
||||||
"override" => llvm::LLVMModFlagBehavior::Override,
|
"append" => llvm::ModuleFlagMergeBehavior::Append,
|
||||||
"append" => llvm::LLVMModFlagBehavior::Append,
|
"appendunique" => llvm::ModuleFlagMergeBehavior::AppendUnique,
|
||||||
"appendunique" => llvm::LLVMModFlagBehavior::AppendUnique,
|
"max" => llvm::ModuleFlagMergeBehavior::Max,
|
||||||
"max" => llvm::LLVMModFlagBehavior::Max,
|
"min" => llvm::ModuleFlagMergeBehavior::Min,
|
||||||
"min" => llvm::LLVMModFlagBehavior::Min,
|
|
||||||
// We already checked this during option parsing
|
// We already checked this during option parsing
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_c_char_ptr(), *value) }
|
llvm::add_module_flag_u32(llmod, merge_behavior, key, *value);
|
||||||
}
|
}
|
||||||
|
|
||||||
llmod
|
llmod
|
||||||
|
@ -91,9 +91,7 @@ pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn finalize(&self, sess: &Session) {
|
pub(crate) fn finalize(&self, sess: &Session) {
|
||||||
unsafe {
|
unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder) };
|
||||||
llvm::LLVMRustDIBuilderFinalize(self.builder);
|
|
||||||
|
|
||||||
if !sess.target.is_like_msvc {
|
if !sess.target.is_like_msvc {
|
||||||
// Debuginfo generation in LLVM by default uses a higher
|
// Debuginfo generation in LLVM by default uses a higher
|
||||||
// version of dwarf than macOS currently understands. We can
|
// version of dwarf than macOS currently understands. We can
|
||||||
@ -101,36 +99,32 @@ pub(crate) fn finalize(&self, sess: &Session) {
|
|||||||
// for macOS to understand. For more info see #11352
|
// for macOS to understand. For more info see #11352
|
||||||
// This can be overridden using --llvm-opts -dwarf-version,N.
|
// This can be overridden using --llvm-opts -dwarf-version,N.
|
||||||
// Android has the same issue (#22398)
|
// Android has the same issue (#22398)
|
||||||
let dwarf_version = sess
|
let dwarf_version =
|
||||||
.opts
|
sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version);
|
||||||
.unstable_opts
|
llvm::add_module_flag_u32(
|
||||||
.dwarf_version
|
|
||||||
.unwrap_or(sess.target.default_dwarf_version);
|
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
|
||||||
self.llmod,
|
self.llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::ModuleFlagMergeBehavior::Warning,
|
||||||
c"Dwarf Version".as_ptr(),
|
"Dwarf Version",
|
||||||
dwarf_version,
|
dwarf_version,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Indicate that we want CodeView debug information on MSVC
|
// Indicate that we want CodeView debug information on MSVC
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
self.llmod,
|
self.llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::ModuleFlagMergeBehavior::Warning,
|
||||||
c"CodeView".as_ptr(),
|
"CodeView",
|
||||||
1,
|
1,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent bitcode readers from deleting the debug info.
|
// Prevent bitcode readers from deleting the debug info.
|
||||||
llvm::LLVMRustAddModuleFlagU32(
|
llvm::add_module_flag_u32(
|
||||||
self.llmod,
|
self.llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::ModuleFlagMergeBehavior::Warning,
|
||||||
c"Debug Info Version".as_ptr(),
|
"Debug Info Version",
|
||||||
llvm::LLVMRustDebugMetadataVersion(),
|
unsafe { llvm::LLVMRustDebugMetadataVersion() },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates any deferred debug metadata nodes
|
/// Creates any deferred debug metadata nodes
|
||||||
|
@ -85,7 +85,7 @@ pub enum LLVMMachineType {
|
|||||||
ARM = 0x01c0,
|
ARM = 0x01c0,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LLVM's Module::ModFlagBehavior, defined in llvm/include/llvm/IR/Module.h.
|
/// Must match the layout of `LLVMRustModuleFlagMergeBehavior`.
|
||||||
///
|
///
|
||||||
/// When merging modules (e.g. during LTO), their metadata flags are combined. Conflicts are
|
/// When merging modules (e.g. during LTO), their metadata flags are combined. Conflicts are
|
||||||
/// resolved according to the merge behaviors specified here. Flags differing only in merge
|
/// resolved according to the merge behaviors specified here. Flags differing only in merge
|
||||||
@ -93,9 +93,13 @@ pub enum LLVMMachineType {
|
|||||||
///
|
///
|
||||||
/// In order for Rust-C LTO to work, we must specify behaviors compatible with Clang. Notably,
|
/// In order for Rust-C LTO to work, we must specify behaviors compatible with Clang. Notably,
|
||||||
/// 'Error' and 'Warning' cannot be mixed for a given flag.
|
/// 'Error' and 'Warning' cannot be mixed for a given flag.
|
||||||
|
///
|
||||||
|
/// There is a stable LLVM-C version of this enum (`LLVMModuleFlagBehavior`),
|
||||||
|
/// but as of LLVM 19 it does not support all of the enum values in the unstable
|
||||||
|
/// C++ API.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum LLVMModFlagBehavior {
|
pub enum ModuleFlagMergeBehavior {
|
||||||
Error = 1,
|
Error = 1,
|
||||||
Warning = 2,
|
Warning = 2,
|
||||||
Require = 3,
|
Require = 3,
|
||||||
@ -1829,21 +1833,21 @@ pub(crate) fn LLVMRustCoverageCreatePGOFuncNameVar(
|
|||||||
/// "compatible" means depends on the merge behaviors involved.
|
/// "compatible" means depends on the merge behaviors involved.
|
||||||
pub fn LLVMRustAddModuleFlagU32(
|
pub fn LLVMRustAddModuleFlagU32(
|
||||||
M: &Module,
|
M: &Module,
|
||||||
merge_behavior: LLVMModFlagBehavior,
|
MergeBehavior: ModuleFlagMergeBehavior,
|
||||||
name: *const c_char,
|
Name: *const c_char,
|
||||||
value: u32,
|
NameLen: size_t,
|
||||||
|
Value: u32,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn LLVMRustAddModuleFlagString(
|
pub fn LLVMRustAddModuleFlagString(
|
||||||
M: &Module,
|
M: &Module,
|
||||||
merge_behavior: LLVMModFlagBehavior,
|
MergeBehavior: ModuleFlagMergeBehavior,
|
||||||
name: *const c_char,
|
Name: *const c_char,
|
||||||
value: *const c_char,
|
NameLen: size_t,
|
||||||
value_len: size_t,
|
Value: *const c_char,
|
||||||
|
ValueLen: size_t,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool;
|
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
|
pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>);
|
pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>);
|
||||||
|
@ -352,3 +352,32 @@ fn drop(&mut self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_module_flag_u32(
|
||||||
|
module: &Module,
|
||||||
|
merge_behavior: ModuleFlagMergeBehavior,
|
||||||
|
key: &str,
|
||||||
|
value: u32,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
LLVMRustAddModuleFlagU32(module, merge_behavior, key.as_c_char_ptr(), key.len(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_module_flag_str(
|
||||||
|
module: &Module,
|
||||||
|
merge_behavior: ModuleFlagMergeBehavior,
|
||||||
|
key: &str,
|
||||||
|
value: &str,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
LLVMRustAddModuleFlagString(
|
||||||
|
module,
|
||||||
|
merge_behavior,
|
||||||
|
key.as_c_char_ptr(),
|
||||||
|
key.len(),
|
||||||
|
value.as_c_char_ptr(),
|
||||||
|
value.len(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -853,25 +853,63 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
|
|||||||
|
|
||||||
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
|
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
|
||||||
|
|
||||||
extern "C" void LLVMRustAddModuleFlagU32(LLVMModuleRef M,
|
// FFI equivalent of LLVM's `llvm::Module::ModFlagBehavior`.
|
||||||
Module::ModFlagBehavior MergeBehavior,
|
// Must match the layout of
|
||||||
const char *Name, uint32_t Value) {
|
// `rustc_codegen_llvm::llvm::ffi::ModuleFlagMergeBehavior`.
|
||||||
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
|
//
|
||||||
|
// There is a stable LLVM-C version of this enum (`LLVMModuleFlagBehavior`),
|
||||||
|
// but as of LLVM 19 it does not support all of the enum values in the unstable
|
||||||
|
// C++ API.
|
||||||
|
enum class LLVMRustModuleFlagMergeBehavior {
|
||||||
|
Error = 1,
|
||||||
|
Warning = 2,
|
||||||
|
Require = 3,
|
||||||
|
Override = 4,
|
||||||
|
Append = 5,
|
||||||
|
AppendUnique = 6,
|
||||||
|
Max = 7,
|
||||||
|
Min = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static Module::ModFlagBehavior
|
||||||
|
fromRust(LLVMRustModuleFlagMergeBehavior Behavior) {
|
||||||
|
switch (Behavior) {
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::Error:
|
||||||
|
return Module::ModFlagBehavior::Error;
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::Warning:
|
||||||
|
return Module::ModFlagBehavior::Warning;
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::Require:
|
||||||
|
return Module::ModFlagBehavior::Require;
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::Override:
|
||||||
|
return Module::ModFlagBehavior::Override;
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::Append:
|
||||||
|
return Module::ModFlagBehavior::Append;
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::AppendUnique:
|
||||||
|
return Module::ModFlagBehavior::AppendUnique;
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::Max:
|
||||||
|
return Module::ModFlagBehavior::Max;
|
||||||
|
case LLVMRustModuleFlagMergeBehavior::Min:
|
||||||
|
return Module::ModFlagBehavior::Min;
|
||||||
|
}
|
||||||
|
report_fatal_error("bad LLVMRustModuleFlagMergeBehavior");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
LLVMRustAddModuleFlagU32(LLVMModuleRef M,
|
||||||
|
LLVMRustModuleFlagMergeBehavior MergeBehavior,
|
||||||
|
const char *Name, size_t NameLen, uint32_t Value) {
|
||||||
|
unwrap(M)->addModuleFlag(fromRust(MergeBehavior), StringRef(Name, NameLen),
|
||||||
|
Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void LLVMRustAddModuleFlagString(
|
extern "C" void LLVMRustAddModuleFlagString(
|
||||||
LLVMModuleRef M, Module::ModFlagBehavior MergeBehavior, const char *Name,
|
LLVMModuleRef M, LLVMRustModuleFlagMergeBehavior MergeBehavior,
|
||||||
const char *Value, size_t ValueLen) {
|
const char *Name, size_t NameLen, const char *Value, size_t ValueLen) {
|
||||||
unwrap(M)->addModuleFlag(
|
unwrap(M)->addModuleFlag(
|
||||||
MergeBehavior, Name,
|
fromRust(MergeBehavior), StringRef(Name, NameLen),
|
||||||
MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen)));
|
MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
|
|
||||||
size_t Len) {
|
|
||||||
return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind,
|
extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind,
|
||||||
LLVMMetadataRef MD) {
|
LLVMMetadataRef MD) {
|
||||||
unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
|
unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
|
||||||
|
Loading…
Reference in New Issue
Block a user