Rollup merge of #123612 - kxxt:riscv-target-abi, r=jieyouxu,nikic,DianQK

Set target-abi module flag for RISC-V targets

Fixes cross-language LTO on RISC-V targets (Fixes #121924)
This commit is contained in:
Matthias Krüger 2024-04-10 04:27:40 +02:00 committed by GitHub
commit 2ddf984594
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 177 additions and 21 deletions

View file

@ -608,7 +608,7 @@ pub(crate) fn run_pass_manager(
"LTOPostLink".as_ptr().cast(),
11,
) {
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
module.module_llvm.llmod(),
llvm::LLVMModFlagBehavior::Error,
c"LTOPostLink".as_ptr().cast(),

View file

@ -180,13 +180,13 @@ pub unsafe fn create_module<'ll>(
// to ensure intrinsic calls don't use it.
if !sess.needs_plt() {
let avoid_plt = c"RtLibUseGOT".as_ptr().cast();
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
}
// 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() {
let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast();
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Override,
canonical_jump_tables,
@ -197,7 +197,7 @@ pub unsafe fn create_module<'ll>(
// Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast();
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Override,
enable_split_lto_unit,
@ -208,7 +208,7 @@ pub unsafe fn create_module<'ll>(
// Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
if sess.is_sanitizer_kcfi_enabled() {
let kcfi = c"kcfi".as_ptr().cast();
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
}
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
@ -217,7 +217,7 @@ pub unsafe fn create_module<'ll>(
CFGuard::Disabled => {}
CFGuard::NoChecks => {
// Set `cfguard=1` module flag to emit metadata only.
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Warning,
c"cfguard".as_ptr() as *const _,
@ -226,7 +226,7 @@ pub unsafe fn create_module<'ll>(
}
CFGuard::Checks => {
// Set `cfguard=2` module flag to emit metadata and checks.
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Warning,
c"cfguard".as_ptr() as *const _,
@ -238,26 +238,26 @@ pub unsafe fn create_module<'ll>(
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
if sess.target.arch == "aarch64" {
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Min,
c"branch-target-enforcement".as_ptr().cast(),
bti.into(),
);
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Min,
c"sign-return-address".as_ptr().cast(),
pac_ret.is_some().into(),
);
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Min,
c"sign-return-address-all".as_ptr().cast(),
pac_opts.leaf.into(),
);
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Min,
c"sign-return-address-with-bkey".as_ptr().cast(),
@ -273,7 +273,7 @@ pub unsafe fn create_module<'ll>(
// 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 {
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Override,
c"cf-protection-branch".as_ptr().cast(),
@ -281,7 +281,7 @@ pub unsafe fn create_module<'ll>(
)
}
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Override,
c"cf-protection-return".as_ptr().cast(),
@ -290,7 +290,7 @@ pub unsafe fn create_module<'ll>(
}
if sess.opts.unstable_opts.virtual_function_elimination {
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Error,
c"Virtual Function Elim".as_ptr().cast(),
@ -300,7 +300,7 @@ pub unsafe fn create_module<'ll>(
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
if sess.opts.unstable_opts.ehcont_guard {
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Warning,
c"ehcontguard".as_ptr() as *const _,
@ -326,6 +326,22 @@ pub unsafe fn create_module<'ll>(
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
);
// Emit RISC-V specific target-abi metadata
// to workaround lld as the LTO plugin not
// correctly setting target-abi for the LTO object
// FIXME: https://github.com/llvm/llvm-project/issues/50591
// If llvm_abiname is empty, emit nothing.
let llvm_abiname = &sess.target.options.llvm_abiname;
if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() {
llvm::LLVMRustAddModuleFlagString(
llmod,
llvm::LLVMModFlagBehavior::Error,
c"target-abi".as_ptr(),
llvm_abiname.as_ptr().cast(),
llvm_abiname.len(),
);
}
// 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");
@ -341,7 +357,7 @@ pub unsafe fn create_module<'ll>(
// We already checked this during option parsing
_ => unreachable!(),
};
llvm::LLVMRustAddModuleFlag(llmod, behavior, key.as_ptr().cast(), *value)
llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value)
}
llmod

View file

@ -110,7 +110,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
.unstable_opts
.dwarf_version
.unwrap_or(sess.target.default_dwarf_version);
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
self.llmod,
llvm::LLVMModFlagBehavior::Warning,
c"Dwarf Version".as_ptr().cast(),
@ -118,7 +118,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
);
} else {
// Indicate that we want CodeView debug information on MSVC
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
self.llmod,
llvm::LLVMModFlagBehavior::Warning,
c"CodeView".as_ptr().cast(),
@ -127,7 +127,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
}
// Prevent bitcode readers from deleting the debug info.
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
self.llmod,
llvm::LLVMModFlagBehavior::Warning,
c"Debug Info Version".as_ptr().cast(),

View file

@ -1801,12 +1801,21 @@ extern "C" {
///
/// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
/// "compatible" means depends on the merge behaviors involved.
pub fn LLVMRustAddModuleFlag(
pub fn LLVMRustAddModuleFlagU32(
M: &Module,
merge_behavior: LLVMModFlagBehavior,
name: *const c_char,
value: u32,
);
pub fn LLVMRustAddModuleFlagString(
M: &Module,
merge_behavior: LLVMModFlagBehavior,
name: *const c_char,
value: *const c_char,
value_len: size_t,
);
pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool;
pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;