Fix unsafe_op_in_unsafe_fn in compiler
This commit is contained in:
parent
71eb49c318
commit
28503d69ac
15 changed files with 386 additions and 311 deletions
|
@ -120,7 +120,7 @@ pub unsafe fn create_module<'ll>(
|
|||
) -> &'ll llvm::Module {
|
||||
let sess = tcx.sess;
|
||||
let mod_name = SmallCStr::new(mod_name);
|
||||
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
|
||||
let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) };
|
||||
|
||||
let mut target_data_layout = sess.target.data_layout.to_string();
|
||||
let llvm_version = llvm_util::get_version();
|
||||
|
@ -153,11 +153,14 @@ pub unsafe fn create_module<'ll>(
|
|||
// Ensure the data-layout values hardcoded remain the defaults.
|
||||
{
|
||||
let tm = crate::back::write::create_informational_target_machine(tcx.sess);
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||
}
|
||||
|
||||
let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod);
|
||||
let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
|
||||
.expect("got a non-UTF8 data-layout from LLVM");
|
||||
let llvm_data_layout = unsafe { llvm::LLVMGetDataLayoutStr(llmod) };
|
||||
let llvm_data_layout =
|
||||
str::from_utf8(unsafe { CStr::from_ptr(llvm_data_layout) }.to_bytes())
|
||||
.expect("got a non-UTF8 data-layout from LLVM");
|
||||
|
||||
if target_data_layout != llvm_data_layout {
|
||||
tcx.dcx().emit_err(crate::errors::MismatchedDataLayout {
|
||||
|
@ -170,20 +173,28 @@ pub unsafe fn create_module<'ll>(
|
|||
}
|
||||
|
||||
let data_layout = SmallCStr::new(&target_data_layout);
|
||||
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
|
||||
unsafe {
|
||||
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
|
||||
}
|
||||
|
||||
let llvm_target = SmallCStr::new(&sess.target.llvm_target);
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
|
||||
unsafe {
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
|
||||
}
|
||||
|
||||
let reloc_model = sess.relocation_model();
|
||||
if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
|
||||
llvm::LLVMRustSetModulePICLevel(llmod);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModulePICLevel(llmod);
|
||||
}
|
||||
// PIE is potentially more effective than PIC, but can only be used in executables.
|
||||
// If all our outputs are executables, then we can relax PIC to PIE.
|
||||
if reloc_model == RelocModel::Pie
|
||||
|| tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable)
|
||||
{
|
||||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,95 +203,109 @@ pub unsafe fn create_module<'ll>(
|
|||
// longer jumps) if a larger code model is used with a smaller one.
|
||||
//
|
||||
// See https://reviews.llvm.org/D52322 and https://reviews.llvm.org/D52323.
|
||||
llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
|
||||
}
|
||||
|
||||
// If skipping the PLT is enabled, we need to add some module metadata
|
||||
// to ensure intrinsic calls don't use it.
|
||||
if !sess.needs_plt() {
|
||||
let avoid_plt = c"RtLibUseGOT".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 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.)
|
||||
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::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||
if sess.target.is_like_msvc {
|
||||
match sess.opts.cg.control_flow_guard {
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
2,
|
||||
)
|
||||
unsafe {
|
||||
match sess.opts.cg.control_flow_guard {
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||
if sess.target.arch == "aarch64" {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
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::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
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::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
bug!(
|
||||
"branch-protection used on non-AArch64 target; \
|
||||
|
@ -291,39 +316,47 @@ 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::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
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::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
||||
if sess.opts.unstable_opts.ehcont_guard {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Insert `llvm.ident` metadata.
|
||||
|
@ -333,16 +366,20 @@ pub unsafe fn create_module<'ll>(
|
|||
#[allow(clippy::option_env_unwrap)]
|
||||
let rustc_producer =
|
||||
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
|
||||
let name_metadata = llvm::LLVMMDStringInContext(
|
||||
llcx,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
rustc_producer.as_bytes().len() as c_uint,
|
||||
);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
||||
);
|
||||
let name_metadata = unsafe {
|
||||
llvm::LLVMMDStringInContext(
|
||||
llcx,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
rustc_producer.as_bytes().len() as c_uint,
|
||||
)
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
||||
);
|
||||
}
|
||||
|
||||
// Emit RISC-V specific target-abi metadata
|
||||
// to workaround lld as the LTO plugin not
|
||||
|
@ -351,13 +388,15 @@ pub unsafe fn create_module<'ll>(
|
|||
// 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(),
|
||||
);
|
||||
unsafe {
|
||||
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
|
||||
|
@ -375,7 +414,7 @@ pub unsafe fn create_module<'ll>(
|
|||
// We already checked this during option parsing
|
||||
_ => unreachable!(),
|
||||
};
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value)
|
||||
unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value) }
|
||||
}
|
||||
|
||||
llmod
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue