trans: don't declare symbols that were already imported.
This commit is contained in:
parent
600dc3552f
commit
e17c48bb24
|
@ -541,14 +541,6 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
};
|
||||
|
||||
let llfn = declare::declare_fn(ccx, &sym, ty);
|
||||
attributes::from_fn_attrs(ccx, attrs, llfn);
|
||||
if let Some(id) = local_item {
|
||||
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
|
||||
attributes::unwind(llfn, true);
|
||||
ccx.item_symbols().borrow_mut().insert(id, sym);
|
||||
}
|
||||
|
||||
// This is subtle and surprising, but sometimes we have to bitcast
|
||||
// the resulting fn pointer. The reason has to do with external
|
||||
// functions. If you have two crates that both bind the same C
|
||||
|
@ -572,12 +564,32 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
// This can occur on either a crate-local or crate-external
|
||||
// reference. It also occurs when testing libcore and in some
|
||||
// other weird situations. Annoying.
|
||||
|
||||
let llptrty = type_of::type_of(ccx, fn_ptr_ty);
|
||||
let llfn = if common::val_ty(llfn) != llptrty {
|
||||
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
|
||||
consts::ptrcast(llfn, llptrty)
|
||||
let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
|
||||
if common::val_ty(llfn) != llptrty {
|
||||
if local_item.is_some() {
|
||||
bug!("symbol `{}` previously declared as {:?}, now wanted as {:?}",
|
||||
sym, Value(llfn), llptrty);
|
||||
}
|
||||
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
|
||||
consts::ptrcast(llfn, llptrty)
|
||||
} else {
|
||||
debug!("get_fn: not casting pointer!");
|
||||
llfn
|
||||
}
|
||||
} else {
|
||||
let llfn = declare::declare_fn(ccx, &sym, ty);
|
||||
assert_eq!(common::val_ty(llfn), llptrty);
|
||||
debug!("get_fn: not casting pointer!");
|
||||
|
||||
attributes::from_fn_attrs(ccx, attrs, llfn);
|
||||
if let Some(id) = local_item {
|
||||
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
|
||||
attributes::unwind(llfn, true);
|
||||
ccx.item_symbols().borrow_mut().insert(id, sym);
|
||||
}
|
||||
|
||||
llfn
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ use abi::{Abi, FnType};
|
|||
use attributes;
|
||||
use context::CrateContext;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
|
||||
use std::ffi::CString;
|
||||
|
||||
|
@ -146,27 +147,33 @@ pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
|
||||
|
||||
/// Get defined or externally defined (AvailableExternally linkage) value by
|
||||
/// name.
|
||||
pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
|
||||
debug!("get_defined_value(name={:?})", name);
|
||||
/// Get declared value by name.
|
||||
pub fn get_declared_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
|
||||
debug!("get_declared_value(name={:?})", name);
|
||||
let namebuf = CString::new(name).unwrap_or_else(|_|{
|
||||
bug!("name {:?} contains an interior null byte", name)
|
||||
});
|
||||
let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
|
||||
if val.is_null() {
|
||||
debug!("get_defined_value: {:?} value is null", name);
|
||||
debug!("get_declared_value: {:?} value is null", name);
|
||||
None
|
||||
} else {
|
||||
debug!("get_declared_value: {:?} => {:?}", name, Value(val));
|
||||
Some(val)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get defined or externally defined (AvailableExternally linkage) value by
|
||||
/// name.
|
||||
pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
|
||||
get_declared_value(ccx, name).and_then(|val|{
|
||||
let declaration = unsafe {
|
||||
llvm::LLVMIsDeclaration(val) != 0
|
||||
};
|
||||
debug!("get_defined_value: found {:?} value (declaration: {})",
|
||||
name, declaration);
|
||||
if !declaration {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -31,9 +31,20 @@ mod rustrt2 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
rustrt1::rust_get_test_int();
|
||||
rustrt2::rust_get_test_int();
|
||||
mod rustrt3 {
|
||||
// Different type, but same ABI (on all supported platforms).
|
||||
// Ensures that we don't ICE or trigger LLVM asserts when
|
||||
// importing the same symbol under different types.
|
||||
// See https://github.com/rust-lang/rust/issues/32740.
|
||||
extern {
|
||||
pub fn rust_get_test_int() -> *const u8;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
let x = rustrt1::rust_get_test_int();
|
||||
assert_eq!(x, rustrt2::rust_get_test_int());
|
||||
assert_eq!(x as *const _, rustrt3::rust_get_test_int());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue