Skip to content

Commit fdb4ef3

Browse files
committed
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.
2 parents 68dea75 + a5ddc00 commit fdb4ef3

21 files changed

+484
-158
lines changed

mk/rt.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ RUNTIME_CXXS_$(1) := \
7676
rt/boxed_region.cpp \
7777
rt/arch/$$(HOST_$(1))/context.cpp \
7878
rt/arch/$$(HOST_$(1))/gpr.cpp \
79-
rt/rust_android_dummy.cpp
79+
rt/rust_android_dummy.cpp \
80+
rt/rust_test_helpers.cpp
8081

8182
RUNTIME_CS_$(1) := rt/linenoise/linenoise.c rt/linenoise/utf8.c
8283

src/libcore/rt/uv/net.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,6 @@ impl NativeHandle<*uvll::uv_write_t> for WriteRequest {
356356

357357

358358
#[test]
359-
#[ignore(reason = "ffi struct issues")]
360359
fn connect_close() {
361360
do run_in_bare_thread() {
362361
let mut loop_ = Loop::new();
@@ -409,7 +408,6 @@ fn connect_read() {
409408
}
410409
411410
#[test]
412-
#[ignore(reason = "ffi struct issues")]
413411
fn listen() {
414412
do run_in_bare_thread() {
415413
static MAX: int = 10;

src/librustc/lib/llvm.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -125,27 +125,25 @@ pub enum RealPredicate {
125125
RealPredicateTrue = 15,
126126
}
127127

128-
// enum for the LLVM TypeKind type - must stay in sync with the def of
128+
// The LLVM TypeKind type - must stay in sync with the def of
129129
// LLVMTypeKind in llvm/include/llvm-c/Core.h
130-
#[deriving(Eq)]
131-
pub enum TypeKind {
132-
Void = 0,
133-
Half = 1,
134-
Float = 2,
135-
Double = 3,
136-
X86_FP80 = 4,
137-
FP128 = 5,
138-
PPC_FP128 = 6,
139-
Label = 7,
140-
Integer = 8,
141-
Function = 9,
142-
Struct = 10,
143-
Array = 11,
144-
Pointer = 12,
145-
Vector = 13,
146-
Metadata = 14,
147-
X86_MMX = 15
148-
}
130+
pub type TypeKind = u32;
131+
pub static Void: TypeKind = 0;
132+
pub static Half: TypeKind = 1;
133+
pub static Float: TypeKind = 2;
134+
pub static Double: TypeKind = 3;
135+
pub static X86_FP80: TypeKind = 4;
136+
pub static FP128: TypeKind = 5;
137+
pub static PPC_FP128: TypeKind = 6;
138+
pub static Label: TypeKind = 7;
139+
pub static Integer: TypeKind = 8;
140+
pub static Function: TypeKind = 9;
141+
pub static Struct: TypeKind = 10;
142+
pub static Array: TypeKind = 11;
143+
pub static Pointer: TypeKind = 12;
144+
pub static Vector: TypeKind = 13;
145+
pub static Metadata: TypeKind = 14;
146+
pub static X86_MMX: TypeKind = 15;
149147

150148
pub enum AtomicBinOp {
151149
Xchg = 0,
@@ -1582,7 +1580,8 @@ pub fn type_to_str_inner(names: @TypeNames, +outer0: &[TypeRef], ty: TypeRef)
15821580
}
15831581
Vector => return @"Vector",
15841582
Metadata => return @"Metadata",
1585-
X86_MMX => return @"X86_MMAX"
1583+
X86_MMX => return @"X86_MMAX",
1584+
_ => fail!()
15861585
}
15871586
}
15881587
}

src/librustc/middle/trans/cabi.rs

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -180,37 +180,3 @@ pub impl FnType {
180180
Ret(bcx, llretval);
181181
}
182182
}
183-
184-
enum LLVM_ABIInfo { LLVM_ABIInfo }
185-
186-
impl ABIInfo for LLVM_ABIInfo {
187-
fn compute_info(&self,
188-
atys: &[TypeRef],
189-
rty: TypeRef,
190-
_ret_def: bool) -> FnType {
191-
let arg_tys = do atys.map |a| {
192-
LLVMType { cast: false, ty: *a }
193-
};
194-
let ret_ty = LLVMType {
195-
cast: false,
196-
ty: rty
197-
};
198-
let attrs = do atys.map |_| {
199-
option::None
200-
};
201-
let sret = false;
202-
203-
return FnType {
204-
arg_tys: arg_tys,
205-
ret_ty: ret_ty,
206-
attrs: attrs,
207-
sret: sret
208-
};
209-
}
210-
}
211-
212-
pub fn llvm_abi_info() -> @ABIInfo {
213-
return @LLVM_ABIInfo as @ABIInfo;
214-
}
215-
216-

src/librustc/middle/trans/cabi_mips.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,6 @@ impl ABIInfo for MIPS_ABIInfo {
227227
}
228228
}
229229

230-
pub fn mips_abi_info() -> @ABIInfo {
230+
pub fn abi_info() -> @ABIInfo {
231231
return @MIPS_ABIInfo as @ABIInfo;
232232
}

src/librustc/middle/trans/cabi_x86.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use driver::session::os_win32;
12+
use core::option::*;
13+
use lib::llvm::*;
14+
use lib::llvm::llvm::*;
15+
use super::cabi::*;
16+
use super::common::*;
17+
use super::machine::*;
18+
19+
struct X86_ABIInfo {
20+
ccx: @CrateContext
21+
}
22+
23+
impl ABIInfo for X86_ABIInfo {
24+
fn compute_info(&self,
25+
atys: &[TypeRef],
26+
rty: TypeRef,
27+
ret_def: bool) -> FnType {
28+
let mut arg_tys = do atys.map |a| {
29+
LLVMType { cast: false, ty: *a }
30+
};
31+
let mut ret_ty = LLVMType {
32+
cast: false,
33+
ty: rty
34+
};
35+
let mut attrs = do atys.map |_| {
36+
None
37+
};
38+
39+
// Rules for returning structs taken from
40+
// http://www.angelcode.com/dev/callconv/callconv.html
41+
let sret = {
42+
let returning_a_struct = unsafe { LLVMGetTypeKind(rty) == Struct && ret_def };
43+
let big_struct = if self.ccx.sess.targ_cfg.os != os_win32 {
44+
true
45+
} else {
46+
llsize_of_alloc(self.ccx, rty) > 8
47+
};
48+
returning_a_struct && big_struct
49+
};
50+
51+
if sret {
52+
let ret_ptr_ty = LLVMType {
53+
cast: false,
54+
ty: T_ptr(ret_ty.ty)
55+
};
56+
arg_tys = ~[ret_ptr_ty] + arg_tys;
57+
attrs = ~[Some(StructRetAttribute)] + attrs;
58+
ret_ty = LLVMType {
59+
cast: false,
60+
ty: T_void(),
61+
};
62+
}
63+
64+
return FnType {
65+
arg_tys: arg_tys,
66+
ret_ty: ret_ty,
67+
attrs: attrs,
68+
sret: sret
69+
};
70+
}
71+
}
72+
73+
pub fn abi_info(ccx: @CrateContext) -> @ABIInfo {
74+
return @X86_ABIInfo {
75+
ccx: ccx
76+
} as @ABIInfo;
77+
}

src/librustc/middle/trans/cabi_x86_64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,6 @@ impl ABIInfo for X86_64_ABIInfo {
410410
}
411411
}
412412

413-
pub fn x86_64_abi_info() -> @ABIInfo {
413+
pub fn abi_info() -> @ABIInfo {
414414
return @X86_64_ABIInfo as @ABIInfo;
415415
}

src/librustc/middle/trans/foreign.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ use lib::llvm::{TypeRef, ValueRef};
1616
use lib;
1717
use middle::trans::base::*;
1818
use middle::trans::cabi;
19-
use middle::trans::cabi_x86_64::*;
19+
use middle::trans::cabi_x86;
20+
use middle::trans::cabi_x86_64;
2021
use middle::trans::cabi_arm;
21-
use middle::trans::cabi_mips::*;
22+
use middle::trans::cabi_mips;
2223
use middle::trans::build::*;
2324
use middle::trans::callee::*;
2425
use middle::trans::common::*;
@@ -42,12 +43,12 @@ use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
4243
use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall,
4344
Cdecl, Aapcs, C};
4445

45-
fn abi_info(arch: Architecture) -> @cabi::ABIInfo {
46-
return match arch {
47-
X86_64 => x86_64_abi_info(),
46+
fn abi_info(ccx: @CrateContext) -> @cabi::ABIInfo {
47+
return match ccx.sess.targ_cfg.arch {
48+
X86 => cabi_x86::abi_info(ccx),
49+
X86_64 => cabi_x86_64::abi_info(),
4850
Arm => cabi_arm::abi_info(),
49-
Mips => mips_abi_info(),
50-
X86 => cabi::llvm_abi_info()
51+
Mips => cabi_mips::abi_info(),
5152
}
5253
}
5354

@@ -112,7 +113,7 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes {
112113
!ty::type_is_bot(fn_sig.output) &&
113114
!ty::type_is_nil(fn_sig.output);
114115
let fn_ty =
115-
abi_info(ccx.sess.targ_cfg.arch).compute_info(
116+
abi_info(ccx).compute_info(
116117
llsig.llarg_tys,
117118
llsig.llret_ty,
118119
ret_def);

src/librustc/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub mod middle {
6969
pub mod tvec;
7070
pub mod meth;
7171
pub mod cabi;
72+
pub mod cabi_x86;
7273
pub mod cabi_x86_64;
7374
pub mod cabi_arm;
7475
pub mod cabi_mips;

src/rt/rust_builtin.cpp

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -589,50 +589,6 @@ rust_log_console_off() {
589589
log_console_off(task->kernel->env);
590590
}
591591

592-
extern "C" CDECL lock_and_signal *
593-
rust_dbg_lock_create() {
594-
return new lock_and_signal();
595-
}
596-
597-
extern "C" CDECL void
598-
rust_dbg_lock_destroy(lock_and_signal *lock) {
599-
assert(lock);
600-
delete lock;
601-
}
602-
603-
extern "C" CDECL void
604-
rust_dbg_lock_lock(lock_and_signal *lock) {
605-
assert(lock);
606-
lock->lock();
607-
}
608-
609-
extern "C" CDECL void
610-
rust_dbg_lock_unlock(lock_and_signal *lock) {
611-
assert(lock);
612-
lock->unlock();
613-
}
614-
615-
extern "C" CDECL void
616-
rust_dbg_lock_wait(lock_and_signal *lock) {
617-
assert(lock);
618-
lock->wait();
619-
}
620-
621-
extern "C" CDECL void
622-
rust_dbg_lock_signal(lock_and_signal *lock) {
623-
assert(lock);
624-
lock->signal();
625-
}
626-
627-
typedef void *(*dbg_callback)(void*);
628-
629-
extern "C" CDECL void *
630-
rust_dbg_call(dbg_callback cb, void *data) {
631-
return cb(data);
632-
}
633-
634-
extern "C" CDECL void rust_dbg_do_nothing() { }
635-
636592
extern "C" CDECL void
637593
rust_dbg_breakpoint() {
638594
BREAKPOINT_AWESOME;
@@ -844,48 +800,6 @@ rust_readdir() {
844800

845801
#endif
846802

847-
// These functions are used in the unit tests for C ABI calls.
848-
849-
extern "C" CDECL uint32_t
850-
rust_dbg_extern_identity_u32(uint32_t u) {
851-
return u;
852-
}
853-
854-
extern "C" CDECL uint64_t
855-
rust_dbg_extern_identity_u64(uint64_t u) {
856-
return u;
857-
}
858-
859-
struct TwoU64s {
860-
uint64_t one;
861-
uint64_t two;
862-
};
863-
864-
extern "C" CDECL TwoU64s
865-
rust_dbg_extern_identity_TwoU64s(TwoU64s u) {
866-
return u;
867-
}
868-
869-
struct TwoDoubles {
870-
double one;
871-
double two;
872-
};
873-
874-
extern "C" CDECL TwoDoubles
875-
rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) {
876-
return u;
877-
}
878-
879-
extern "C" CDECL double
880-
rust_dbg_extern_identity_double(double u) {
881-
return u;
882-
}
883-
884-
extern "C" CDECL char
885-
rust_dbg_extern_identity_u8(char u) {
886-
return u;
887-
}
888-
889803
extern "C" rust_env*
890804
rust_get_rt_env() {
891805
rust_task *task = rust_get_current_task();

0 commit comments

Comments
 (0)