librustc: Make sure to add argument attributes to extern fns from non-local crates.
This commit is contained in:
parent
e4414739a5
commit
589f447299
@ -860,15 +860,8 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
|
||||
did)
|
||||
}
|
||||
Some(..) | None => {
|
||||
let c = foreign::llvm_calling_convention(ccx, fn_ty.abi);
|
||||
let cconv = c.unwrap_or(lib::llvm::CCallConv);
|
||||
let llty = type_of_fn_from_ty(ccx, t);
|
||||
get_extern_fn(&mut *ccx.externs.borrow_mut(),
|
||||
ccx.llmod,
|
||||
name.as_slice(),
|
||||
cconv,
|
||||
llty,
|
||||
fn_ty.sig.output)
|
||||
foreign::register_foreign_item_fn(ccx, fn_ty.abi, t,
|
||||
name.as_slice(), None)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1976,7 +1969,11 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
match ni.node {
|
||||
ast::ForeignItemFn(..) => {
|
||||
let abi = ccx.tcx.map.get_foreign_abi(id);
|
||||
foreign::register_foreign_item_fn(ccx, abi, ni)
|
||||
let ty = ty::node_id_to_type(ccx.tcx(), ni.id);
|
||||
let name = foreign::link_name(ni);
|
||||
foreign::register_foreign_item_fn(ccx, abi, ty,
|
||||
name.get().as_slice(),
|
||||
Some(ni.span))
|
||||
}
|
||||
ast::ForeignItemStatic(..) => {
|
||||
foreign::register_static(ccx, ni)
|
||||
|
@ -180,33 +180,42 @@ pub fn register_static(ccx: &CrateContext,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi,
|
||||
foreign_item: &ast::ForeignItem) -> ValueRef {
|
||||
pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t,
|
||||
name: &str, span: Option<Span>) -> ValueRef {
|
||||
/*!
|
||||
* Registers a foreign function found in a library.
|
||||
* Just adds a LLVM global.
|
||||
*/
|
||||
|
||||
debug!("register_foreign_item_fn(abi={}, \
|
||||
path={}, \
|
||||
foreign_item.id={})",
|
||||
ty={}, \
|
||||
name={})",
|
||||
abi.repr(ccx.tcx()),
|
||||
ccx.tcx.map.path_to_str(foreign_item.id),
|
||||
foreign_item.id);
|
||||
fty.repr(ccx.tcx()),
|
||||
name);
|
||||
|
||||
let cc = match llvm_calling_convention(ccx, abi) {
|
||||
Some(cc) => cc,
|
||||
None => {
|
||||
ccx.sess().span_fatal(foreign_item.span,
|
||||
format!("ABI `{}` has no suitable calling convention \
|
||||
for target architecture",
|
||||
abi.user_string(ccx.tcx())));
|
||||
match span {
|
||||
Some(s) => {
|
||||
ccx.sess().span_fatal(s,
|
||||
format!("ABI `{}` has no suitable calling convention \
|
||||
for target architecture",
|
||||
abi.user_string(ccx.tcx())))
|
||||
}
|
||||
None => {
|
||||
ccx.sess().fatal(
|
||||
format!("ABI `{}` has no suitable calling convention \
|
||||
for target architecture",
|
||||
abi.user_string(ccx.tcx())))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Register the function as a C extern fn
|
||||
let lname = link_name(foreign_item);
|
||||
let tys = foreign_types_for_id(ccx, foreign_item.id);
|
||||
let tys = foreign_types_for_fn_ty(ccx, fty);
|
||||
|
||||
// Make sure the calling convention is right for variadic functions
|
||||
// (should've been caught if not in typeck)
|
||||
@ -219,7 +228,7 @@ pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi,
|
||||
|
||||
let llfn = base::get_extern_fn(&mut *ccx.externs.borrow_mut(),
|
||||
ccx.llmod,
|
||||
lname.get(),
|
||||
name,
|
||||
cc,
|
||||
llfn_ty,
|
||||
tys.fn_sig.output);
|
||||
@ -433,17 +442,23 @@ pub fn trans_native_call<'a>(
|
||||
pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
|
||||
let _icx = push_ctxt("foreign::trans_foreign_mod");
|
||||
for &foreign_item in foreign_mod.items.iter() {
|
||||
let lname = link_name(foreign_item);
|
||||
|
||||
match foreign_item.node {
|
||||
ast::ForeignItemFn(..) => {
|
||||
match foreign_mod.abi {
|
||||
Rust | RustIntrinsic => {}
|
||||
abi => { register_foreign_item_fn(ccx, abi, foreign_item); }
|
||||
abi => {
|
||||
let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
|
||||
register_foreign_item_fn(ccx, abi, ty,
|
||||
lname.get().as_slice(),
|
||||
Some(foreign_item.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let lname = link_name(foreign_item);
|
||||
ccx.item_symbols.borrow_mut().insert(foreign_item.id,
|
||||
lname.get().to_strbuf());
|
||||
}
|
||||
|
8
src/test/run-make/extern-fn-with-union/Makefile
Normal file
8
src/test/run-make/extern-fn-with-union/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
|
||||
$(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
|
||||
$(RUSTC) testcrate.rs -L $(TMPDIR)
|
||||
$(RUSTC) test.rs -L $(TMPDIR)
|
||||
$(call RUN,test) || exit 1
|
10
src/test/run-make/extern-fn-with-union/test.c
Normal file
10
src/test/run-make/extern-fn-with-union/test.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union TestUnion {
|
||||
uint64_t bits;
|
||||
} TestUnion;
|
||||
|
||||
uint64_t give_back(TestUnion tu) {
|
||||
return tu.bits;
|
||||
}
|
34
src/test/run-make/extern-fn-with-union/test.rs
Normal file
34
src/test/run-make/extern-fn-with-union/test.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate testcrate;
|
||||
|
||||
use std::mem;
|
||||
|
||||
#[link(name = "test", kind = "static")]
|
||||
extern {
|
||||
fn give_back(tu: testcrate::TestUnion) -> u64;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let magic: u64 = 0xDEADBEEF;
|
||||
|
||||
// Let's test calling it cross crate
|
||||
let back = unsafe {
|
||||
testcrate::give_back(mem::transmute(magic))
|
||||
};
|
||||
assert_eq!(magic, back);
|
||||
|
||||
// And just within this crate
|
||||
let back = unsafe {
|
||||
give_back(mem::transmute(magic))
|
||||
};
|
||||
assert_eq!(magic, back);
|
||||
}
|
20
src/test/run-make/extern-fn-with-union/testcrate.rs
Normal file
20
src/test/run-make/extern-fn-with-union/testcrate.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub struct TestUnion {
|
||||
val: u64
|
||||
}
|
||||
|
||||
#[link(name = "test", kind = "static")]
|
||||
extern {
|
||||
pub fn give_back(tu: TestUnion) -> u64;
|
||||
}
|
Loading…
Reference in New Issue
Block a user