Skip to content

Commit d78718a

Browse files
committed
auto merge of #14191 : luqmana/rust/eu, r=alexcrichton
We were correctly determining the attributes needed for the parameters for extern fns, but when that extern fn was from another crate we never bothered to pass that information along to LLVM. (i.e never called `foreign::add_argument_attributes`). I've just changed both local and non-local (crate) extern fn's to be dealt with together (through `foreign::register_foreign_item_fn`) so we don't run into something like again. Fixes #14177.
2 parents d990681 + 589f447 commit d78718a

File tree

6 files changed

+109
-25
lines changed

6 files changed

+109
-25
lines changed

src/librustc/middle/trans/base.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -860,15 +860,8 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
860860
did)
861861
}
862862
Some(..) | None => {
863-
let c = foreign::llvm_calling_convention(ccx, fn_ty.abi);
864-
let cconv = c.unwrap_or(lib::llvm::CCallConv);
865-
let llty = type_of_fn_from_ty(ccx, t);
866-
get_extern_fn(&mut *ccx.externs.borrow_mut(),
867-
ccx.llmod,
868-
name.as_slice(),
869-
cconv,
870-
llty,
871-
fn_ty.sig.output)
863+
foreign::register_foreign_item_fn(ccx, fn_ty.abi, t,
864+
name.as_slice(), None)
872865
}
873866
}
874867
}
@@ -1976,7 +1969,11 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
19761969
match ni.node {
19771970
ast::ForeignItemFn(..) => {
19781971
let abi = ccx.tcx.map.get_foreign_abi(id);
1979-
foreign::register_foreign_item_fn(ccx, abi, ni)
1972+
let ty = ty::node_id_to_type(ccx.tcx(), ni.id);
1973+
let name = foreign::link_name(ni);
1974+
foreign::register_foreign_item_fn(ccx, abi, ty,
1975+
name.get().as_slice(),
1976+
Some(ni.span))
19801977
}
19811978
ast::ForeignItemStatic(..) => {
19821979
foreign::register_static(ccx, ni)

src/librustc/middle/trans/foreign.rs

+30-15
Original file line numberDiff line numberDiff line change
@@ -180,33 +180,42 @@ pub fn register_static(ccx: &CrateContext,
180180
}
181181
}
182182

183-
pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi,
184-
foreign_item: &ast::ForeignItem) -> ValueRef {
183+
pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t,
184+
name: &str, span: Option<Span>) -> ValueRef {
185185
/*!
186186
* Registers a foreign function found in a library.
187187
* Just adds a LLVM global.
188188
*/
189189

190190
debug!("register_foreign_item_fn(abi={}, \
191-
path={}, \
192-
foreign_item.id={})",
191+
ty={}, \
192+
name={})",
193193
abi.repr(ccx.tcx()),
194-
ccx.tcx.map.path_to_str(foreign_item.id),
195-
foreign_item.id);
194+
fty.repr(ccx.tcx()),
195+
name);
196196

197197
let cc = match llvm_calling_convention(ccx, abi) {
198198
Some(cc) => cc,
199199
None => {
200-
ccx.sess().span_fatal(foreign_item.span,
201-
format!("ABI `{}` has no suitable calling convention \
202-
for target architecture",
203-
abi.user_string(ccx.tcx())));
200+
match span {
201+
Some(s) => {
202+
ccx.sess().span_fatal(s,
203+
format!("ABI `{}` has no suitable calling convention \
204+
for target architecture",
205+
abi.user_string(ccx.tcx())))
206+
}
207+
None => {
208+
ccx.sess().fatal(
209+
format!("ABI `{}` has no suitable calling convention \
210+
for target architecture",
211+
abi.user_string(ccx.tcx())))
212+
}
213+
}
204214
}
205215
};
206216

207217
// Register the function as a C extern fn
208-
let lname = link_name(foreign_item);
209-
let tys = foreign_types_for_id(ccx, foreign_item.id);
218+
let tys = foreign_types_for_fn_ty(ccx, fty);
210219

211220
// Make sure the calling convention is right for variadic functions
212221
// (should've been caught if not in typeck)
@@ -219,7 +228,7 @@ pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi,
219228

220229
let llfn = base::get_extern_fn(&mut *ccx.externs.borrow_mut(),
221230
ccx.llmod,
222-
lname.get(),
231+
name,
223232
cc,
224233
llfn_ty,
225234
tys.fn_sig.output);
@@ -433,17 +442,23 @@ pub fn trans_native_call<'a>(
433442
pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
434443
let _icx = push_ctxt("foreign::trans_foreign_mod");
435444
for &foreign_item in foreign_mod.items.iter() {
445+
let lname = link_name(foreign_item);
446+
436447
match foreign_item.node {
437448
ast::ForeignItemFn(..) => {
438449
match foreign_mod.abi {
439450
Rust | RustIntrinsic => {}
440-
abi => { register_foreign_item_fn(ccx, abi, foreign_item); }
451+
abi => {
452+
let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
453+
register_foreign_item_fn(ccx, abi, ty,
454+
lname.get().as_slice(),
455+
Some(foreign_item.span));
456+
}
441457
}
442458
}
443459
_ => {}
444460
}
445461

446-
let lname = link_name(foreign_item);
447462
ccx.item_symbols.borrow_mut().insert(foreign_item.id,
448463
lname.get().to_strbuf());
449464
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-include ../tools.mk
2+
3+
all:
4+
$(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
5+
$(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
6+
$(RUSTC) testcrate.rs -L $(TMPDIR)
7+
$(RUSTC) test.rs -L $(TMPDIR)
8+
$(call RUN,test) || exit 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <stdio.h>
2+
#include <stdint.h>
3+
4+
typedef union TestUnion {
5+
uint64_t bits;
6+
} TestUnion;
7+
8+
uint64_t give_back(TestUnion tu) {
9+
return tu.bits;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate testcrate;
12+
13+
use std::mem;
14+
15+
#[link(name = "test", kind = "static")]
16+
extern {
17+
fn give_back(tu: testcrate::TestUnion) -> u64;
18+
}
19+
20+
fn main() {
21+
let magic: u64 = 0xDEADBEEF;
22+
23+
// Let's test calling it cross crate
24+
let back = unsafe {
25+
testcrate::give_back(mem::transmute(magic))
26+
};
27+
assert_eq!(magic, back);
28+
29+
// And just within this crate
30+
let back = unsafe {
31+
give_back(mem::transmute(magic))
32+
};
33+
assert_eq!(magic, back);
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "lib"]
12+
13+
pub struct TestUnion {
14+
val: u64
15+
}
16+
17+
#[link(name = "test", kind = "static")]
18+
extern {
19+
pub fn give_back(tu: TestUnion) -> u64;
20+
}

0 commit comments

Comments
 (0)