diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs index 29ea36cd88b03..4b9ff4504ddac 100644 --- a/src/libcore/rt/uv/net.rs +++ b/src/libcore/rt/uv/net.rs @@ -356,7 +356,6 @@ impl NativeHandle<*uvll::uv_write_t> for WriteRequest { #[test] -#[ignore(reason = "ffi struct issues")] fn connect_close() { do run_in_bare_thread() { let mut loop_ = Loop::new(); @@ -409,7 +408,6 @@ fn connect_read() { } #[test] -#[ignore(reason = "ffi struct issues")] fn listen() { do run_in_bare_thread() { static MAX: int = 10; diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index b6d3fce7e7546..06f7261040c5d 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -125,27 +125,25 @@ pub enum RealPredicate { RealPredicateTrue = 15, } -// enum for the LLVM TypeKind type - must stay in sync with the def of +// The LLVM TypeKind type - must stay in sync with the def of // LLVMTypeKind in llvm/include/llvm-c/Core.h -#[deriving(Eq)] -pub enum TypeKind { - Void = 0, - Half = 1, - Float = 2, - Double = 3, - X86_FP80 = 4, - FP128 = 5, - PPC_FP128 = 6, - Label = 7, - Integer = 8, - Function = 9, - Struct = 10, - Array = 11, - Pointer = 12, - Vector = 13, - Metadata = 14, - X86_MMX = 15 -} +pub type TypeKind = u32; +pub static Void: TypeKind = 0; +pub static Half: TypeKind = 1; +pub static Float: TypeKind = 2; +pub static Double: TypeKind = 3; +pub static X86_FP80: TypeKind = 4; +pub static FP128: TypeKind = 5; +pub static PPC_FP128: TypeKind = 6; +pub static Label: TypeKind = 7; +pub static Integer: TypeKind = 8; +pub static Function: TypeKind = 9; +pub static Struct: TypeKind = 10; +pub static Array: TypeKind = 11; +pub static Pointer: TypeKind = 12; +pub static Vector: TypeKind = 13; +pub static Metadata: TypeKind = 14; +pub static X86_MMX: TypeKind = 15; pub enum AtomicBinOp { Xchg = 0, @@ -1582,7 +1580,8 @@ pub fn type_to_str_inner(names: @TypeNames, +outer0: &[TypeRef], ty: TypeRef) } Vector => return @"Vector", Metadata => return @"Metadata", - X86_MMX => return @"X86_MMAX" + X86_MMX => return @"X86_MMAX", + _ => fail!() } } } diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index 7e159ef606242..60b502873e2d5 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -180,37 +180,3 @@ pub impl FnType { Ret(bcx, llretval); } } - -enum LLVM_ABIInfo { LLVM_ABIInfo } - -impl ABIInfo for LLVM_ABIInfo { - fn compute_info(&self, - atys: &[TypeRef], - rty: TypeRef, - _ret_def: bool) -> FnType { - let arg_tys = do atys.map |a| { - LLVMType { cast: false, ty: *a } - }; - let ret_ty = LLVMType { - cast: false, - ty: rty - }; - let attrs = do atys.map |_| { - option::None - }; - let sret = false; - - return FnType { - arg_tys: arg_tys, - ret_ty: ret_ty, - attrs: attrs, - sret: sret - }; - } -} - -pub fn llvm_abi_info() -> @ABIInfo { - return @LLVM_ABIInfo as @ABIInfo; -} - - diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index ce37455560b5c..9a1c95e5184c0 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -227,6 +227,6 @@ impl ABIInfo for MIPS_ABIInfo { } } -pub fn mips_abi_info() -> @ABIInfo { +pub fn abi_info() -> @ABIInfo { return @MIPS_ABIInfo as @ABIInfo; } diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs new file mode 100644 index 0000000000000..a549f9121716f --- /dev/null +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -0,0 +1,77 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use driver::session::os_win32; +use core::option::*; +use lib::llvm::*; +use lib::llvm::llvm::*; +use super::cabi::*; +use super::common::*; +use super::machine::*; + +struct X86_ABIInfo { + ccx: @CrateContext +} + +impl ABIInfo for X86_ABIInfo { + fn compute_info(&self, + atys: &[TypeRef], + rty: TypeRef, + ret_def: bool) -> FnType { + let mut arg_tys = do atys.map |a| { + LLVMType { cast: false, ty: *a } + }; + let mut ret_ty = LLVMType { + cast: false, + ty: rty + }; + let mut attrs = do atys.map |_| { + None + }; + + // Rules for returning structs taken from + // http://www.angelcode.com/dev/callconv/callconv.html + let sret = { + let returning_a_struct = unsafe { LLVMGetTypeKind(rty) == Struct && ret_def }; + let big_struct = if self.ccx.sess.targ_cfg.os != os_win32 { + true + } else { + llsize_of_alloc(self.ccx, rty) > 8 + }; + returning_a_struct && big_struct + }; + + if sret { + let ret_ptr_ty = LLVMType { + cast: false, + ty: T_ptr(ret_ty.ty) + }; + arg_tys = ~[ret_ptr_ty] + arg_tys; + attrs = ~[Some(StructRetAttribute)] + attrs; + ret_ty = LLVMType { + cast: false, + ty: T_void(), + }; + } + + return FnType { + arg_tys: arg_tys, + ret_ty: ret_ty, + attrs: attrs, + sret: sret + }; + } +} + +pub fn abi_info(ccx: @CrateContext) -> @ABIInfo { + return @X86_ABIInfo { + ccx: ccx + } as @ABIInfo; +} diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index fa85588cb0f48..31ac4534462a5 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -410,6 +410,6 @@ impl ABIInfo for X86_64_ABIInfo { } } -pub fn x86_64_abi_info() -> @ABIInfo { +pub fn abi_info() -> @ABIInfo { return @X86_64_ABIInfo as @ABIInfo; } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 387caa4d8d31f..1037a4c071041 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -16,9 +16,10 @@ use lib::llvm::{TypeRef, ValueRef}; use lib; use middle::trans::base::*; use middle::trans::cabi; -use middle::trans::cabi_x86_64::*; +use middle::trans::cabi_x86; +use middle::trans::cabi_x86_64; use middle::trans::cabi_arm; -use middle::trans::cabi_mips::*; +use middle::trans::cabi_mips; use middle::trans::build::*; use middle::trans::callee::*; use middle::trans::common::*; @@ -42,12 +43,12 @@ use syntax::abi::{Architecture, X86, X86_64, Arm, Mips}; use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, Cdecl, Aapcs, C}; -fn abi_info(arch: Architecture) -> @cabi::ABIInfo { - return match arch { - X86_64 => x86_64_abi_info(), +fn abi_info(ccx: @CrateContext) -> @cabi::ABIInfo { + return match ccx.sess.targ_cfg.arch { + X86 => cabi_x86::abi_info(ccx), + X86_64 => cabi_x86_64::abi_info(), Arm => cabi_arm::abi_info(), - Mips => mips_abi_info(), - X86 => cabi::llvm_abi_info() + Mips => cabi_mips::abi_info(), } } @@ -112,7 +113,7 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { !ty::type_is_bot(fn_sig.output) && !ty::type_is_nil(fn_sig.output); let fn_ty = - abi_info(ccx.sess.targ_cfg.arch).compute_info( + abi_info(ccx).compute_info( llsig.llarg_tys, llsig.llret_ty, ret_def); diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index d1dbb48ba08a4..3fbe1b96ef7aa 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -69,6 +69,7 @@ pub mod middle { pub mod tvec; pub mod meth; pub mod cabi; + pub mod cabi_x86; pub mod cabi_x86_64; pub mod cabi_arm; pub mod cabi_mips; diff --git a/src/rt/rust_test_helpers.cpp b/src/rt/rust_test_helpers.cpp index 2c8026f159efa..64966bd345489 100644 --- a/src/rt/rust_test_helpers.cpp +++ b/src/rt/rust_test_helpers.cpp @@ -30,26 +30,6 @@ rust_dbg_extern_identity_u64(uint64_t u) { return u; } -struct TwoU64s { - uint64_t one; - uint64_t two; -}; - -extern "C" CDECL TwoU64s -rust_dbg_extern_identity_TwoU64s(TwoU64s u) { - return u; -} - -struct TwoDoubles { - double one; - double two; -}; - -extern "C" CDECL TwoDoubles -rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { - return u; -} - extern "C" CDECL double rust_dbg_extern_identity_double(double u) { return u; @@ -103,3 +83,85 @@ rust_dbg_call(dbg_callback cb, void *data) { } extern "C" CDECL void rust_dbg_do_nothing() { } + +struct TwoU8s { + uint8_t one; + uint8_t two; +}; + +extern "C" CDECL TwoU8s +rust_dbg_extern_return_TwoU8s() { + struct TwoU8s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU8s +rust_dbg_extern_identity_TwoU8s(TwoU8s u) { + return u; +} + +struct TwoU16s { + uint16_t one; + uint16_t two; +}; + +extern "C" CDECL TwoU16s +rust_dbg_extern_return_TwoU16s() { + struct TwoU16s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU16s +rust_dbg_extern_identity_TwoU16s(TwoU16s u) { + return u; +} + +struct TwoU32s { + uint32_t one; + uint32_t two; +}; + +extern "C" CDECL TwoU32s +rust_dbg_extern_return_TwoU32s() { + struct TwoU32s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU32s +rust_dbg_extern_identity_TwoU32s(TwoU32s u) { + return u; +} + +struct TwoU64s { + uint64_t one; + uint64_t two; +}; + +extern "C" CDECL TwoU64s +rust_dbg_extern_return_TwoU64s() { + struct TwoU64s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU64s +rust_dbg_extern_identity_TwoU64s(TwoU64s u) { + return u; +} + +struct TwoDoubles { + double one; + double two; +}; + +extern "C" CDECL TwoDoubles +rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { + return u; +} diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 73dbe661d3f86..f63e3f53a7caf 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -198,8 +198,15 @@ rust_readdir rust_opendir rust_dbg_extern_identity_u32 rust_dbg_extern_identity_u64 +rust_dbg_extern_identity_TwoU8s +rust_dbg_extern_identity_TwoU16s +rust_dbg_extern_identity_TwoU32s rust_dbg_extern_identity_TwoU64s rust_dbg_extern_identity_TwoDoubles +rust_dbg_extern_return_TwoU8s +rust_dbg_extern_return_TwoU16s +rust_dbg_extern_return_TwoU32s +rust_dbg_extern_return_TwoU64s rust_dbg_extern_identity_double rust_dbg_extern_identity_u8 rust_get_rt_env @@ -214,4 +221,3 @@ rust_uv_free_ip6_addr rust_call_nullary_fn rust_initialize_global_state - diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs new file mode 100644 index 0000000000000..f0343c4d2a267 --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU16s.rs @@ -0,0 +1,32 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a foreign function that accepts and returns a struct +// by value. + +// xfail-test #5744 + +#[deriving(Eq)] +struct TwoU16s { + one: u16, two: u16 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; +} + +pub fn main() { + unsafe { + let x = TwoU16s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU16s(x); + assert!(x == y); + } +} + diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs new file mode 100644 index 0000000000000..16d14a96cfe4f --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -0,0 +1,30 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a foreign function that accepts and returns a struct +// by value. + +#[deriving(Eq)] +struct TwoU32s { + one: u32, two: u32 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s; +} + +pub fn main() { + unsafe { + let x = TwoU32s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU32s(x); + assert!(x == y); + } +} + diff --git a/src/test/run-pass/extern-pass-TwoU64s-ref.rs b/src/test/run-pass/extern-pass-TwoU64s-ref.rs index 87bec86d8de70..56d3f8ebbff7f 100644 --- a/src/test/run-pass/extern-pass-TwoU64s-ref.rs +++ b/src/test/run-pass/extern-pass-TwoU64s-ref.rs @@ -10,8 +10,6 @@ // Test that we ignore modes when calling extern functions. -// xfail-test --- broken on 32-bit ABIs! (#5347) - #[deriving(Eq)] struct TwoU64s { one: u64, two: u64 diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs index fb91d5495e16f..eb2e3b1158f1c 100644 --- a/src/test/run-pass/extern-pass-TwoU64s.rs +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -11,7 +11,7 @@ // Test a foreign function that accepts and returns a struct // by value. -// xfail-test --- broken on 32-bit ABIs! (#5347) +// xfail-fast This works standalone on windows but not with check-fast. don't know why #[deriving(Eq)] struct TwoU64s { diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs new file mode 100644 index 0000000000000..213e9a68a7f89 --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU8s.rs @@ -0,0 +1,32 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a foreign function that accepts and returns a struct +// by value. + +// xfail-test #5744 + +#[deriving(Eq)] +struct TwoU8s { + one: u8, two: u8 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; +} + +pub fn main() { + unsafe { + let x = TwoU8s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU8s(x); + assert!(x == y); + } +} + diff --git a/src/test/run-pass/extern-return-TwoU16s.rs b/src/test/run-pass/extern-return-TwoU16s.rs new file mode 100644 index 0000000000000..0ea649a65b05f --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU16s.rs @@ -0,0 +1,27 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 #5745 + +struct TwoU16s { + one: u16, two: u16 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU16s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +} diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs new file mode 100644 index 0000000000000..9e374687855b0 --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU32s.rs @@ -0,0 +1,25 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct TwoU32s { + one: u32, two: u32 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU32s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +} diff --git a/src/test/run-pass/extern-return-TwoU64s.rs b/src/test/run-pass/extern-return-TwoU64s.rs new file mode 100644 index 0000000000000..250d3b8f562b0 --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU64s.rs @@ -0,0 +1,25 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct TwoU64s { + one: u64, two: u64 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU64s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +} diff --git a/src/test/run-pass/extern-return-TwoU8s.rs b/src/test/run-pass/extern-return-TwoU8s.rs new file mode 100644 index 0000000000000..9007d12a4514f --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU8s.rs @@ -0,0 +1,27 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 #5745 + +struct TwoU8s { + one: u8, two: u8 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU8s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +}