Skip to content

Commit

Permalink
embed riscv64 target abi in bc when plugin-lto is used
Browse files Browse the repository at this point in the history
  • Loading branch information
kxxt committed Jan 28, 2024
1 parent 6351247 commit a599284
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 21 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,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(),
Expand Down
49 changes: 34 additions & 15 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use rustc_span::Span;
use rustc_target::abi::{
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
};
use rustc_target::spec::TargetTriple;
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
use smallvec::SmallVec;

Expand Down Expand Up @@ -203,13 +204,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,
Expand All @@ -220,7 +221,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,
Expand All @@ -231,7 +232,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.
Expand All @@ -240,7 +241,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 _,
Expand All @@ -249,7 +250,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 _,
Expand All @@ -267,26 +268,26 @@ pub unsafe fn create_module<'ll>(
};

if sess.target.arch == "aarch64" {
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
behavior,
c"branch-target-enforcement".as_ptr().cast(),
bti.into(),
);
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
behavior,
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,
behavior,
c"sign-return-address-all".as_ptr().cast(),
pac_opts.leaf.into(),
);
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
llmod,
behavior,
c"sign-return-address-with-bkey".as_ptr().cast(),
Expand All @@ -302,15 +303,15 @@ 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(),
1,
)
}
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(),
Expand All @@ -319,7 +320,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(),
Expand All @@ -329,7 +330,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 _,
Expand All @@ -354,6 +355,24 @@ pub unsafe fn create_module<'ll>(
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
);

// Embed target-abi into bitcode for rv64gc when plugin-lto is enabled
// Relevant:
// https://discourse.llvm.org/t/encode-target-abi-into-llvm-bitcode-for-lto/54116
// https://internals.rust-lang.org/t/per-target-llvm-module-flags/12023
if sess.opts.cg.linker_plugin_lto.enabled() {
let TargetTriple::TargetTriple(ref triple) = sess.opts.target_triple else {
panic!("Unexpected TargetTriple::TargetJson")
};
if triple == "riscv64gc-unknown-linux-gnu" {
llvm::LLVMRustAddModuleFlagString(
llmod,
llvm::LLVMModFlagBehavior::Error,
c"target-abi".as_ptr() as *const _,
c"lp64d".as_ptr() as *const _,
)
}
}

// 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");
Expand All @@ -369,7 +388,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
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,15 @@ 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(),
dwarf_version,
);
} else {
// Indicate that we want CodeView debug information on MSVC
llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlagU32(
self.llmod,
llvm::LLVMModFlagBehavior::Warning,
c"CodeView".as_ptr().cast(),
Expand All @@ -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(),
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1793,12 +1793,20 @@ 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,
);

pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool;

pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,8 @@ impl Drop for OperandBundleDef<'_> {
}
}
}

pub enum LLVMModFlagValue {
String(String),
U32(u32),
}
11 changes: 10 additions & 1 deletion compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -748,14 +748,23 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }

extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }

extern "C" void LLVMRustAddModuleFlag(
extern "C" void LLVMRustAddModuleFlagU32(
LLVMModuleRef M,
Module::ModFlagBehavior MergeBehavior,
const char *Name,
uint32_t Value) {
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
}

extern "C" void LLVMRustAddModuleFlagString(
LLVMModuleRef M,
Module::ModFlagBehavior MergeBehavior,
const char *Name,
const char *Value) {
llvm::LLVMContext &Ctx = unwrap(M)->getContext();
unwrap(M)->addModuleFlag(MergeBehavior, Name, llvm::MDString::get(Ctx, Value));
}

extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
size_t Len) {
return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
Expand Down

0 comments on commit a599284

Please sign in to comment.