auto merge of #5726 : brson/rust/struct-return, r=brson
r? @nikomatsakis This doesn't completely fix the x86 ABI for structs, but it does fix some cases. On linux, structs appear to be returned correctly now. On windows, structs are only returned by pointer when they are greater than 8 bytes. That scenario works now. In the case where the struct is less than 8 bytes our generated code looks peculiar. When returning a pair of u16, C packs both variables into %eax to return them. Our generated code though expects to find one of the pair in %ax and the other in %dx. Similar for u8. I haven't looked into it yet. There appears to also be struct passing problems on linux, where my `extern-pass-TwoU8s` and `extern-pass-TwoU16s` tests are failing.
This commit is contained in:
commit
fdb4ef321e
21 changed files with 484 additions and 158 deletions
3
mk/rt.mk
3
mk/rt.mk
|
|
@ -76,7 +76,8 @@ RUNTIME_CXXS_$(1) := \
|
|||
rt/boxed_region.cpp \
|
||||
rt/arch/$$(HOST_$(1))/context.cpp \
|
||||
rt/arch/$$(HOST_$(1))/gpr.cpp \
|
||||
rt/rust_android_dummy.cpp
|
||||
rt/rust_android_dummy.cpp \
|
||||
rt/rust_test_helpers.cpp
|
||||
|
||||
RUNTIME_CS_$(1) := rt/linenoise/linenoise.c rt/linenoise/utf8.c
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
77
src/librustc/middle/trans/cabi_x86.rs
Normal file
77
src/librustc/middle/trans/cabi_x86.rs
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
167
src/rt/rust_test_helpers.cpp
Normal file
167
src/rt/rust_test_helpers.cpp
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
32
src/test/run-pass/extern-pass-TwoU16s.rs
Normal file
32
src/test/run-pass/extern-pass-TwoU16s.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
30
src/test/run-pass/extern-pass-TwoU32s.rs
Normal file
30
src/test/run-pass/extern-pass-TwoU32s.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
32
src/test/run-pass/extern-pass-TwoU8s.rs
Normal file
32
src/test/run-pass/extern-pass-TwoU8s.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
27
src/test/run-pass/extern-return-TwoU16s.rs
Normal file
27
src/test/run-pass/extern-return-TwoU16s.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
25
src/test/run-pass/extern-return-TwoU32s.rs
Normal file
25
src/test/run-pass/extern-return-TwoU32s.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
25
src/test/run-pass/extern-return-TwoU64s.rs
Normal file
25
src/test/run-pass/extern-return-TwoU64s.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
27
src/test/run-pass/extern-return-TwoU8s.rs
Normal file
27
src/test/run-pass/extern-return-TwoU8s.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue