about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/trans/cabi.rs18
-rw-r--r--src/librustc/middle/trans/cabi_x86.rs15
-rw-r--r--src/librustc/middle/trans/foreign.rs10
-rw-r--r--src/rt/rust_test_helpers.c23
-rw-r--r--src/test/run-pass/extern-pass-TwoU16s.rs4
-rw-r--r--src/test/run-pass/extern-pass-TwoU8s.rs4
-rw-r--r--src/test/run-pass/extern-pass-empty.rs55
7 files changed, 120 insertions, 9 deletions
diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs
index d760c645441..7e67673d160 100644
--- a/src/librustc/middle/trans/cabi.rs
+++ b/src/librustc/middle/trans/cabi.rs
@@ -25,7 +25,9 @@ pub enum ArgKind {
     /// LLVM type or by coercing to another specified type
     Direct,
     /// Pass the argument indirectly via a hidden pointer
-    Indirect
+    Indirect,
+    /// Ignore the argument (useful for empty struct)
+    Ignore,
 }
 
 /// Information about how a specific C type
@@ -68,6 +70,16 @@ impl ArgType {
         }
     }
 
+    pub fn ignore(ty: Type) -> ArgType {
+        ArgType {
+            kind: Ignore,
+            ty: ty,
+            cast: None,
+            pad: None,
+            attr: None,
+        }
+    }
+
     pub fn is_direct(&self) -> bool {
         return self.kind == Direct;
     }
@@ -75,6 +87,10 @@ impl ArgType {
     pub fn is_indirect(&self) -> bool {
         return self.kind == Indirect;
     }
+
+    pub fn is_ignore(&self) -> bool {
+        return self.kind == Ignore;
+    }
 }
 
 /// Metadata describing how the arguments to a native function
diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs
index b2cb6970597..85a7c14968f 100644
--- a/src/librustc/middle/trans/cabi_x86.rs
+++ b/src/librustc/middle/trans/cabi_x86.rs
@@ -63,8 +63,19 @@ pub fn compute_abi_info(ccx: &CrateContext,
         ret_ty = ArgType::direct(rty, None, None, None);
     }
 
-    for &a in atys.iter() {
-        arg_tys.push(ArgType::direct(a, None, None, None));
+    for &t in atys.iter() {
+        let ty = match t.kind() {
+            Struct => {
+                let size = llsize_of_alloc(ccx, t);
+                if size == 0 {
+                    ArgType::ignore(t)
+                } else {
+                    ArgType::indirect(t, Some(ByValAttribute))
+                }
+            }
+            _ => ArgType::direct(t, None, None, None),
+        };
+        arg_tys.push(ty);
     }
 
     return FnType {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 7f6781096f5..74bed116806 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -325,6 +325,10 @@ pub fn trans_native_call<'a>(
     for (i, &llarg_rust) in llargs_rust.iter().enumerate() {
         let mut llarg_rust = llarg_rust;
 
+        if arg_tys[i].is_ignore() {
+            continue;
+        }
+
         // Does Rust pass this argument by pointer?
         let rust_indirect = type_of::arg_is_indirect(ccx,
                                                      *passed_arg_tys.get(i));
@@ -901,6 +905,9 @@ fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> T
     };
 
     for &arg_ty in tys.fn_ty.arg_tys.iter() {
+        if arg_ty.is_ignore() {
+            continue;
+        }
         // add padding
         match arg_ty.pad {
             Some(ty) => llargument_tys.push(ty),
@@ -949,6 +956,9 @@ fn add_argument_attributes(tys: &ForeignTypes,
     }
 
     for &arg_ty in tys.fn_ty.arg_tys.iter() {
+        if arg_ty.is_ignore() {
+            continue;
+        }
         // skip padding
         if arg_ty.pad.is_some() { i += 1; }
 
diff --git a/src/rt/rust_test_helpers.c b/src/rt/rust_test_helpers.c
index ee328e6cdb5..4d5b95155ca 100644
--- a/src/rt/rust_test_helpers.c
+++ b/src/rt/rust_test_helpers.c
@@ -126,6 +126,29 @@ rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) {
     return u;
 }
 
+struct ManyInts {
+    int8_t arg1;
+    int16_t arg2;
+    int32_t arg3;
+    int16_t arg4;
+    int8_t arg5;
+    struct TwoU8s arg6;
+};
+
+struct Empty {
+};
+
+void
+rust_dbg_extern_empty_struct(struct ManyInts v1, struct Empty e, struct ManyInts v2) {
+    assert(v1.arg1 == v2.arg1 + 1);
+    assert(v1.arg2 == v2.arg2 + 1);
+    assert(v1.arg3 == v2.arg3 + 1);
+    assert(v1.arg4 == v2.arg4 + 1);
+    assert(v1.arg5 == v2.arg5 + 1);
+    assert(v1.arg6.one == v2.arg6.one + 1);
+    assert(v1.arg6.two == v2.arg6.two + 1);
+}
+
 intptr_t
 rust_get_test_int() {
   return 1;
diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs
index 2cbf9a37ca1..0eb7eabe747 100644
--- a/src/test/run-pass/extern-pass-TwoU16s.rs
+++ b/src/test/run-pass/extern-pass-TwoU16s.rs
@@ -8,12 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test #5744 fails on 32 bit
-
 // Test a foreign function that accepts and returns a struct
 // by value.
 
-#[deriving(Eq)]
+#[deriving(Eq, Show)]
 struct TwoU16s {
     one: u16, two: u16
 }
diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs
index 7ca351994bf..b5c99d55a8e 100644
--- a/src/test/run-pass/extern-pass-TwoU8s.rs
+++ b/src/test/run-pass/extern-pass-TwoU8s.rs
@@ -8,12 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test #5744 fails on 32 bit
-
 // Test a foreign function that accepts and returns a struct
 // by value.
 
-#[deriving(Eq)]
+#[deriving(Eq, Show)]
 struct TwoU8s {
     one: u8, two: u8
 }
diff --git a/src/test/run-pass/extern-pass-empty.rs b/src/test/run-pass/extern-pass-empty.rs
new file mode 100644
index 00000000000..4c343fdb1a2
--- /dev/null
+++ b/src/test/run-pass/extern-pass-empty.rs
@@ -0,0 +1,55 @@
+// 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.
+
+// Test a foreign function that accepts empty struct.
+
+struct TwoU8s {
+    one: u8,
+    two: u8,
+}
+
+struct ManyInts {
+    arg1: i8,
+    arg2: i16,
+    arg3: i32,
+    arg4: i16,
+    arg5: i8,
+    arg6: TwoU8s,
+}
+
+struct Empty;
+
+#[link(name = "rustrt")]
+extern {
+    fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
+}
+
+pub fn main() {
+    unsafe {
+        let x = ManyInts {
+            arg1: 2,
+            arg2: 3,
+            arg3: 4,
+            arg4: 5,
+            arg5: 6,
+            arg6: TwoU8s { one: 7, two: 8, }
+        };
+        let y = ManyInts {
+            arg1: 1,
+            arg2: 2,
+            arg3: 3,
+            arg4: 4,
+            arg5: 5,
+            arg6: TwoU8s { one: 6, two: 7, }
+        };
+        let empty = Empty;
+        rust_dbg_extern_empty_struct(x, empty, y);
+    }
+}