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:
commit
2ddf984594
11 changed files with 177 additions and 21 deletions
|
@ -608,7 +608,7 @@ pub(crate) fn run_pass_manager(
|
||||||
"LTOPostLink".as_ptr().cast(),
|
"LTOPostLink".as_ptr().cast(),
|
||||||
11,
|
11,
|
||||||
) {
|
) {
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
module.module_llvm.llmod(),
|
module.module_llvm.llmod(),
|
||||||
llvm::LLVMModFlagBehavior::Error,
|
llvm::LLVMModFlagBehavior::Error,
|
||||||
c"LTOPostLink".as_ptr().cast(),
|
c"LTOPostLink".as_ptr().cast(),
|
||||||
|
|
|
@ -180,13 +180,13 @@ pub unsafe fn create_module<'ll>(
|
||||||
// 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().cast();
|
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.)
|
// 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().cast();
|
let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast();
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::LLVMModFlagBehavior::Override,
|
||||||
canonical_jump_tables,
|
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.)
|
// 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() {
|
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
|
||||||
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast();
|
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast();
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::LLVMModFlagBehavior::Override,
|
||||||
enable_split_lto_unit,
|
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.)
|
// 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().cast();
|
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.
|
// 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::Disabled => {}
|
||||||
CFGuard::NoChecks => {
|
CFGuard::NoChecks => {
|
||||||
// Set `cfguard=1` module flag to emit metadata only.
|
// Set `cfguard=1` module flag to emit metadata only.
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
c"cfguard".as_ptr() as *const _,
|
c"cfguard".as_ptr() as *const _,
|
||||||
|
@ -226,7 +226,7 @@ pub unsafe fn create_module<'ll>(
|
||||||
}
|
}
|
||||||
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::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
c"cfguard".as_ptr() as *const _,
|
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 let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||||
if sess.target.arch == "aarch64" {
|
if sess.target.arch == "aarch64" {
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::LLVMModFlagBehavior::Min,
|
||||||
c"branch-target-enforcement".as_ptr().cast(),
|
c"branch-target-enforcement".as_ptr().cast(),
|
||||||
bti.into(),
|
bti.into(),
|
||||||
);
|
);
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::LLVMModFlagBehavior::Min,
|
||||||
c"sign-return-address".as_ptr().cast(),
|
c"sign-return-address".as_ptr().cast(),
|
||||||
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::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::LLVMModFlagBehavior::Min,
|
||||||
c"sign-return-address-all".as_ptr().cast(),
|
c"sign-return-address-all".as_ptr().cast(),
|
||||||
pac_opts.leaf.into(),
|
pac_opts.leaf.into(),
|
||||||
);
|
);
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Min,
|
llvm::LLVMModFlagBehavior::Min,
|
||||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
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).
|
// 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 {
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::LLVMModFlagBehavior::Override,
|
||||||
c"cf-protection-branch".as_ptr().cast(),
|
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 {
|
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Override,
|
llvm::LLVMModFlagBehavior::Override,
|
||||||
c"cf-protection-return".as_ptr().cast(),
|
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 {
|
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Error,
|
llvm::LLVMModFlagBehavior::Error,
|
||||||
c"Virtual Function Elim".as_ptr().cast(),
|
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).
|
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
||||||
if sess.opts.unstable_opts.ehcont_guard {
|
if sess.opts.unstable_opts.ehcont_guard {
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
llmod,
|
llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
c"ehcontguard".as_ptr() as *const _,
|
c"ehcontguard".as_ptr() as *const _,
|
||||||
|
@ -326,6 +326,22 @@ pub unsafe fn create_module<'ll>(
|
||||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
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
|
// Add module flags specified via -Z llvm_module_flag
|
||||||
for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
|
for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
|
||||||
let key = format!("{key}\0");
|
let key = format!("{key}\0");
|
||||||
|
@ -341,7 +357,7 @@ pub unsafe fn create_module<'ll>(
|
||||||
// We already checked this during option parsing
|
// We already checked this during option parsing
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
llvm::LLVMRustAddModuleFlag(llmod, behavior, key.as_ptr().cast(), *value)
|
llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
llmod
|
llmod
|
||||||
|
|
|
@ -110,7 +110,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||||
.unstable_opts
|
.unstable_opts
|
||||||
.dwarf_version
|
.dwarf_version
|
||||||
.unwrap_or(sess.target.default_dwarf_version);
|
.unwrap_or(sess.target.default_dwarf_version);
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
self.llmod,
|
self.llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
c"Dwarf Version".as_ptr().cast(),
|
c"Dwarf Version".as_ptr().cast(),
|
||||||
|
@ -118,7 +118,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Indicate that we want CodeView debug information on MSVC
|
// Indicate that we want CodeView debug information on MSVC
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
self.llmod,
|
self.llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
c"CodeView".as_ptr().cast(),
|
c"CodeView".as_ptr().cast(),
|
||||||
|
@ -127,7 +127,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent bitcode readers from deleting the debug info.
|
// Prevent bitcode readers from deleting the debug info.
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlagU32(
|
||||||
self.llmod,
|
self.llmod,
|
||||||
llvm::LLVMModFlagBehavior::Warning,
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
c"Debug Info Version".as_ptr().cast(),
|
c"Debug Info Version".as_ptr().cast(),
|
||||||
|
|
|
@ -1801,12 +1801,21 @@ extern "C" {
|
||||||
///
|
///
|
||||||
/// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
|
/// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
|
||||||
/// "compatible" means depends on the merge behaviors involved.
|
/// "compatible" means depends on the merge behaviors involved.
|
||||||
pub fn LLVMRustAddModuleFlag(
|
pub fn LLVMRustAddModuleFlagU32(
|
||||||
M: &Module,
|
M: &Module,
|
||||||
merge_behavior: LLVMModFlagBehavior,
|
merge_behavior: LLVMModFlagBehavior,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
value: u32,
|
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 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<'_>;
|
||||||
|
|
|
@ -817,7 +817,7 @@ 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 LLVMRustAddModuleFlag(
|
extern "C" void LLVMRustAddModuleFlagU32(
|
||||||
LLVMModuleRef M,
|
LLVMModuleRef M,
|
||||||
Module::ModFlagBehavior MergeBehavior,
|
Module::ModFlagBehavior MergeBehavior,
|
||||||
const char *Name,
|
const char *Name,
|
||||||
|
@ -825,6 +825,16 @@ extern "C" void LLVMRustAddModuleFlag(
|
||||||
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
|
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMRustAddModuleFlagString(
|
||||||
|
LLVMModuleRef M,
|
||||||
|
Module::ModFlagBehavior MergeBehavior,
|
||||||
|
const char *Name,
|
||||||
|
const char *Value,
|
||||||
|
size_t ValueLen) {
|
||||||
|
unwrap(M)->addModuleFlag(MergeBehavior, Name,
|
||||||
|
MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen)));
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
|
extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
|
||||||
size_t Len) {
|
size_t Len) {
|
||||||
return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
|
return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
|
||||||
|
|
|
@ -819,6 +819,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
||||||
"needs-dynamic-linking",
|
"needs-dynamic-linking",
|
||||||
"needs-git-hash",
|
"needs-git-hash",
|
||||||
"needs-llvm-components",
|
"needs-llvm-components",
|
||||||
|
"needs-matching-clang",
|
||||||
"needs-profiler-support",
|
"needs-profiler-support",
|
||||||
"needs-relocation-model-pic",
|
"needs-relocation-model-pic",
|
||||||
"needs-run-enabled",
|
"needs-run-enabled",
|
||||||
|
|
|
@ -86,6 +86,18 @@ impl Rustc {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This flag defers LTO optimizations to the linker.
|
||||||
|
pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
|
||||||
|
self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specify what happens when the code panics.
|
||||||
|
pub fn panic(&mut self, option: &str) -> &mut Self {
|
||||||
|
self.cmd.arg(format!("-Cpanic={option}"));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Specify number of codegen units
|
/// Specify number of codegen units
|
||||||
pub fn codegen_units(&mut self, units: usize) -> &mut Self {
|
pub fn codegen_units(&mut self, units: usize) -> &mut Self {
|
||||||
self.cmd.arg(format!("-Ccodegen-units={units}"));
|
self.cmd.arg(format!("-Ccodegen-units={units}"));
|
||||||
|
|
20
tests/codegen/riscv-target-abi.rs
Normal file
20
tests/codegen/riscv-target-abi.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//@ revisions:riscv64gc riscv32gc riscv32imac
|
||||||
|
|
||||||
|
//@[riscv64gc] compile-flags: --target=riscv64gc-unknown-linux-gnu
|
||||||
|
//@[riscv64gc] needs-llvm-components: riscv
|
||||||
|
// riscv64gc: !{i32 1, !"target-abi", !"lp64d"}
|
||||||
|
|
||||||
|
//@[riscv32gc] compile-flags: --target=riscv32gc-unknown-linux-musl
|
||||||
|
//@[riscv32gc] needs-llvm-components: riscv
|
||||||
|
// riscv32gc: !{i32 1, !"target-abi", !"ilp32d"}
|
||||||
|
|
||||||
|
//@[riscv32imac] compile-flags: --target=riscv32imac-unknown-none-elf
|
||||||
|
//@[riscv32imac] needs-llvm-components: riscv
|
||||||
|
// riscv32imac-NOT: !"target-abi"
|
||||||
|
|
||||||
|
#![feature(no_core, lang_items)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
5
tests/run-make/cross-lang-lto-riscv-abi/cstart.c
Normal file
5
tests/run-make/cross-lang-lto-riscv-abi/cstart.c
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
extern void hello();
|
||||||
|
|
||||||
|
void _start() {
|
||||||
|
hello();
|
||||||
|
}
|
9
tests/run-make/cross-lang-lto-riscv-abi/riscv-xlto.rs
Normal file
9
tests/run-make/cross-lang-lto-riscv-abi/riscv-xlto.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#![allow(internal_features)]
|
||||||
|
#![feature(no_core, lang_items)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn hello() {}
|
74
tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
Normal file
74
tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
//! Make sure that cross-language LTO works on riscv targets,
|
||||||
|
//! which requires extra abi metadata to be emitted.
|
||||||
|
//@ needs-matching-clang
|
||||||
|
//@ needs-llvm-components riscv
|
||||||
|
extern crate run_make_support;
|
||||||
|
|
||||||
|
use run_make_support::{bin_name, rustc, tmp_dir};
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
path::PathBuf,
|
||||||
|
process::{Command, Output},
|
||||||
|
str,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn handle_failed_output(output: Output) {
|
||||||
|
eprintln!("output status: `{}`", output.status);
|
||||||
|
eprintln!("=== STDOUT ===\n{}\n\n", String::from_utf8(output.stdout).unwrap());
|
||||||
|
eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
|
||||||
|
std::process::exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float: bool) {
|
||||||
|
eprintln!("Checking target {target}");
|
||||||
|
// Rust part
|
||||||
|
rustc()
|
||||||
|
.input("riscv-xlto.rs")
|
||||||
|
.crate_type("rlib")
|
||||||
|
.target(target)
|
||||||
|
.panic("abort")
|
||||||
|
.linker_plugin_lto("on")
|
||||||
|
.run();
|
||||||
|
// C part
|
||||||
|
let clang = env::var("CLANG").unwrap();
|
||||||
|
let mut cmd = Command::new(clang);
|
||||||
|
let executable = tmp_dir().join("riscv-xlto");
|
||||||
|
cmd.arg("-target")
|
||||||
|
.arg(clang_target)
|
||||||
|
.arg(format!("-march={carch}"))
|
||||||
|
.arg(format!("-flto=thin"))
|
||||||
|
.arg(format!("-fuse-ld=lld"))
|
||||||
|
.arg("-nostdlib")
|
||||||
|
.arg("-o")
|
||||||
|
.arg(&executable)
|
||||||
|
.arg("cstart.c")
|
||||||
|
.arg(tmp_dir().join("libriscv_xlto.rlib"));
|
||||||
|
eprintln!("{cmd:?}");
|
||||||
|
let output = cmd.output().unwrap();
|
||||||
|
if !output.status.success() {
|
||||||
|
handle_failed_output(output);
|
||||||
|
}
|
||||||
|
// Check that the built binary has correct float abi
|
||||||
|
let llvm_readobj =
|
||||||
|
PathBuf::from(env::var("LLVM_BIN_DIR").unwrap()).join(bin_name("llvm-readobj"));
|
||||||
|
let mut cmd = Command::new(llvm_readobj);
|
||||||
|
cmd.arg("--file-header").arg(executable);
|
||||||
|
eprintln!("{cmd:?}");
|
||||||
|
let output = cmd.output().unwrap();
|
||||||
|
if output.status.success() {
|
||||||
|
assert!(
|
||||||
|
!(is_double_float
|
||||||
|
^ dbg!(str::from_utf8(&output.stdout).unwrap())
|
||||||
|
.contains("EF_RISCV_FLOAT_ABI_DOUBLE"))
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
handle_failed_output(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
check_target("riscv64gc-unknown-linux-gnu", "riscv64-linux-gnu", "rv64gc", true);
|
||||||
|
check_target("riscv64imac-unknown-none-elf", "riscv64-unknown-elf", "rv64imac", false);
|
||||||
|
check_target("riscv32imac-unknown-none-elf", "riscv32-unknown-elf", "rv32imac", false);
|
||||||
|
check_target("riscv32gc-unknown-linux-gnu", "riscv32-linux-gnu", "rv32gc", true);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue