Mercurial > projects > ldc
comparison gen/abi.cpp @ 1024:9167d492cbc2
Abstracted more (most) ABI details out of the normal codegen.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 03 Mar 2009 02:51:21 +0100 |
parents | e8c6dbcd33d1 |
children | 0477f98d357e |
comparison
equal
deleted
inserted
replaced
1023:ca191c141cec | 1024:9167d492cbc2 |
---|---|
1 #include "gen/llvm.h" | 1 #include "gen/llvm.h" |
2 | |
3 #include <algorithm> | |
2 | 4 |
3 #include "mars.h" | 5 #include "mars.h" |
4 | 6 |
5 #include "gen/irstate.h" | 7 #include "gen/irstate.h" |
6 #include "gen/llvmhelpers.h" | 8 #include "gen/llvmhelpers.h" |
7 #include "gen/tollvm.h" | 9 #include "gen/tollvm.h" |
8 #include "gen/abi.h" | 10 #include "gen/abi.h" |
9 #include "gen/logger.h" | 11 #include "gen/logger.h" |
10 | 12 |
11 ////////////////////////////////////////////////////////////////////////////// | 13 #include "ir/irfunction.h" |
12 ////////////////////////////////////////////////////////////////////////////// | |
13 ///////////////////// baseclass //////////////////////////// | |
14 ////////////////////////////////////////////////////////////////////////////// | |
15 ////////////////////////////////////////////////////////////////////////////// | |
16 | |
17 // FIXME: Would be nice to come up a better and faster way to do this, right | |
18 // now I'm more worried about actually making this abstraction work at all ... | |
19 // It's definitely way overkill with the amount of return value rewrites we | |
20 // have right now, but I expect this to change with proper x86-64 abi support | |
21 | |
22 TargetABI::TargetABI() | |
23 { | |
24 } | |
25 | |
26 llvm::Value* TargetABI::getRet(TypeFunction* tf, llvm::Value* io) | |
27 { | |
28 if (ABIRetRewrite* r = findRetRewrite(tf)) | |
29 { | |
30 return r->get(io); | |
31 } | |
32 return io; | |
33 } | |
34 | |
35 llvm::Value* TargetABI::putRet(TypeFunction* tf, llvm::Value* io) | |
36 { | |
37 if (ABIRetRewrite* r = findRetRewrite(tf)) | |
38 { | |
39 return r->put(io); | |
40 } | |
41 return io; | |
42 } | |
43 | |
44 const llvm::Type* TargetABI::getRetType(TypeFunction* tf, const llvm::Type* t) | |
45 { | |
46 if (ABIRetRewrite* r = findRetRewrite(tf)) | |
47 { | |
48 return r->type(t); | |
49 } | |
50 return t; | |
51 } | |
52 | |
53 ABIRetRewrite * TargetABI::findRetRewrite(TypeFunction * tf) | |
54 { | |
55 size_t n = retOps.size(); | |
56 if (n) | |
57 for (size_t i = 0; i < n; i++) | |
58 { | |
59 if (retOps[i]->test(tf)) | |
60 return retOps[i]; | |
61 } | |
62 return NULL; | |
63 } | |
64 | 14 |
65 ////////////////////////////////////////////////////////////////////////////// | 15 ////////////////////////////////////////////////////////////////////////////// |
66 ////////////////////////////////////////////////////////////////////////////// | 16 ////////////////////////////////////////////////////////////////////////////// |
67 ///////////////////// X86 //////////////////////////// | 17 ///////////////////// X86 //////////////////////////// |
68 ////////////////////////////////////////////////////////////////////////////// | 18 ////////////////////////////////////////////////////////////////////////////// |
69 ////////////////////////////////////////////////////////////////////////////// | 19 ////////////////////////////////////////////////////////////////////////////// |
70 | 20 |
71 // simply swap of real/imag parts for proper x87 complex abi | 21 // simply swap of real/imag parts for proper x87 complex abi |
72 struct X87_complex_swap : ABIRetRewrite | 22 struct X87_complex_swap : ABIRewrite |
73 { | 23 { |
74 LLValue* get(LLValue* v) | 24 LLValue* get(Type*, LLValue* v) |
75 { | 25 { |
76 return DtoAggrPairSwap(v); | 26 return DtoAggrPairSwap(v); |
77 } | 27 } |
78 LLValue* put(LLValue* v) | 28 LLValue* put(Type*, LLValue* v) |
79 { | 29 { |
80 return DtoAggrPairSwap(v); | 30 return DtoAggrPairSwap(v); |
81 } | 31 } |
82 const LLType* type(const LLType* t) | 32 const LLType* type(Type*, const LLType* t) |
83 { | 33 { |
84 return t; | 34 return t; |
85 } | 35 } |
86 bool test(TypeFunction* tf) | 36 }; |
87 { | 37 |
88 // extern(D) && is(T:creal) | 38 ////////////////////////////////////////////////////////////////////////////// |
89 return (tf->linkage == LINKd && tf->next->toBasetype()->iscomplex()); | 39 |
90 } | 40 struct X86_cfloat_rewrite : ABIRewrite |
91 }; | |
92 | |
93 ////////////////////////////////////////////////////////////////////////////// | |
94 | |
95 struct X86_cfloat_rewrite : ABIRetRewrite | |
96 { | 41 { |
97 // i64 -> {float,float} | 42 // i64 -> {float,float} |
98 LLValue* get(LLValue* in) | 43 LLValue* get(Type*, LLValue* in) |
99 { | 44 { |
100 // extract real part | 45 // extract real part |
101 LLValue* rpart = gIR->ir->CreateTrunc(in, LLType::Int32Ty); | 46 LLValue* rpart = gIR->ir->CreateTrunc(in, LLType::Int32Ty); |
102 rpart = gIR->ir->CreateBitCast(rpart, LLType::FloatTy, ".re"); | 47 rpart = gIR->ir->CreateBitCast(rpart, LLType::FloatTy, ".re"); |
103 | 48 |
109 // return {float,float} aggr pair with same bits | 54 // return {float,float} aggr pair with same bits |
110 return DtoAggrPair(rpart, ipart, ".final_cfloat"); | 55 return DtoAggrPair(rpart, ipart, ".final_cfloat"); |
111 } | 56 } |
112 | 57 |
113 // {float,float} -> i64 | 58 // {float,float} -> i64 |
114 LLValue* put(LLValue* v) | 59 LLValue* put(Type*, LLValue* v) |
115 { | 60 { |
116 // extract real | 61 // extract real |
117 LLValue* r = gIR->ir->CreateExtractValue(v, 0); | 62 LLValue* r = gIR->ir->CreateExtractValue(v, 0); |
118 // cast to i32 | 63 // cast to i32 |
119 r = gIR->ir->CreateBitCast(r, LLType::Int32Ty); | 64 r = gIR->ir->CreateBitCast(r, LLType::Int32Ty); |
132 // combine and return | 77 // combine and return |
133 return v = gIR->ir->CreateOr(r, i); | 78 return v = gIR->ir->CreateOr(r, i); |
134 } | 79 } |
135 | 80 |
136 // {float,float} -> i64 | 81 // {float,float} -> i64 |
137 const LLType* type(const LLType* t) | 82 const LLType* type(Type*, const LLType* t) |
138 { | 83 { |
139 return LLType::Int64Ty; | 84 return LLType::Int64Ty; |
140 } | 85 } |
141 | 86 }; |
142 // test if rewrite applies to function | 87 |
143 bool test(TypeFunction* tf) | 88 ////////////////////////////////////////////////////////////////////////////// |
144 { | 89 |
145 return (tf->linkage != LINKd) | 90 // FIXME: try into eliminating the alloca or if at least check |
146 && (tf->next->toBasetype() == Type::tcomplex32); | 91 // if it gets optimized away |
92 | |
93 // convert byval struct | |
94 // when | |
95 struct X86_struct_to_register : ABIRewrite | |
96 { | |
97 // int -> struct | |
98 LLValue* get(Type* dty, LLValue* v) | |
99 { | |
100 Logger::println("rewriting int -> struct"); | |
101 LLValue* mem = DtoAlloca(DtoType(dty), ".int_to_struct"); | |
102 DtoStore(v, DtoBitCast(mem, getPtrToType(v->getType()))); | |
103 return DtoLoad(mem); | |
104 } | |
105 // struct -> int | |
106 LLValue* put(Type* dty, LLValue* v) | |
107 { | |
108 Logger::println("rewriting struct -> int"); | |
109 LLValue* mem = DtoAlloca(v->getType(), ".struct_to_int"); | |
110 DtoStore(v, mem); | |
111 DtoLoad(DtoBitCast(mem, getPtrToType(type(dty, v->getType())))); | |
112 } | |
113 const LLType* type(Type*, const LLType* t) | |
114 { | |
115 size_t sz = getTypePaddedSize(t)*8; | |
116 return LLIntegerType::get(sz); | |
147 } | 117 } |
148 }; | 118 }; |
149 | 119 |
150 ////////////////////////////////////////////////////////////////////////////// | 120 ////////////////////////////////////////////////////////////////////////////// |
151 | 121 |
152 struct X86TargetABI : TargetABI | 122 struct X86TargetABI : TargetABI |
153 { | 123 { |
154 X86TargetABI() | 124 X87_complex_swap swapComplex; |
155 { | 125 X86_cfloat_rewrite cfloatToInt; |
156 retOps.push_back(new X87_complex_swap); | 126 X86_struct_to_register structToReg; |
157 retOps.push_back(new X86_cfloat_rewrite); | |
158 } | |
159 | 127 |
160 bool returnInArg(TypeFunction* tf) | 128 bool returnInArg(TypeFunction* tf) |
161 { | 129 { |
162 Type* rt = tf->next->toBasetype(); | 130 Type* rt = tf->next->toBasetype(); |
163 // D only returns structs on the stack | 131 // D only returns structs on the stack |
166 // other ABI's follow C, which is cdouble and creal returned on the stack | 134 // other ABI's follow C, which is cdouble and creal returned on the stack |
167 // as well as structs | 135 // as well as structs |
168 else | 136 else |
169 return (rt->ty == Tstruct || rt->ty == Tcomplex64 || rt->ty == Tcomplex80); | 137 return (rt->ty == Tstruct || rt->ty == Tcomplex64 || rt->ty == Tcomplex80); |
170 } | 138 } |
139 | |
140 bool passByVal(Type* t) | |
141 { | |
142 return t->toBasetype()->ty == Tstruct; | |
143 } | |
144 | |
145 void rewriteFunctionType(TypeFunction* tf) | |
146 { | |
147 IrFuncTy* fty = tf->fty; | |
148 Type* rt = fty->ret->type->toBasetype(); | |
149 | |
150 // extern(D) | |
151 if (tf->linkage == LINKd) | |
152 { | |
153 // RETURN VALUE | |
154 | |
155 // complex {re,im} -> {im,re} | |
156 if (rt->iscomplex()) | |
157 { | |
158 fty->ret->rewrite = &swapComplex; | |
159 } | |
160 | |
161 // IMPLICIT PARAMETERS | |
162 | |
163 // mark this/nested params inreg | |
164 if (fty->arg_this) | |
165 { | |
166 fty->arg_this->attrs = llvm::Attribute::InReg; | |
167 } | |
168 else if (fty->arg_nest) | |
169 { | |
170 fty->arg_nest->attrs = llvm::Attribute::InReg; | |
171 } | |
172 // otherwise try to mark the last param inreg | |
173 else if (!fty->arg_sret && !fty->args.empty()) | |
174 { | |
175 // The last parameter is passed in EAX rather than being pushed on the stack if the following conditions are met: | |
176 // * It fits in EAX. | |
177 // * It is not a 3 byte struct. | |
178 // * It is not a floating point type. | |
179 | |
180 IrFuncTyArg* last = fty->args.back(); | |
181 Type* lastTy = last->type->toBasetype(); | |
182 unsigned sz = lastTy->size(); | |
183 | |
184 if (last->byref && !last->isByVal()) | |
185 { | |
186 last->attrs = llvm::Attribute::InReg; | |
187 } | |
188 else if (!lastTy->isfloating() && (sz == 1 || sz == 2 || sz == 4)) // right? | |
189 { | |
190 // rewrite the struct into an integer to make inreg work | |
191 if (lastTy->ty == Tstruct) | |
192 { | |
193 last->rewrite = &structToReg; | |
194 last->ltype = structToReg.type(last->type, last->ltype); | |
195 last->byref = false; | |
196 } | |
197 last->attrs = llvm::Attribute::InReg; | |
198 } | |
199 } | |
200 | |
201 // FIXME: tf->varargs == 1 need to use C calling convention and vararg mechanism to live up to the spec: | |
202 // "The caller is expected to clean the stack. _argptr is not passed, it is computed by the callee." | |
203 | |
204 // EXPLICIT PARAMETERS | |
205 | |
206 // reverse parameter order | |
207 // for non variadics | |
208 if (!fty->args.empty() && tf->varargs != 1) | |
209 { | |
210 fty->reverseParams = true; | |
211 } | |
212 } | |
213 | |
214 // extern(C) and all others | |
215 else | |
216 { | |
217 // RETURN VALUE | |
218 | |
219 // cfloat -> i64 | |
220 if (tf->next->toBasetype() == Type::tcomplex32) | |
221 { | |
222 fty->ret->rewrite = &cfloatToInt; | |
223 fty->ret->ltype = LLType::Int64Ty; | |
224 } | |
225 | |
226 // IMPLICIT PARAMETERS | |
227 | |
228 // EXPLICIT PARAMETERS | |
229 } | |
230 } | |
171 }; | 231 }; |
172 | 232 |
173 ////////////////////////////////////////////////////////////////////////////// | 233 ////////////////////////////////////////////////////////////////////////////// |
174 ////////////////////////////////////////////////////////////////////////////// | 234 ////////////////////////////////////////////////////////////////////////////// |
175 /////////////////// X86-64 ////////////////////////// | 235 /////////////////// X86-64 ////////////////////////// |
176 ////////////////////////////////////////////////////////////////////////////// | 236 ////////////////////////////////////////////////////////////////////////////// |
177 ////////////////////////////////////////////////////////////////////////////// | 237 ////////////////////////////////////////////////////////////////////////////// |
178 | 238 |
179 struct X86_64_cfloat_rewrite : ABIRetRewrite | 239 struct X86_64_cfloat_rewrite : ABIRewrite |
180 { | 240 { |
181 // {double} -> {float,float} | 241 // {double} -> {float,float} |
182 LLValue* get(LLValue* in) | 242 LLValue* get(Type*, LLValue* in) |
183 { | 243 { |
184 // extract double | 244 // extract double |
185 LLValue* v = gIR->ir->CreateExtractValue(in, 0); | 245 LLValue* v = gIR->ir->CreateExtractValue(in, 0); |
186 // cast to i64 | 246 // cast to i64 |
187 v = gIR->ir->CreateBitCast(v, LLType::Int64Ty); | 247 v = gIR->ir->CreateBitCast(v, LLType::Int64Ty); |
198 // return {float,float} aggr pair with same bits | 258 // return {float,float} aggr pair with same bits |
199 return DtoAggrPair(rpart, ipart, ".final_cfloat"); | 259 return DtoAggrPair(rpart, ipart, ".final_cfloat"); |
200 } | 260 } |
201 | 261 |
202 // {float,float} -> {double} | 262 // {float,float} -> {double} |
203 LLValue* put(LLValue* v) | 263 LLValue* put(Type*, LLValue* v) |
204 { | 264 { |
205 // extract real | 265 // extract real |
206 LLValue* r = gIR->ir->CreateExtractValue(v, 0); | 266 LLValue* r = gIR->ir->CreateExtractValue(v, 0); |
207 // cast to i32 | 267 // cast to i32 |
208 r = gIR->ir->CreateBitCast(r, LLType::Int32Ty); | 268 r = gIR->ir->CreateBitCast(r, LLType::Int32Ty); |
229 LLValue* undef = llvm::UndefValue::get(t); | 289 LLValue* undef = llvm::UndefValue::get(t); |
230 return gIR->ir->CreateInsertValue(undef, v, 0); | 290 return gIR->ir->CreateInsertValue(undef, v, 0); |
231 } | 291 } |
232 | 292 |
233 // {float,float} -> {double} | 293 // {float,float} -> {double} |
234 const LLType* type(const LLType* t) | 294 const LLType* type(Type*, const LLType* t) |
235 { | 295 { |
236 return LLStructType::get(LLType::DoubleTy, NULL); | 296 return LLStructType::get(LLType::DoubleTy, NULL); |
237 } | 297 } |
238 | |
239 // test if rewrite applies to function | |
240 bool test(TypeFunction* tf) | |
241 { | |
242 return (tf->linkage != LINKd) | |
243 && (tf->next->toBasetype() == Type::tcomplex32); | |
244 } | |
245 }; | 298 }; |
246 | 299 |
247 ////////////////////////////////////////////////////////////////////////////// | 300 ////////////////////////////////////////////////////////////////////////////// |
248 | 301 |
249 struct X86_64TargetABI : TargetABI | 302 struct X86_64TargetABI : TargetABI |
250 { | 303 { |
251 X86_64TargetABI() | 304 X86_64_cfloat_rewrite cfloat_rewrite; |
252 { | |
253 retOps.push_back(new X86_64_cfloat_rewrite); | |
254 } | |
255 | 305 |
256 bool returnInArg(TypeFunction* tf) | 306 bool returnInArg(TypeFunction* tf) |
257 { | 307 { |
258 Type* rt = tf->next->toBasetype(); | 308 Type* rt = tf->next->toBasetype(); |
259 return (rt->ty == Tstruct); | 309 return (rt->ty == Tstruct); |
260 } | 310 } |
311 | |
312 bool passByVal(Type* t) | |
313 { | |
314 return t->toBasetype()->ty == Tstruct; | |
315 } | |
316 | |
317 void rewriteFunctionType(TypeFunction* tf) | |
318 { | |
319 IrFuncTy* fty = tf->fty; | |
320 Type* rt = fty->ret->type->toBasetype(); | |
321 | |
322 // rewrite cfloat return for !extern(D) | |
323 if (tf->linkage != LINKd && rt == Type::tcomplex32) | |
324 { | |
325 fty->ret->rewrite = &cfloat_rewrite; | |
326 fty->ret->ltype = cfloat_rewrite.type(fty->ret->type, fty->ret->ltype); | |
327 } | |
328 } | |
261 }; | 329 }; |
262 | 330 |
263 ////////////////////////////////////////////////////////////////////////////// | 331 ////////////////////////////////////////////////////////////////////////////// |
264 ////////////////////////////////////////////////////////////////////////////// | 332 ////////////////////////////////////////////////////////////////////////////// |
265 /////////////////// Unknown targets ////////////////////////// | 333 /////////////////// Unknown targets ////////////////////////// |
267 ////////////////////////////////////////////////////////////////////////////// | 335 ////////////////////////////////////////////////////////////////////////////// |
268 | 336 |
269 // Some reasonable defaults for when we don't know what ABI to use. | 337 // Some reasonable defaults for when we don't know what ABI to use. |
270 struct UnknownTargetABI : TargetABI | 338 struct UnknownTargetABI : TargetABI |
271 { | 339 { |
272 UnknownTargetABI() | |
273 { | |
274 // Don't push anything into retOps, assume defaults will be fine. | |
275 } | |
276 | |
277 bool returnInArg(TypeFunction* tf) | 340 bool returnInArg(TypeFunction* tf) |
278 { | 341 { |
279 Type* rt = tf->next->toBasetype(); | 342 return (tf->next->toBasetype()->ty == Tstruct); |
280 return (rt->ty == Tstruct); | 343 } |
344 | |
345 bool passByVal(Type* t) | |
346 { | |
347 return t->toBasetype()->ty == Tstruct; | |
348 } | |
349 | |
350 void rewriteFunctionType(TypeFunction* t) | |
351 { | |
352 // why? | |
281 } | 353 } |
282 }; | 354 }; |
283 | 355 |
284 ////////////////////////////////////////////////////////////////////////////// | 356 ////////////////////////////////////////////////////////////////////////////// |
285 ////////////////////////////////////////////////////////////////////////////// | 357 ////////////////////////////////////////////////////////////////////////////// |