Auto merge of #132167 - Zalathar:llvm-wrappers, r=jieyouxu
Replace some LLVMRust wrappers with calls to the LLVM C API This PR removes the LLVMRust wrapper functions for getting/setting linkage and visibility, and replaces them with direct calls to the corresponding functions in LLVM's C API. To make this convenient and sound, two pieces of supporting code have also been added: - A simple proc-macro that derives `TryFrom<u32>` for fieldless enums - A wrapper type for C enum values returned by LLVM functions, to ensure soundness if LLVM returns an enum value we don't know about In a few places, the use of safe wrapper functions means that an `unsafe` block is no longer needed, so the affected code has changed its indentation level.
This commit is contained in:
commit
be33e4f3d6
18 changed files with 321 additions and 229 deletions
|
@ -77,20 +77,14 @@ pub(crate) unsafe fn codegen(
|
|||
// __rust_alloc_error_handler_should_panic
|
||||
let name = OomStrategy::SYMBOL;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
llvm::LLVMRustSetVisibility(
|
||||
ll_g,
|
||||
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
|
||||
);
|
||||
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
llvm::LLVMRustSetVisibility(
|
||||
ll_g,
|
||||
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
|
||||
);
|
||||
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
}
|
||||
|
@ -134,10 +128,7 @@ fn create_wrapper_function(
|
|||
None
|
||||
};
|
||||
|
||||
llvm::LLVMRustSetVisibility(
|
||||
llfn,
|
||||
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
|
||||
);
|
||||
llvm::set_visibility(llfn, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||
|
||||
if tcx.sess.must_emit_unwind_tables() {
|
||||
let uwtable =
|
||||
|
@ -151,7 +142,7 @@ fn create_wrapper_function(
|
|||
// -> ! DIFlagNoReturn
|
||||
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
|
||||
}
|
||||
llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
|
||||
llvm::set_visibility(callee, llvm::Visibility::Hidden);
|
||||
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr());
|
||||
|
||||
|
|
|
@ -1043,7 +1043,7 @@ unsafe fn embed_bitcode(
|
|||
|
||||
let section = bitcode_section_name(cgcx);
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
|
||||
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
|
||||
|
@ -1061,7 +1061,7 @@ unsafe fn embed_bitcode(
|
|||
c".llvmcmd"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
} else {
|
||||
// We need custom section flags, so emit module-level inline assembly.
|
||||
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
|
||||
|
@ -1096,7 +1096,7 @@ fn create_msvc_imps(
|
|||
let ptr_ty = Type::ptr_llcx(llcx);
|
||||
let globals = base::iter_globals(llmod)
|
||||
.filter(|&val| {
|
||||
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage
|
||||
llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage
|
||||
&& llvm::LLVMIsDeclaration(val) == 0
|
||||
})
|
||||
.filter_map(|val| {
|
||||
|
@ -1115,7 +1115,7 @@ fn create_msvc_imps(
|
|||
for (imp_name, val) in globals {
|
||||
let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr());
|
||||
llvm::LLVMSetInitializer(imp, val);
|
||||
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
|
||||
llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,9 +95,9 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
|||
// whether we are sharing generics or not. The important thing here is
|
||||
// that the visibility we apply to the declaration is the same one that
|
||||
// has been applied to the definition (wherever that definition may be).
|
||||
unsafe {
|
||||
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
|
||||
|
||||
llvm::set_linkage(llfn, llvm::Linkage::ExternalLinkage);
|
||||
unsafe {
|
||||
let is_generic = instance.args.non_erasable_generics().next().is_some();
|
||||
|
||||
let is_hidden = if is_generic {
|
||||
|
@ -135,7 +135,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
|||
|| !cx.tcx.is_reachable_non_generic(instance_def_id))
|
||||
};
|
||||
if is_hidden {
|
||||
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
|
||||
llvm::set_visibility(llfn, llvm::Visibility::Hidden);
|
||||
}
|
||||
|
||||
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
||||
|
|
|
@ -219,8 +219,8 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
llvm::LLVMSetInitializer(g, sc);
|
||||
llvm::LLVMSetGlobalConstant(g, True);
|
||||
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
|
||||
llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
|
||||
}
|
||||
llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
|
||||
(s.to_owned(), g)
|
||||
})
|
||||
.1;
|
||||
|
|
|
@ -172,29 +172,27 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
if let Some(linkage) = attrs.import_linkage {
|
||||
debug!("get_static: sym={} linkage={:?}", sym, linkage);
|
||||
|
||||
unsafe {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
let g1 = cx.declare_global(sym, cx.type_i8());
|
||||
llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
let g1 = cx.declare_global(sym, cx.type_i8());
|
||||
llvm::set_linkage(g1, base::linkage_to_llvm(linkage));
|
||||
|
||||
// Declare an internal global `extern_with_linkage_foo` which
|
||||
// is initialized with the address of `foo`. If `foo` is
|
||||
// discarded during linking (for example, if `foo` has weak
|
||||
// linkage and there are no definitions), then
|
||||
// `extern_with_linkage_foo` will instead be initialized to
|
||||
// zero.
|
||||
let mut real_name = "_rust_extern_with_linkage_".to_string();
|
||||
real_name.push_str(sym);
|
||||
let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
|
||||
cx.sess().dcx().emit_fatal(SymbolAlreadyDefined {
|
||||
span: cx.tcx.def_span(def_id),
|
||||
symbol_name: sym,
|
||||
})
|
||||
});
|
||||
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
||||
llvm::LLVMSetInitializer(g2, g1);
|
||||
g2
|
||||
}
|
||||
// Declare an internal global `extern_with_linkage_foo` which
|
||||
// is initialized with the address of `foo`. If `foo` is
|
||||
// discarded during linking (for example, if `foo` has weak
|
||||
// linkage and there are no definitions), then
|
||||
// `extern_with_linkage_foo` will instead be initialized to
|
||||
// zero.
|
||||
let mut real_name = "_rust_extern_with_linkage_".to_string();
|
||||
real_name.push_str(sym);
|
||||
let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
|
||||
cx.sess().dcx().emit_fatal(SymbolAlreadyDefined {
|
||||
span: cx.tcx.def_span(def_id),
|
||||
symbol_name: sym,
|
||||
})
|
||||
});
|
||||
llvm::set_linkage(g2, llvm::Linkage::InternalLinkage);
|
||||
unsafe { llvm::LLVMSetInitializer(g2, g1) };
|
||||
g2
|
||||
} else if cx.tcx.sess.target.arch == "x86"
|
||||
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
|
||||
{
|
||||
|
@ -224,23 +222,21 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
align: Align,
|
||||
kind: Option<&str>,
|
||||
) -> &'ll Value {
|
||||
unsafe {
|
||||
let gv = match kind {
|
||||
Some(kind) if !self.tcx.sess.fewer_names() => {
|
||||
let name = self.generate_local_symbol_name(kind);
|
||||
let gv = self.define_global(&name, self.val_ty(cv)).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", name);
|
||||
});
|
||||
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
|
||||
gv
|
||||
}
|
||||
_ => self.define_private_global(self.val_ty(cv)),
|
||||
};
|
||||
llvm::LLVMSetInitializer(gv, cv);
|
||||
set_global_alignment(self, gv, align);
|
||||
llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
|
||||
gv
|
||||
}
|
||||
let gv = match kind {
|
||||
Some(kind) if !self.tcx.sess.fewer_names() => {
|
||||
let name = self.generate_local_symbol_name(kind);
|
||||
let gv = self.define_global(&name, self.val_ty(cv)).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", name);
|
||||
});
|
||||
llvm::set_linkage(gv, llvm::Linkage::PrivateLinkage);
|
||||
gv
|
||||
}
|
||||
_ => self.define_private_global(self.val_ty(cv)),
|
||||
};
|
||||
unsafe { llvm::LLVMSetInitializer(gv, cv) };
|
||||
set_global_alignment(self, gv, align);
|
||||
llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
|
||||
gv
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
|
@ -292,9 +288,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
let g = self.declare_global(sym, llty);
|
||||
|
||||
if !self.tcx.is_reachable_non_generic(def_id) {
|
||||
unsafe {
|
||||
llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
|
||||
}
|
||||
llvm::set_visibility(g, llvm::Visibility::Hidden);
|
||||
}
|
||||
|
||||
g
|
||||
|
@ -312,7 +306,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
llvm::set_thread_local_mode(g, self.tls_model);
|
||||
}
|
||||
|
||||
let dso_local = unsafe { self.should_assume_dso_local(g, true) };
|
||||
let dso_local = self.should_assume_dso_local(g, true);
|
||||
if dso_local {
|
||||
unsafe {
|
||||
llvm::LLVMRustSetDSOLocal(g, true);
|
||||
|
@ -401,8 +395,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
let name = llvm::get_value_name(g).to_vec();
|
||||
llvm::set_value_name(g, b"");
|
||||
|
||||
let linkage = llvm::LLVMRustGetLinkage(g);
|
||||
let visibility = llvm::LLVMRustGetVisibility(g);
|
||||
let linkage = llvm::get_linkage(g);
|
||||
let visibility = llvm::get_visibility(g);
|
||||
|
||||
let new_g = llvm::LLVMRustGetOrInsertGlobal(
|
||||
self.llmod,
|
||||
|
@ -411,8 +405,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
val_llty,
|
||||
);
|
||||
|
||||
llvm::LLVMRustSetLinkage(new_g, linkage);
|
||||
llvm::LLVMRustSetVisibility(new_g, visibility);
|
||||
llvm::set_linkage(new_g, linkage);
|
||||
llvm::set_visibility(new_g, visibility);
|
||||
|
||||
// The old global has had its name removed but is returned by
|
||||
// get_static since it is in the instance cache. Provide an
|
||||
|
|
|
@ -605,7 +605,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
unsafe {
|
||||
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
|
||||
llvm::LLVMSetInitializer(g, array);
|
||||
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
|
||||
llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
|
||||
llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
|
|||
llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
|
||||
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
||||
llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
|
||||
llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
|
||||
llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
|
||||
// This should make sure that the whole section is not larger than
|
||||
// the string it contains. Otherwise we get a warning from GDB.
|
||||
llvm::LLVMSetAlignment(section_var, 1);
|
||||
|
|
|
@ -785,13 +785,12 @@ fn codegen_msvc_try<'ll>(
|
|||
let type_info =
|
||||
bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false);
|
||||
let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
|
||||
unsafe {
|
||||
llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
|
||||
if bx.cx.tcx.sess.target.supports_comdat() {
|
||||
llvm::SetUniqueComdat(bx.llmod, tydesc);
|
||||
}
|
||||
llvm::LLVMSetInitializer(tydesc, type_info);
|
||||
|
||||
llvm::set_linkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
|
||||
if bx.cx.tcx.sess.target.supports_comdat() {
|
||||
llvm::SetUniqueComdat(bx.llmod, tydesc);
|
||||
}
|
||||
unsafe { llvm::LLVMSetInitializer(tydesc, type_info) };
|
||||
|
||||
// The flag value of 8 indicates that we are catching the exception by
|
||||
// reference instead of by value. We can't use catch by value because
|
||||
|
@ -1064,7 +1063,7 @@ fn gen_fn<'ll, 'tcx>(
|
|||
cx.set_frame_pointer_type(llfn);
|
||||
cx.apply_target_cpu_attr(llfn);
|
||||
// FIXME(eddyb) find a nicer way to do this.
|
||||
unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
|
||||
llvm::set_linkage(llfn, llvm::Linkage::InternalLinkage);
|
||||
let llbb = Builder::append_block(cx, llfn, "entry-block");
|
||||
let bx = Builder::build(cx, llbb);
|
||||
codegen(bx);
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
|
||||
use rustc_macros::TryFromU32;
|
||||
use rustc_target::spec::SymbolVisibility;
|
||||
|
||||
use super::RustString;
|
||||
|
@ -19,6 +21,30 @@ pub type Bool = c_uint;
|
|||
pub const True: Bool = 1 as Bool;
|
||||
pub const False: Bool = 0 as Bool;
|
||||
|
||||
/// Wrapper for a raw enum value returned from LLVM's C APIs.
|
||||
///
|
||||
/// For C enums returned by LLVM, it's risky to use a Rust enum as the return
|
||||
/// type, because it would be UB if a later version of LLVM adds a new enum
|
||||
/// value and returns it. Instead, return this raw wrapper, then convert to the
|
||||
/// Rust-side enum explicitly.
|
||||
#[repr(transparent)]
|
||||
pub struct RawEnum<T> {
|
||||
value: u32,
|
||||
/// We don't own or consume a `T`, but we can produce one.
|
||||
_rust_side_type: PhantomData<fn() -> T>,
|
||||
}
|
||||
|
||||
impl<T: TryFrom<u32>> RawEnum<T> {
|
||||
#[track_caller]
|
||||
pub(crate) fn to_rust(self) -> T
|
||||
where
|
||||
T::Error: Debug,
|
||||
{
|
||||
// If this fails, the Rust-side enum is out of sync with LLVM's enum.
|
||||
T::try_from(self.value).expect("enum value returned by LLVM should be known")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[repr(C)]
|
||||
#[allow(dead_code)] // Variants constructed by C++.
|
||||
|
@ -108,26 +134,36 @@ pub enum CallConv {
|
|||
AvrInterrupt = 85,
|
||||
}
|
||||
|
||||
/// LLVMRustLinkage
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
/// Must match the layout of `LLVMLinkage`.
|
||||
#[derive(Copy, Clone, PartialEq, TryFromU32)]
|
||||
#[repr(C)]
|
||||
pub enum Linkage {
|
||||
ExternalLinkage = 0,
|
||||
AvailableExternallyLinkage = 1,
|
||||
LinkOnceAnyLinkage = 2,
|
||||
LinkOnceODRLinkage = 3,
|
||||
WeakAnyLinkage = 4,
|
||||
WeakODRLinkage = 5,
|
||||
AppendingLinkage = 6,
|
||||
InternalLinkage = 7,
|
||||
PrivateLinkage = 8,
|
||||
ExternalWeakLinkage = 9,
|
||||
CommonLinkage = 10,
|
||||
#[deprecated = "marked obsolete by LLVM"]
|
||||
LinkOnceODRAutoHideLinkage = 4,
|
||||
WeakAnyLinkage = 5,
|
||||
WeakODRLinkage = 6,
|
||||
AppendingLinkage = 7,
|
||||
InternalLinkage = 8,
|
||||
PrivateLinkage = 9,
|
||||
#[deprecated = "marked obsolete by LLVM"]
|
||||
DLLImportLinkage = 10,
|
||||
#[deprecated = "marked obsolete by LLVM"]
|
||||
DLLExportLinkage = 11,
|
||||
ExternalWeakLinkage = 12,
|
||||
#[deprecated = "marked obsolete by LLVM"]
|
||||
GhostLinkage = 13,
|
||||
CommonLinkage = 14,
|
||||
LinkerPrivateLinkage = 15,
|
||||
LinkerPrivateWeakLinkage = 16,
|
||||
}
|
||||
|
||||
// LLVMRustVisibility
|
||||
/// Must match the layout of `LLVMVisibility`.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq, TryFromU32)]
|
||||
pub enum Visibility {
|
||||
Default = 0,
|
||||
Hidden = 1,
|
||||
|
@ -945,7 +981,11 @@ unsafe extern "C" {
|
|||
|
||||
// Operations on global variables, functions, and aliases (globals)
|
||||
pub fn LLVMIsDeclaration(Global: &Value) -> Bool;
|
||||
pub fn LLVMGetLinkage(Global: &Value) -> RawEnum<Linkage>;
|
||||
pub fn LLVMSetLinkage(Global: &Value, RustLinkage: Linkage);
|
||||
pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
|
||||
pub fn LLVMGetVisibility(Global: &Value) -> RawEnum<Visibility>;
|
||||
pub fn LLVMSetVisibility(Global: &Value, Viz: Visibility);
|
||||
pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
|
||||
pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
|
||||
pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
|
||||
|
@ -1521,10 +1561,6 @@ unsafe extern "C" {
|
|||
) -> bool;
|
||||
|
||||
// Operations on global variables, functions, and aliases (globals)
|
||||
pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage;
|
||||
pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage);
|
||||
pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility;
|
||||
pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility);
|
||||
pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
|
||||
|
||||
// Operations on global variables
|
||||
|
|
|
@ -232,15 +232,23 @@ pub fn set_global_constant(llglobal: &Value, is_constant: bool) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_linkage(llglobal: &Value) -> Linkage {
|
||||
unsafe { LLVMGetLinkage(llglobal) }.to_rust()
|
||||
}
|
||||
|
||||
pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
|
||||
unsafe {
|
||||
LLVMRustSetLinkage(llglobal, linkage);
|
||||
LLVMSetLinkage(llglobal, linkage);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_visibility(llglobal: &Value) -> Visibility {
|
||||
unsafe { LLVMGetVisibility(llglobal) }.to_rust()
|
||||
}
|
||||
|
||||
pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
|
||||
unsafe {
|
||||
LLVMRustSetVisibility(llglobal, visibility);
|
||||
LLVMSetVisibility(llglobal, visibility);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
.emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name })
|
||||
});
|
||||
|
||||
llvm::set_linkage(g, base::linkage_to_llvm(linkage));
|
||||
llvm::set_visibility(g, base::visibility_to_llvm(visibility));
|
||||
unsafe {
|
||||
llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
|
||||
llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
|
||||
if self.should_assume_dso_local(g, false) {
|
||||
llvm::LLVMRustSetDSOLocal(g, true);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance));
|
||||
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
|
||||
llvm::set_linkage(lldecl, base::linkage_to_llvm(linkage));
|
||||
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||
base::set_link_section(lldecl, attrs);
|
||||
if (linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR)
|
||||
|
@ -78,21 +78,15 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
&& linkage != Linkage::Private
|
||||
&& self.tcx.is_compiler_builtins(LOCAL_CRATE)
|
||||
{
|
||||
unsafe {
|
||||
llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
|
||||
}
|
||||
llvm::set_visibility(lldecl, llvm::Visibility::Hidden);
|
||||
} else {
|
||||
unsafe {
|
||||
llvm::LLVMRustSetVisibility(lldecl, base::visibility_to_llvm(visibility));
|
||||
}
|
||||
llvm::set_visibility(lldecl, base::visibility_to_llvm(visibility));
|
||||
}
|
||||
|
||||
debug!("predefine_fn: instance = {:?}", instance);
|
||||
|
||||
unsafe {
|
||||
if self.should_assume_dso_local(lldecl, false) {
|
||||
llvm::LLVMRustSetDSOLocal(lldecl, true);
|
||||
}
|
||||
if self.should_assume_dso_local(lldecl, false) {
|
||||
unsafe { llvm::LLVMRustSetDSOLocal(lldecl, true) };
|
||||
}
|
||||
|
||||
self.instances.borrow_mut().insert(instance, lldecl);
|
||||
|
@ -102,13 +96,13 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
impl CodegenCx<'_, '_> {
|
||||
/// Whether a definition or declaration can be assumed to be local to a group of
|
||||
/// libraries that form a single DSO or executable.
|
||||
pub(crate) unsafe fn should_assume_dso_local(
|
||||
pub(crate) fn should_assume_dso_local(
|
||||
&self,
|
||||
llval: &llvm::Value,
|
||||
is_declaration: bool,
|
||||
) -> bool {
|
||||
let linkage = unsafe { llvm::LLVMRustGetLinkage(llval) };
|
||||
let visibility = unsafe { llvm::LLVMRustGetVisibility(llval) };
|
||||
let linkage = llvm::get_linkage(llval);
|
||||
let visibility = llvm::get_visibility(llval);
|
||||
|
||||
if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) {
|
||||
return true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue