Skip to content

Commit e17c48b

Browse files
committed
trans: don't declare symbols that were already imported.
1 parent 600dc35 commit e17c48b

File tree

3 files changed

+51
-21
lines changed

3 files changed

+51
-21
lines changed

src/librustc_trans/callee.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -541,14 +541,6 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
541541
}
542542
};
543543

544-
let llfn = declare::declare_fn(ccx, &sym, ty);
545-
attributes::from_fn_attrs(ccx, attrs, llfn);
546-
if let Some(id) = local_item {
547-
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
548-
attributes::unwind(llfn, true);
549-
ccx.item_symbols().borrow_mut().insert(id, sym);
550-
}
551-
552544
// This is subtle and surprising, but sometimes we have to bitcast
553545
// the resulting fn pointer. The reason has to do with external
554546
// 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>,
572564
// This can occur on either a crate-local or crate-external
573565
// reference. It also occurs when testing libcore and in some
574566
// other weird situations. Annoying.
567+
575568
let llptrty = type_of::type_of(ccx, fn_ptr_ty);
576-
let llfn = if common::val_ty(llfn) != llptrty {
577-
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
578-
consts::ptrcast(llfn, llptrty)
569+
let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
570+
if common::val_ty(llfn) != llptrty {
571+
if local_item.is_some() {
572+
bug!("symbol `{}` previously declared as {:?}, now wanted as {:?}",
573+
sym, Value(llfn), llptrty);
574+
}
575+
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
576+
consts::ptrcast(llfn, llptrty)
577+
} else {
578+
debug!("get_fn: not casting pointer!");
579+
llfn
580+
}
579581
} else {
582+
let llfn = declare::declare_fn(ccx, &sym, ty);
583+
assert_eq!(common::val_ty(llfn), llptrty);
580584
debug!("get_fn: not casting pointer!");
585+
586+
attributes::from_fn_attrs(ccx, attrs, llfn);
587+
if let Some(id) = local_item {
588+
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
589+
attributes::unwind(llfn, true);
590+
ccx.item_symbols().borrow_mut().insert(id, sym);
591+
}
592+
581593
llfn
582594
};
583595

src/librustc_trans/declare.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use abi::{Abi, FnType};
2626
use attributes;
2727
use context::CrateContext;
2828
use type_::Type;
29+
use value::Value;
2930

3031
use std::ffi::CString;
3132

@@ -146,27 +147,33 @@ pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
146147
}
147148

148149

149-
/// Get defined or externally defined (AvailableExternally linkage) value by
150-
/// name.
151-
pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
152-
debug!("get_defined_value(name={:?})", name);
150+
/// Get declared value by name.
151+
pub fn get_declared_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
152+
debug!("get_declared_value(name={:?})", name);
153153
let namebuf = CString::new(name).unwrap_or_else(|_|{
154154
bug!("name {:?} contains an interior null byte", name)
155155
});
156156
let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
157157
if val.is_null() {
158-
debug!("get_defined_value: {:?} value is null", name);
158+
debug!("get_declared_value: {:?} value is null", name);
159159
None
160160
} else {
161+
debug!("get_declared_value: {:?} => {:?}", name, Value(val));
162+
Some(val)
163+
}
164+
}
165+
166+
/// Get defined or externally defined (AvailableExternally linkage) value by
167+
/// name.
168+
pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
169+
get_declared_value(ccx, name).and_then(|val|{
161170
let declaration = unsafe {
162171
llvm::LLVMIsDeclaration(val) != 0
163172
};
164-
debug!("get_defined_value: found {:?} value (declaration: {})",
165-
name, declaration);
166173
if !declaration {
167174
Some(val)
168175
} else {
169176
None
170177
}
171-
}
178+
})
172179
}

src/test/run-pass/foreign-dupe.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,20 @@ mod rustrt2 {
3131
}
3232
}
3333

34+
mod rustrt3 {
35+
// Different type, but same ABI (on all supported platforms).
36+
// Ensures that we don't ICE or trigger LLVM asserts when
37+
// importing the same symbol under different types.
38+
// See https://github.com/rust-lang/rust/issues/32740.
39+
extern {
40+
pub fn rust_get_test_int() -> *const u8;
41+
}
42+
}
43+
3444
pub fn main() {
3545
unsafe {
36-
rustrt1::rust_get_test_int();
37-
rustrt2::rust_get_test_int();
46+
let x = rustrt1::rust_get_test_int();
47+
assert_eq!(x, rustrt2::rust_get_test_int());
48+
assert_eq!(x as *const _, rustrt3::rust_get_test_int());
3849
}
3950
}

0 commit comments

Comments
 (0)