Skip to content

Commit 0daced6

Browse files
committed
auto merge of #9517 : crabtw/rust/cabi, r=nikomatsakis
I borrow some ideas from clang's ABIInfo.h and TargetInfo.cpp. LLVMType is replaced with ArgType, which is similar to clang's ABIArgInfo, and I also merge attrs of FnType into it. Now ABI implementation doesn't need to insert hidden return pointer to arg_tys of FnType. Instead it is handled in foreign.rs. This change also fixes LLVM assertion failure when compiling MIPS target.
2 parents afa42a0 + 95fc31a commit 0daced6

File tree

6 files changed

+206
-188
lines changed

6 files changed

+206
-188
lines changed

src/librustc/middle/trans/cabi.rs

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,62 @@ use middle::trans::cabi_mips;
1818
use middle::trans::type_::Type;
1919
use syntax::abi::{X86, X86_64, Arm, Mips};
2020

21+
#[deriving(Clone, Eq)]
22+
pub enum ArgKind {
23+
/// Pass the argument directly using the normal converted
24+
/// LLVM type or by coercing to another specified type
25+
Direct,
26+
/// Pass the argument indirectly via a hidden pointer
27+
Indirect
28+
}
29+
30+
/// Information about how a specific C type
31+
/// should be passed to or returned from a function
32+
///
33+
/// This is borrowed from clang's ABIInfo.h
2134
#[deriving(Clone)]
22-
pub struct LLVMType {
23-
cast: bool,
24-
ty: Type
35+
pub struct ArgType {
36+
kind: ArgKind,
37+
/// Original LLVM type
38+
ty: Type,
39+
/// Coerced LLVM Type
40+
cast: option::Option<Type>,
41+
/// Dummy argument, which is emitted before the real argument
42+
pad: option::Option<Type>,
43+
/// LLVM attribute of argument
44+
attr: option::Option<Attribute>
45+
}
46+
47+
impl ArgType {
48+
pub fn direct(ty: Type, cast: option::Option<Type>,
49+
pad: option::Option<Type>,
50+
attr: option::Option<Attribute>) -> ArgType {
51+
ArgType {
52+
kind: Direct,
53+
ty: ty,
54+
cast: cast,
55+
pad: pad,
56+
attr: attr
57+
}
58+
}
59+
60+
pub fn indirect(ty: Type, attr: option::Option<Attribute>) -> ArgType {
61+
ArgType {
62+
kind: Indirect,
63+
ty: ty,
64+
cast: option::None,
65+
pad: option::None,
66+
attr: attr
67+
}
68+
}
69+
70+
pub fn is_direct(&self) -> bool {
71+
return self.kind == Direct;
72+
}
73+
74+
pub fn is_indirect(&self) -> bool {
75+
return self.kind == Indirect;
76+
}
2577
}
2678

2779
/// Metadata describing how the arguments to a native function
@@ -30,22 +82,11 @@ pub struct LLVMType {
3082
/// I will do my best to describe this structure, but these
3183
/// comments are reverse-engineered and may be inaccurate. -NDM
3284
pub struct FnType {
33-
/// The LLVM types of each argument. If the cast flag is true,
34-
/// then the argument should be cast, typically because the
35-
/// official argument type will be an int and the rust type is i8
36-
/// or something like that.
37-
arg_tys: ~[LLVMType],
38-
39-
/// A list of attributes to be attached to each argument (parallel
40-
/// the `arg_tys` array). If the attribute for a given is Some,
41-
/// then the argument should be passed by reference.
42-
attrs: ~[option::Option<Attribute>],
85+
/// The LLVM types of each argument.
86+
arg_tys: ~[ArgType],
4387

4488
/// LLVM return type.
45-
ret_ty: LLVMType,
46-
47-
/// If true, then an implicit pointer should be added for the result.
48-
sret: bool
89+
ret_ty: ArgType,
4990
}
5091

5192
pub fn compute_abi_info(ccx: &mut CrateContext,

src/librustc/middle/trans/cabi_arm.rs

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
#[allow(non_uppercase_pattern_statics)];
1212

1313
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
14-
use lib::llvm::{Attribute, StructRetAttribute};
15-
use middle::trans::cabi::{FnType, LLVMType};
14+
use lib::llvm::StructRetAttribute;
15+
use middle::trans::cabi::{FnType, ArgType};
1616
use middle::trans::context::CrateContext;
1717

1818
use middle::trans::type_::Type;
1919

2020
use std::num;
21-
use std::option::{Option, None, Some};
21+
use std::option::{None, Some};
2222

2323
fn align_up_to(off: uint, a: uint) -> uint {
2424
return (off + a - 1u) / a * a;
@@ -85,9 +85,9 @@ fn ty_size(ty: Type) -> uint {
8585
}
8686
}
8787

88-
fn classify_ret_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
88+
fn classify_ret_ty(ty: Type) -> ArgType {
8989
if is_reg_ty(ty) {
90-
return (LLVMType { cast: false, ty: ty }, None);
90+
return ArgType::direct(ty, None, None, None);
9191
}
9292
let size = ty_size(ty);
9393
if size <= 4 {
@@ -98,14 +98,14 @@ fn classify_ret_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
9898
} else {
9999
Type::i32()
100100
};
101-
return (LLVMType { cast: true, ty: llty }, None);
101+
return ArgType::direct(ty, Some(llty), None, None);
102102
}
103-
(LLVMType { cast: false, ty: ty.ptr_to() }, Some(StructRetAttribute))
103+
ArgType::indirect(ty, Some(StructRetAttribute))
104104
}
105105

106-
fn classify_arg_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
106+
fn classify_arg_ty(ty: Type) -> ArgType {
107107
if is_reg_ty(ty) {
108-
return (LLVMType { cast: false, ty: ty }, None);
108+
return ArgType::direct(ty, None, None, None);
109109
}
110110
let align = ty_align(ty);
111111
let size = ty_size(ty);
@@ -114,7 +114,7 @@ fn classify_arg_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
114114
} else {
115115
Type::array(&Type::i64(), ((size + 7) / 8) as u64)
116116
};
117-
(LLVMType { cast: true, ty: llty }, None)
117+
ArgType::direct(ty, Some(llty), None, None)
118118
}
119119

120120
fn is_reg_ty(ty: Type) -> bool {
@@ -132,32 +132,19 @@ pub fn compute_abi_info(_ccx: &mut CrateContext,
132132
rty: Type,
133133
ret_def: bool) -> FnType {
134134
let mut arg_tys = ~[];
135-
let mut attrs = ~[];
136135
for &aty in atys.iter() {
137-
let (ty, attr) = classify_arg_ty(aty);
136+
let ty = classify_arg_ty(aty);
138137
arg_tys.push(ty);
139-
attrs.push(attr);
140138
}
141139

142-
let (ret_ty, ret_attr) = if ret_def {
140+
let ret_ty = if ret_def {
143141
classify_ret_ty(rty)
144142
} else {
145-
(LLVMType { cast: false, ty: Type::void() }, None)
143+
ArgType::direct(Type::void(), None, None, None)
146144
};
147145

148-
let mut ret_ty = ret_ty;
149-
150-
let sret = ret_attr.is_some();
151-
if sret {
152-
arg_tys.unshift(ret_ty);
153-
attrs.unshift(ret_attr);
154-
ret_ty = LLVMType { cast: false, ty: Type::void() };
155-
}
156-
157146
return FnType {
158147
arg_tys: arg_tys,
159148
ret_ty: ret_ty,
160-
attrs: attrs,
161-
sret: sret
162149
};
163150
}

src/librustc/middle/trans/cabi_mips.rs

Lines changed: 22 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212

1313
use std::libc::c_uint;
1414
use std::num;
15-
use std::vec;
1615
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
17-
use lib::llvm::{Attribute, StructRetAttribute};
16+
use lib::llvm::StructRetAttribute;
1817
use middle::trans::context::CrateContext;
1918
use middle::trans::context::task_llcx;
2019
use middle::trans::cabi::*;
@@ -86,15 +85,15 @@ fn ty_size(ty: Type) -> uint {
8685
}
8786
}
8887

89-
fn classify_ret_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
90-
return if is_reg_ty(ty) {
91-
(LLVMType { cast: false, ty: ty }, None)
88+
fn classify_ret_ty(ty: Type) -> ArgType {
89+
if is_reg_ty(ty) {
90+
ArgType::direct(ty, None, None, None)
9291
} else {
93-
(LLVMType { cast: false, ty: ty.ptr_to() }, Some(StructRetAttribute))
94-
};
92+
ArgType::indirect(ty, Some(StructRetAttribute))
93+
}
9594
}
9695

97-
fn classify_arg_ty(ty: Type, offset: &mut uint) -> (LLVMType, Option<Attribute>) {
96+
fn classify_arg_ty(ty: Type, offset: &mut uint) -> ArgType {
9897
let orig_offset = *offset;
9998
let size = ty_size(ty) * 8;
10099
let mut align = ty_align(ty);
@@ -103,20 +102,16 @@ fn classify_arg_ty(ty: Type, offset: &mut uint) -> (LLVMType, Option<Attribute>)
103102
*offset = align_up_to(*offset, align);
104103
*offset += align_up_to(size, align * 8) / 8;
105104

106-
let padding = padding_ty(align, orig_offset);
107-
return if !is_reg_ty(ty) {
108-
(LLVMType {
109-
cast: true,
110-
ty: struct_ty(ty, padding, true)
111-
}, None)
112-
} else if padding.is_some() {
113-
(LLVMType {
114-
cast: true,
115-
ty: struct_ty(ty, padding, false)
116-
}, None)
105+
if is_reg_ty(ty) {
106+
ArgType::direct(ty, None, None, None)
117107
} else {
118-
(LLVMType { cast: false, ty: ty }, None)
119-
};
108+
ArgType::direct(
109+
ty,
110+
Some(struct_ty(ty)),
111+
padding_ty(align, orig_offset),
112+
None
113+
)
114+
}
120115
}
121116

122117
fn is_reg_ty(ty: Type) -> bool {
@@ -157,54 +152,33 @@ fn coerce_to_int(size: uint) -> ~[Type] {
157152
args
158153
}
159154

160-
fn struct_ty(ty: Type,
161-
padding: Option<Type>,
162-
coerce: bool) -> Type {
155+
fn struct_ty(ty: Type) -> Type {
163156
let size = ty_size(ty) * 8;
164-
let mut fields = padding.map_default(~[], |p| ~[p]);
165-
166-
if coerce {
167-
fields = vec::append(fields, coerce_to_int(size));
168-
} else {
169-
fields.push(ty);
170-
}
171-
157+
let fields = coerce_to_int(size);
172158
return Type::struct_(fields, false);
173159
}
174160

175161
pub fn compute_abi_info(_ccx: &mut CrateContext,
176162
atys: &[Type],
177163
rty: Type,
178164
ret_def: bool) -> FnType {
179-
let (ret_ty, ret_attr) = if ret_def {
165+
let ret_ty = if ret_def {
180166
classify_ret_ty(rty)
181167
} else {
182-
(LLVMType { cast: false, ty: Type::void() }, None)
168+
ArgType::direct(Type::void(), None, None, None)
183169
};
184170

185-
let mut ret_ty = ret_ty;
186-
187-
let sret = ret_attr.is_some();
171+
let sret = ret_ty.is_indirect();
188172
let mut arg_tys = ~[];
189-
let mut attrs = ~[];
190173
let mut offset = if sret { 4 } else { 0 };
191174

192175
for aty in atys.iter() {
193-
let (ty, attr) = classify_arg_ty(*aty, &mut offset);
176+
let ty = classify_arg_ty(*aty, &mut offset);
194177
arg_tys.push(ty);
195-
attrs.push(attr);
196178
};
197179

198-
if sret {
199-
arg_tys = vec::append(~[ret_ty], arg_tys);
200-
attrs = vec::append(~[ret_attr], attrs);
201-
ret_ty = LLVMType { cast: false, ty: Type::void() };
202-
}
203-
204180
return FnType {
205181
arg_tys: arg_tys,
206182
ret_ty: ret_ty,
207-
attrs: attrs,
208-
sret: sret
209183
};
210184
}

src/librustc/middle/trans/cabi_x86.rs

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,10 @@ pub fn compute_abi_info(ccx: &mut CrateContext,
2121
rty: Type,
2222
ret_def: bool) -> FnType {
2323
let mut arg_tys = ~[];
24-
let mut attrs = ~[];
2524

2625
let ret_ty;
27-
let sret;
2826
if !ret_def {
29-
ret_ty = LLVMType {
30-
cast: false,
31-
ty: Type::void(),
32-
};
33-
sret = false;
27+
ret_ty = ArgType::direct(Type::void(), None, None, None);
3428
} else if rty.kind() == Struct {
3529
// Returning a structure. Most often, this will use
3630
// a hidden first argument. On some platforms, though,
@@ -58,43 +52,22 @@ pub fn compute_abi_info(ccx: &mut CrateContext,
5852

5953
match strategy {
6054
RetValue(t) => {
61-
ret_ty = LLVMType {
62-
cast: true,
63-
ty: t
64-
};
65-
sret = false;
55+
ret_ty = ArgType::direct(rty, Some(t), None, None);
6656
}
6757
RetPointer => {
68-
arg_tys.push(LLVMType {
69-
cast: false,
70-
ty: rty.ptr_to()
71-
});
72-
attrs.push(Some(StructRetAttribute));
73-
74-
ret_ty = LLVMType {
75-
cast: false,
76-
ty: Type::void(),
77-
};
78-
sret = true;
58+
ret_ty = ArgType::indirect(rty, Some(StructRetAttribute));
7959
}
8060
}
8161
} else {
82-
ret_ty = LLVMType {
83-
cast: false,
84-
ty: rty
85-
};
86-
sret = false;
62+
ret_ty = ArgType::direct(rty, None, None, None);
8763
}
8864

8965
for &a in atys.iter() {
90-
arg_tys.push(LLVMType { cast: false, ty: a });
91-
attrs.push(None);
66+
arg_tys.push(ArgType::direct(a, None, None, None));
9267
}
9368

9469
return FnType {
9570
arg_tys: arg_tys,
9671
ret_ty: ret_ty,
97-
attrs: attrs,
98-
sret: sret
9972
};
10073
}

0 commit comments

Comments
 (0)