Skip to content

Commit f8266fa

Browse files
committed
rustc: Use an out pointer to return structs in x86 C ABI. rust-lang#5347
1 parent c11dddc commit f8266fa

19 files changed

+379
-82
lines changed

src/libcore/rt/uv/net.rs

-2
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

+20-21
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

-34
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

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,6 @@ impl ABIInfo for MIPS_ABIInfo {
216216
}
217217
}
218218

219-
pub fn mips_abi_info() -> @ABIInfo {
219+
pub fn abi_info() -> @ABIInfo {
220220
return @MIPS_ABIInfo as @ABIInfo;
221221
}

src/librustc/middle/trans/cabi_x86.rs

+77
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

+1-1
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,6 @@ impl ABIInfo for X86_64_ABIInfo {
399399
}
400400
}
401401

402-
pub fn x86_64_abi_info() -> @ABIInfo {
402+
pub fn abi_info() -> @ABIInfo {
403403
return @X86_64_ABIInfo as @ABIInfo;
404404
}

src/librustc/middle/trans/foreign.rs

+10-8
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

@@ -111,7 +112,7 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes {
111112
!ty::type_is_bot(fn_sig.output) &&
112113
!ty::type_is_nil(fn_sig.output);
113114
let fn_ty =
114-
abi_info(ccx.sess.targ_cfg.arch).compute_info(
115+
abi_info(ccx).compute_info(
115116
llsig.llarg_tys,
116117
llsig.llret_ty,
117118
ret_def);
@@ -257,6 +258,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
257258
};
258259

259260
for vec::each(foreign_mod.items) |&foreign_item| {
261+
error!("translating foreign item: %s", *ccx.sess.str_of(foreign_item.ident))
260262
match foreign_item.node {
261263
ast::foreign_item_fn(*) => {
262264
let id = foreign_item.id;

src/librustc/rustc.rc

+1
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_test_helpers.cpp

+72-10
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,6 @@ rust_dbg_extern_identity_u64(uint64_t u) {
3030
return u;
3131
}
3232

33-
struct TwoU64s {
34-
uint64_t one;
35-
uint64_t two;
36-
};
37-
38-
extern "C" CDECL TwoU64s
39-
rust_dbg_extern_identity_TwoU64s(TwoU64s u) {
40-
return u;
41-
}
42-
4333
extern "C" CDECL double
4434
rust_dbg_extern_identity_double(double u) {
4535
return u;
@@ -93,3 +83,75 @@ rust_dbg_call(dbg_callback cb, void *data) {
9383
}
9484

9585
extern "C" CDECL void rust_dbg_do_nothing() { }
86+
87+
struct TwoU8s {
88+
uint8_t one;
89+
uint8_t two;
90+
};
91+
92+
extern "C" CDECL TwoU8s
93+
rust_dbg_extern_return_TwoU8s() {
94+
struct TwoU8s s;
95+
s.one = 10;
96+
s.two = 20;
97+
return s;
98+
}
99+
100+
extern "C" CDECL TwoU8s
101+
rust_dbg_extern_identity_TwoU8s(TwoU8s u) {
102+
return u;
103+
}
104+
105+
struct TwoU16s {
106+
uint16_t one;
107+
uint16_t two;
108+
};
109+
110+
extern "C" CDECL TwoU16s
111+
rust_dbg_extern_return_TwoU16s() {
112+
struct TwoU16s s;
113+
s.one = 10;
114+
s.two = 20;
115+
return s;
116+
}
117+
118+
extern "C" CDECL TwoU16s
119+
rust_dbg_extern_identity_TwoU16s(TwoU16s u) {
120+
return u;
121+
}
122+
123+
struct TwoU32s {
124+
uint32_t one;
125+
uint32_t two;
126+
};
127+
128+
extern "C" CDECL TwoU32s
129+
rust_dbg_extern_return_TwoU32s() {
130+
struct TwoU32s s;
131+
s.one = 10;
132+
s.two = 20;
133+
return s;
134+
}
135+
136+
extern "C" CDECL TwoU32s
137+
rust_dbg_extern_identity_TwoU32s(TwoU32s u) {
138+
return u;
139+
}
140+
141+
struct TwoU64s {
142+
uint64_t one;
143+
uint64_t two;
144+
};
145+
146+
extern "C" CDECL TwoU64s
147+
rust_dbg_extern_return_TwoU64s() {
148+
struct TwoU64s s;
149+
s.one = 10;
150+
s.two = 20;
151+
return s;
152+
}
153+
154+
extern "C" CDECL TwoU64s
155+
rust_dbg_extern_identity_TwoU64s(TwoU64s u) {
156+
return u;
157+
}

src/rt/rustrt.def.in

+7-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,14 @@ rust_readdir
198198
rust_opendir
199199
rust_dbg_extern_identity_u32
200200
rust_dbg_extern_identity_u64
201+
rust_dbg_extern_identity_TwoU8s
202+
rust_dbg_extern_identity_TwoU16s
203+
rust_dbg_extern_identity_TwoU32s
201204
rust_dbg_extern_identity_TwoU64s
205+
rust_dbg_extern_return_TwoU8s
206+
rust_dbg_extern_return_TwoU16s
207+
rust_dbg_extern_return_TwoU32s
208+
rust_dbg_extern_return_TwoU64s
202209
rust_dbg_extern_identity_double
203210
rust_dbg_extern_identity_u8
204211
rust_get_rt_env
@@ -213,4 +220,3 @@ rust_uv_free_ip6_addr
213220
rust_call_nullary_fn
214221
rust_initialize_global_state
215222

216-

0 commit comments

Comments
 (0)