From c78b1639b445e31274858d0801d30a2f9cd3d7e6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 24 Oct 2011 17:03:18 -0700 Subject: [PATCH] fix c-stack-cdecl when used w/ i64 --- src/comp/back/upcall.rs | 10 +++++++--- src/comp/middle/trans.rs | 10 ++++++++-- src/rt/arch/i386/ccall.S | 4 ++++ src/rt/rustrt.def.in | 1 + src/test/run-pass/c-stack-returning-int64.rs | 20 ++++++++++++++++++++ 5 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 src/test/run-pass/c-stack-returning-int64.rs diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs index 04bdebb04a1..0eaef300d80 100644 --- a/src/comp/back/upcall.rs +++ b/src/comp/back/upcall.rs @@ -3,7 +3,7 @@ import std::str; import middle::trans; import trans::decl_cdecl_fn; import middle::trans_common::{T_f32, T_f64, T_fn, T_bool, T_i1, T_i8, T_i32, - T_int, T_vec, T_nil, T_opaque_chan_ptr, + T_i64, T_int, T_vec, T_nil, T_opaque_chan_ptr, T_opaque_vec, T_opaque_port_ptr, T_ptr, T_size_t, T_void, T_float}; import lib::llvm::type_names; @@ -28,6 +28,7 @@ type upcalls = dynastack_free: ValueRef, alloc_c_stack: ValueRef, call_c_stack: ValueRef, + call_c_stack_i64: ValueRef, call_c_stack_float: ValueRef, rust_personality: ValueRef}; @@ -76,8 +77,11 @@ fn declare_upcalls(_tn: type_names, tydesc_type: TypeRef, dynastack_free: dv("dynastack_free", [T_ptr(T_i8())]), alloc_c_stack: d("alloc_c_stack", [T_size_t()], T_ptr(T_i8())), call_c_stack: d("call_c_stack", - [T_ptr(T_fn([], T_int())), T_ptr(T_i8())], - T_int()), + [T_ptr(T_fn([], T_int())), T_ptr(T_i8())], + T_int()), + call_c_stack_i64: d("call_c_stack_i64", + [T_ptr(T_fn([], T_int())), T_ptr(T_i8())], + T_i64()), call_c_stack_float: d("call_c_stack_float", [T_ptr(T_fn([], T_int())), T_ptr(T_i8())], T_float()), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 11d7d62436a..7fe35776529 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3878,13 +3878,19 @@ fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr, ccx.upcalls.call_c_stack_float } + 7 { + // LLVMIntegerTypeKind + let width = lib::llvm::llvm::LLVMGetIntTypeWidth(llretty); + if width == 64u { ccx.upcalls.call_c_stack_i64 } + else { ccx.upcalls.call_c_stack } // on 64-bit target, no diff + } + _ { ccx.upcalls.call_c_stack } }; // Call and cast the return type. // TODO: Invoke instead. - let llrawretval = Call(bcx, upcall_fn, - [llfn, llrawargbundle]); + let llrawretval = Call(bcx, upcall_fn, [llfn, llrawargbundle]); let llretval; if lib::llvm::llvm::LLVMGetTypeKind(llretty) as int == 11 { // pointer llretval = IntToPtr(bcx, llrawretval, llretty); diff --git a/src/rt/arch/i386/ccall.S b/src/rt/arch/i386/ccall.S index 378ea5e0b67..d901666c6a4 100644 --- a/src/rt/arch/i386/ccall.S +++ b/src/rt/arch/i386/ccall.S @@ -6,13 +6,17 @@ // slower. #if defined(__APPLE__) || defined(_WIN32) .globl _upcall_call_c_stack +.globl _upcall_call_c_stack_i64 .globl _upcall_call_c_stack_float _upcall_call_c_stack: +_upcall_call_c_stack_i64: _upcall_call_c_stack_float: #else .globl upcall_call_c_stack +.globl upcall_call_c_stack_i64 .globl upcall_call_c_stack_float upcall_call_c_stack: +upcall_call_c_stack_i64: upcall_call_c_stack_float: #endif pushl %ebp diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 6b70e283957..8293a23d126 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -65,6 +65,7 @@ task_join unsupervise upcall_alloc_c_stack upcall_call_c_stack +upcall_call_c_stack_i64 upcall_call_c_stack_float upcall_cmp_type upcall_dynastack_alloc diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs new file mode 100644 index 00000000000..33e8b73a495 --- /dev/null +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -0,0 +1,20 @@ +use std; +import std::str; + +native "c-stack-cdecl" mod libc = "" { + fn atol(x: str::sbuf) -> int; + fn atoll(x: str::sbuf) -> i64; +} + +fn atol(s: str) -> int { + ret str::as_buf(s, { |x| libc::atol(x) }); +} + +fn atoll(s: str) -> i64 { + ret str::as_buf(s, { |x| libc::atoll(x) }); +} + +fn main() { + assert atol("1024") * 10 == atol("10240"); + assert (atoll("11111111111111111") * 10i64) == atoll("111111111111111110"); +}