about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcore/rt/uv/net.rs2
-rw-r--r--src/librustc/lib/llvm.rs41
-rw-r--r--src/librustc/middle/trans/cabi.rs34
-rw-r--r--src/librustc/middle/trans/cabi_mips.rs2
-rw-r--r--src/librustc/middle/trans/cabi_x86.rs77
-rw-r--r--src/librustc/middle/trans/cabi_x86_64.rs2
-rw-r--r--src/librustc/middle/trans/foreign.rs17
-rw-r--r--src/librustc/rustc.rc1
-rw-r--r--src/rt/rust_builtin.cpp86
-rw-r--r--src/rt/rust_test_helpers.cpp167
-rw-r--r--src/rt/rustrt.def.in8
-rw-r--r--src/test/run-pass/extern-pass-TwoU16s.rs32
-rw-r--r--src/test/run-pass/extern-pass-TwoU32s.rs30
-rw-r--r--src/test/run-pass/extern-pass-TwoU64s-ref.rs2
-rw-r--r--src/test/run-pass/extern-pass-TwoU64s.rs2
-rw-r--r--src/test/run-pass/extern-pass-TwoU8s.rs32
-rw-r--r--src/test/run-pass/extern-return-TwoU16s.rs27
-rw-r--r--src/test/run-pass/extern-return-TwoU32s.rs25
-rw-r--r--src/test/run-pass/extern-return-TwoU64s.rs25
-rw-r--r--src/test/run-pass/extern-return-TwoU8s.rs27
20 files changed, 482 insertions, 157 deletions
diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs
index 29ea36cd88b..4b9ff4504dd 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 b6d3fce7e75..06f7261040c 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 7e159ef6062..60b502873e2 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 ce37455560b..9a1c95e5184 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 00000000000..a549f912171
--- /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 <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.
+
+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 fa85588cb0f..31ac4534462 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 387caa4d8d3..1037a4c0710 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 d1dbb48ba08..3fbe1b96ef7 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_builtin.cpp b/src/rt/rust_builtin.cpp
index 3c6cc9d9245..475c030e8f2 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -589,50 +589,6 @@ rust_log_console_off() {
     log_console_off(task->kernel->env);
 }
 
-extern "C" CDECL lock_and_signal *
-rust_dbg_lock_create() {
-    return new lock_and_signal();
-}
-
-extern "C" CDECL void
-rust_dbg_lock_destroy(lock_and_signal *lock) {
-    assert(lock);
-    delete lock;
-}
-
-extern "C" CDECL void
-rust_dbg_lock_lock(lock_and_signal *lock) {
-    assert(lock);
-    lock->lock();
-}
-
-extern "C" CDECL void
-rust_dbg_lock_unlock(lock_and_signal *lock) {
-    assert(lock);
-    lock->unlock();
-}
-
-extern "C" CDECL void
-rust_dbg_lock_wait(lock_and_signal *lock) {
-    assert(lock);
-    lock->wait();
-}
-
-extern "C" CDECL void
-rust_dbg_lock_signal(lock_and_signal *lock) {
-    assert(lock);
-    lock->signal();
-}
-
-typedef void *(*dbg_callback)(void*);
-
-extern "C" CDECL void *
-rust_dbg_call(dbg_callback cb, void *data) {
-    return cb(data);
-}
-
-extern "C" CDECL void rust_dbg_do_nothing() { }
-
 extern "C" CDECL void
 rust_dbg_breakpoint() {
     BREAKPOINT_AWESOME;
@@ -844,48 +800,6 @@ rust_readdir() {
 
 #endif
 
-// These functions are used in the unit tests for C ABI calls.
-
-extern "C" CDECL uint32_t
-rust_dbg_extern_identity_u32(uint32_t u) {
-    return u;
-}
-
-extern "C" CDECL uint64_t
-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;
-}
-
-extern "C" CDECL char
-rust_dbg_extern_identity_u8(char u) {
-    return u;
-}
-
 extern "C" rust_env*
 rust_get_rt_env() {
     rust_task *task = rust_get_current_task();
diff --git a/src/rt/rust_test_helpers.cpp b/src/rt/rust_test_helpers.cpp
new file mode 100644
index 00000000000..64966bd3454
--- /dev/null
+++ b/src/rt/rust_test_helpers.cpp
@@ -0,0 +1,167 @@
+// 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 <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.
+
+// Helper functions used only in tests
+
+#include "rust_sched_loop.h"
+#include "rust_task.h"
+#include "rust_util.h"
+#include "rust_scheduler.h"
+#include "sync/timer.h"
+#include "sync/rust_thread.h"
+#include "rust_abi.h"
+
+// These functions are used in the unit tests for C ABI calls.
+
+extern "C" CDECL uint32_t
+rust_dbg_extern_identity_u32(uint32_t u) {
+    return u;
+}
+
+extern "C" CDECL uint64_t
+rust_dbg_extern_identity_u64(uint64_t u) {
+    return u;
+}
+
+extern "C" CDECL double
+rust_dbg_extern_identity_double(double u) {
+    return u;
+}
+
+extern "C" CDECL char
+rust_dbg_extern_identity_u8(char u) {
+    return u;
+}
+
+extern "C" CDECL lock_and_signal *
+rust_dbg_lock_create() {
+    return new lock_and_signal();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_destroy(lock_and_signal *lock) {
+    assert(lock);
+    delete lock;
+}
+
+extern "C" CDECL void
+rust_dbg_lock_lock(lock_and_signal *lock) {
+    assert(lock);
+    lock->lock();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_unlock(lock_and_signal *lock) {
+    assert(lock);
+    lock->unlock();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_wait(lock_and_signal *lock) {
+    assert(lock);
+    lock->wait();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_signal(lock_and_signal *lock) {
+    assert(lock);
+    lock->signal();
+}
+
+typedef void *(*dbg_callback)(void*);
+
+extern "C" CDECL void *
+rust_dbg_call(dbg_callback cb, void *data) {
+    return cb(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 73dbe661d3f..f63e3f53a7c 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 00000000000..f0343c4d2a2
--- /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 <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.
+
+// 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 00000000000..16d14a96cfe
--- /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 <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.
+
+// 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 87bec86d8de..56d3f8ebbff 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 fb91d5495e1..eb2e3b1158f 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 00000000000..213e9a68a7f
--- /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 <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.
+
+// 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 00000000000..0ea649a65b0
--- /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 <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.
+
+// 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 00000000000..9e374687855
--- /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 <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.
+
+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 00000000000..250d3b8f562
--- /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 <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.
+
+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 00000000000..9007d12a451
--- /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 <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.
+
+// 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);
+    }
+}