Clean up FFI calls for setting module flags
- Don't rely on enum values defined by LLVM's C++ API - Use safe wrapper functions instead of direct `unsafe` calls - Consistently pass pointer/length strings instead of C strings
This commit is contained in:
parent
ba81dbf3c6
commit
8d2ed4f0f3
@ -210,133 +210,111 @@ pub(crate) unsafe fn create_module<'ll>(
|
||||
// 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();
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
}
|
||||
llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "RtLibUseGOT", 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();
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"CFI Canonical Jump Tables",
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
// If we're normalizing integers with CFI, ensure LLVM generated functions do the same.
|
||||
// See https://github.com/llvm/llvm-project/pull/104826
|
||||
if sess.is_sanitizer_cfi_normalize_integers_enabled() {
|
||||
let cfi_normalize_integers = c"cfi-normalize-integers".as_ptr();
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
cfi_normalize_integers,
|
||||
1,
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"cfi-normalize-integers",
|
||||
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();
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"EnableSplitLTOUnit",
|
||||
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();
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
}
|
||||
llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Override, "kcfi", 1);
|
||||
|
||||
// Add "kcfi-offset" module flag with -Z patchable-function-entry (See
|
||||
// https://reviews.llvm.org/D141172).
|
||||
let pfe =
|
||||
PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry);
|
||||
if pfe.prefix() > 0 {
|
||||
let kcfi_offset = c"kcfi-offset".as_ptr();
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
kcfi_offset,
|
||||
pfe.prefix().into(),
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"kcfi-offset",
|
||||
pfe.prefix().into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||
if sess.target.is_like_msvc {
|
||||
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,
|
||||
)
|
||||
}
|
||||
match sess.opts.cg.control_flow_guard {
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Warning,
|
||||
"cfguard",
|
||||
1,
|
||||
);
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Warning,
|
||||
"cfguard",
|
||||
2,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||
if sess.target.arch == "aarch64" {
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr(),
|
||||
bti.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address".as_ptr(),
|
||||
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(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Min,
|
||||
"branch-target-enforcement",
|
||||
bti.into(),
|
||||
);
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Min,
|
||||
"sign-return-address",
|
||||
pac_ret.is_some().into(),
|
||||
);
|
||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Min,
|
||||
"sign-return-address-all",
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Min,
|
||||
"sign-return-address-with-bkey",
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
} else {
|
||||
bug!(
|
||||
"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).
|
||||
if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"cf-protection-branch",
|
||||
1,
|
||||
);
|
||||
}
|
||||
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"cf-protection-return",
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
"Virtual Function Elim",
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
||||
if sess.opts.unstable_opts.ehcont_guard {
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "ehcontguard", 1);
|
||||
}
|
||||
|
||||
match sess.opts.unstable_opts.function_return {
|
||||
FunctionReturn::Keep => {}
|
||||
FunctionReturn::ThunkExtern => unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
FunctionReturn::ThunkExtern => {
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"function_return_thunk_extern".as_ptr(),
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"function_return_thunk_extern",
|
||||
1,
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// an LLVM module flag to control this.
|
||||
(Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => {
|
||||
let flag = SmallCStr::new(flag.as_ref());
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
flag.as_c_str().as_ptr(),
|
||||
threshold as u32,
|
||||
)
|
||||
}
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
&flag,
|
||||
threshold as u32,
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
@ -449,33 +411,29 @@ pub(crate) 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() {
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagString(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"target-abi".as_ptr(),
|
||||
llvm_abiname.as_c_char_ptr(),
|
||||
llvm_abiname.len(),
|
||||
);
|
||||
}
|
||||
llvm::add_module_flag_str(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
"target-abi",
|
||||
llvm_abiname,
|
||||
);
|
||||
}
|
||||
|
||||
// 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");
|
||||
let behavior = match behavior.as_str() {
|
||||
"error" => llvm::LLVMModFlagBehavior::Error,
|
||||
"warning" => llvm::LLVMModFlagBehavior::Warning,
|
||||
"require" => llvm::LLVMModFlagBehavior::Require,
|
||||
"override" => llvm::LLVMModFlagBehavior::Override,
|
||||
"append" => llvm::LLVMModFlagBehavior::Append,
|
||||
"appendunique" => llvm::LLVMModFlagBehavior::AppendUnique,
|
||||
"max" => llvm::LLVMModFlagBehavior::Max,
|
||||
"min" => llvm::LLVMModFlagBehavior::Min,
|
||||
for (key, value, merge_behavior) in &sess.opts.unstable_opts.llvm_module_flag {
|
||||
let merge_behavior = match merge_behavior.as_str() {
|
||||
"error" => llvm::ModuleFlagMergeBehavior::Error,
|
||||
"warning" => llvm::ModuleFlagMergeBehavior::Warning,
|
||||
"require" => llvm::ModuleFlagMergeBehavior::Require,
|
||||
"override" => llvm::ModuleFlagMergeBehavior::Override,
|
||||
"append" => llvm::ModuleFlagMergeBehavior::Append,
|
||||
"appendunique" => llvm::ModuleFlagMergeBehavior::AppendUnique,
|
||||
"max" => llvm::ModuleFlagMergeBehavior::Max,
|
||||
"min" => llvm::ModuleFlagMergeBehavior::Min,
|
||||
// We already checked this during option parsing
|
||||
_ => unreachable!(),
|
||||
};
|
||||
unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_c_char_ptr(), *value) }
|
||||
llvm::add_module_flag_u32(llmod, merge_behavior, key, *value);
|
||||
}
|
||||
|
||||
llmod
|
||||
|
@ -91,45 +91,39 @@ pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
|
||||
}
|
||||
|
||||
pub(crate) fn finalize(&self, sess: &Session) {
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderFinalize(self.builder);
|
||||
|
||||
if !sess.target.is_like_msvc {
|
||||
// Debuginfo generation in LLVM by default uses a higher
|
||||
// version of dwarf than macOS currently understands. We can
|
||||
// instruct LLVM to emit an older version of dwarf, however,
|
||||
// for macOS to understand. For more info see #11352
|
||||
// This can be overridden using --llvm-opts -dwarf-version,N.
|
||||
// Android has the same issue (#22398)
|
||||
let dwarf_version = sess
|
||||
.opts
|
||||
.unstable_opts
|
||||
.dwarf_version
|
||||
.unwrap_or(sess.target.default_dwarf_version);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"Dwarf Version".as_ptr(),
|
||||
dwarf_version,
|
||||
);
|
||||
} else {
|
||||
// Indicate that we want CodeView debug information on MSVC
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"CodeView".as_ptr(),
|
||||
1,
|
||||
)
|
||||
}
|
||||
|
||||
// Prevent bitcode readers from deleting the debug info.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder) };
|
||||
if !sess.target.is_like_msvc {
|
||||
// Debuginfo generation in LLVM by default uses a higher
|
||||
// version of dwarf than macOS currently understands. We can
|
||||
// instruct LLVM to emit an older version of dwarf, however,
|
||||
// for macOS to understand. For more info see #11352
|
||||
// This can be overridden using --llvm-opts -dwarf-version,N.
|
||||
// Android has the same issue (#22398)
|
||||
let dwarf_version =
|
||||
sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version);
|
||||
llvm::add_module_flag_u32(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"Debug Info Version".as_ptr(),
|
||||
llvm::LLVMRustDebugMetadataVersion(),
|
||||
llvm::ModuleFlagMergeBehavior::Warning,
|
||||
"Dwarf Version",
|
||||
dwarf_version,
|
||||
);
|
||||
} else {
|
||||
// Indicate that we want CodeView debug information on MSVC
|
||||
llvm::add_module_flag_u32(
|
||||
self.llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Warning,
|
||||
"CodeView",
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
// Prevent bitcode readers from deleting the debug info.
|
||||
llvm::add_module_flag_u32(
|
||||
self.llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Warning,
|
||||
"Debug Info Version",
|
||||
unsafe { llvm::LLVMRustDebugMetadataVersion() },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ pub enum LLVMMachineType {
|
||||
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
|
||||
/// 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,
|
||||
/// '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)]
|
||||
#[repr(C)]
|
||||
pub enum LLVMModFlagBehavior {
|
||||
pub enum ModuleFlagMergeBehavior {
|
||||
Error = 1,
|
||||
Warning = 2,
|
||||
Require = 3,
|
||||
@ -1829,17 +1833,19 @@ pub(crate) fn LLVMRustCoverageCreatePGOFuncNameVar(
|
||||
/// "compatible" means depends on the merge behaviors involved.
|
||||
pub fn LLVMRustAddModuleFlagU32(
|
||||
M: &Module,
|
||||
merge_behavior: LLVMModFlagBehavior,
|
||||
name: *const c_char,
|
||||
value: u32,
|
||||
MergeBehavior: ModuleFlagMergeBehavior,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
Value: u32,
|
||||
);
|
||||
|
||||
pub fn LLVMRustAddModuleFlagString(
|
||||
M: &Module,
|
||||
merge_behavior: LLVMModFlagBehavior,
|
||||
name: *const c_char,
|
||||
value: *const c_char,
|
||||
value_len: size_t,
|
||||
MergeBehavior: ModuleFlagMergeBehavior,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
Value: *const c_char,
|
||||
ValueLen: size_t,
|
||||
);
|
||||
|
||||
pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
|
||||
|
@ -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,17 +853,60 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
|
||||
|
||||
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
|
||||
|
||||
extern "C" void LLVMRustAddModuleFlagU32(LLVMModuleRef M,
|
||||
Module::ModFlagBehavior MergeBehavior,
|
||||
const char *Name, uint32_t Value) {
|
||||
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
|
||||
// FFI equivalent of LLVM's `llvm::Module::ModFlagBehavior`.
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::llvm::ffi::ModuleFlagMergeBehavior`.
|
||||
//
|
||||
// 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(
|
||||
LLVMModuleRef M, Module::ModFlagBehavior MergeBehavior, const char *Name,
|
||||
const char *Value, size_t ValueLen) {
|
||||
LLVMModuleRef M, LLVMRustModuleFlagMergeBehavior MergeBehavior,
|
||||
const char *Name, size_t NameLen, const char *Value, size_t ValueLen) {
|
||||
unwrap(M)->addModuleFlag(
|
||||
MergeBehavior, Name,
|
||||
fromRust(MergeBehavior), StringRef(Name, NameLen),
|
||||
MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen)));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user