Skip to content

Commit b990190

Browse files
committed
[MIR] Calling extern functions.
1 parent 5d4efcb commit b990190

File tree

2 files changed

+50
-16
lines changed

2 files changed

+50
-16
lines changed

Diff for: src/librustc_trans/trans/mir/block.rs

+35-16
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ use trans::base;
1717
use trans::build;
1818
use trans::common::{self, Block};
1919
use trans::debuginfo::DebugLoc;
20+
use trans::foreign;
2021
use trans::type_of;
2122

23+
use syntax::abi as synabi;
24+
2225
use super::MirContext;
2326
use super::operand::OperandValue::{FatPtr, Immediate, Ref};
2427

@@ -112,19 +115,24 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
112115
// Create the callee. This will always be a fn
113116
// ptr and hence a kind of scalar.
114117
let callee = self.trans_operand(bcx, &data.func);
115-
let ret_ty = if let ty::TyBareFn(_, ref f) = callee.ty.sty {
118+
let (abi, ret_ty) = if let ty::TyBareFn(_, ref f) = callee.ty.sty {
116119
let sig = bcx.tcx().erase_late_bound_regions(&f.sig);
117120
let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
118-
sig.output
121+
(f.abi, sig.output)
119122
} else {
120123
panic!("trans_block: expected TyBareFn as callee");
121124
};
122125

126+
// Have we got a 'Rust' function?
127+
let is_rust_fn = abi == synabi::Rust || abi == synabi::RustCall;
128+
123129
// The arguments we'll be passing
124-
let mut llargs = vec![];
130+
let mut llargs = Vec::with_capacity(data.args.len() + 1);
131+
// and their Rust types (formal args only so not outptr)
132+
let mut arg_tys = Vec::with_capacity(data.args.len());
125133

126134
// Does the fn use an outptr? If so, that's the first arg.
127-
if let ty::FnConverging(ret_ty) = ret_ty {
135+
if let (true, ty::FnConverging(ret_ty)) = (is_rust_fn, ret_ty) {
128136
if type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
129137
llargs.push(call_dest.llval);
130138
}
@@ -133,6 +141,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
133141
// Process the rest of the args.
134142
for arg in &data.args {
135143
let arg_op = self.trans_operand(bcx, arg);
144+
arg_tys.push(arg_op.ty);
136145
match arg_op.val {
137146
Ref(llval) | Immediate(llval) => llargs.push(llval),
138147
FatPtr(base, extra) => {
@@ -148,19 +157,29 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
148157
//self.make_landing_pad(panic_bb);
149158

150159
// Do the actual call.
151-
let (llret, b) = base::invoke(bcx,
152-
callee.immediate(),
153-
&llargs[..],
154-
callee.ty,
155-
DebugLoc::None);
156-
bcx = b;
157-
158-
// Copy the return value into the destination.
159-
if let ty::FnConverging(ret_ty) = ret_ty {
160-
if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
161-
!common::type_is_zero_size(bcx.ccx(), ret_ty) {
162-
base::store_ty(bcx, llret, call_dest.llval, ret_ty);
160+
if is_rust_fn {
161+
let (llret, b) = base::invoke(bcx,
162+
callee.immediate(),
163+
&llargs,
164+
callee.ty,
165+
DebugLoc::None);
166+
bcx = b;
167+
168+
// Copy the return value into the destination.
169+
if let ty::FnConverging(ret_ty) = ret_ty {
170+
if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
171+
!common::type_is_zero_size(bcx.ccx(), ret_ty) {
172+
base::store_ty(bcx, llret, call_dest.llval, ret_ty);
173+
}
163174
}
175+
} else {
176+
bcx = foreign::trans_native_call(bcx,
177+
callee.ty,
178+
callee.immediate(),
179+
call_dest.llval,
180+
&llargs,
181+
arg_tys,
182+
DebugLoc::None);
164183
}
165184

166185
build::Br(bcx, self.llblock(targets.0), DebugLoc::None)

Diff for: src/test/run-pass/mir_trans_calls.rs

+15
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ fn test8() -> isize {
8888
Two::two()
8989
}
9090

91+
#[link(name = "c")]
92+
extern {
93+
fn printf(format: *const u8, ...) -> i32;
94+
}
95+
96+
#[rustc_mir]
97+
fn native_test() -> i32 {
98+
unsafe {
99+
let format = b"Hello World! There are %d days in a year. Mmmm %.5f\n\0";
100+
printf(format.as_ptr(), 365, 3.14159)
101+
}
102+
}
103+
91104
fn main() {
92105
assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..]));
93106
assert_eq!(test2(98), 98);
@@ -97,4 +110,6 @@ fn main() {
97110
assert_eq!(test6(&Foo, 12367), 12367);
98111
assert_eq!(test7(), 1);
99112
assert_eq!(test8(), 2);
113+
114+
assert_eq!(native_test(), 56);
100115
}

0 commit comments

Comments
 (0)