Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/gen/abi.cpp

Revision 1571:8d086d552909, 12.6 kB (checked in by Benjamin Kramer <benny.kra@gmail.com>, 3 years ago)

IntegerType? is now contextifed.

Requires llvm >= 78969. resistor says this will be the last context API change :)

Line 
1 #include "gen/llvm.h"
2
3 #include <algorithm>
4
5 #include "mars.h"
6
7 #include "gen/irstate.h"
8 #include "gen/llvmhelpers.h"
9 #include "gen/tollvm.h"
10 #include "gen/abi.h"
11 #include "gen/logger.h"
12 #include "gen/dvalue.h"
13 #include "gen/abi-generic.h"
14
15 #include "ir/irfunction.h"
16
17 //////////////////////////////////////////////////////////////////////////////
18
19 void ABIRewrite::getL(Type* dty, DValue* v, llvm::Value* lval)
20 {
21     LLValue* rval = get(dty, v);
22     assert(rval->getType() == lval->getType()->getContainedType(0));
23     DtoStore(rval, lval);
24 }
25
26 //////////////////////////////////////////////////////////////////////////////
27 //////////////////////////////////////////////////////////////////////////////
28 /////////////////////              X86            ////////////////////////////
29 //////////////////////////////////////////////////////////////////////////////
30 //////////////////////////////////////////////////////////////////////////////
31
32 // simply swap of real/imag parts for proper x87 complex abi
33 struct X87_complex_swap : ABIRewrite
34 {
35     LLValue* get(Type*, DValue* v)
36     {
37         return DtoAggrPairSwap(v->getRVal());
38     }
39     LLValue* put(Type*, DValue* v)
40     {
41         return DtoAggrPairSwap(v->getRVal());
42     }
43     const LLType* type(Type*, const LLType* t)
44     {
45         return t;
46     }
47 };
48
49 //////////////////////////////////////////////////////////////////////////////
50
51 struct X86_cfloat_rewrite : ABIRewrite
52 {
53     // i64 -> {float,float}
54     LLValue* get(Type*, DValue* dv)
55     {
56         LLValue* in = dv->getRVal();
57
58         // extract real part
59         LLValue* rpart = gIR->ir->CreateTrunc(in, LLType::getInt32Ty(gIR->context()));
60         rpart = gIR->ir->CreateBitCast(rpart, LLType::getFloatTy(gIR->context()), ".re");
61
62         // extract imag part
63         LLValue* ipart = gIR->ir->CreateLShr(in, LLConstantInt::get(LLType::getInt64Ty(gIR->context()), 32, false));
64         ipart = gIR->ir->CreateTrunc(ipart, LLType::getInt32Ty(gIR->context()));
65         ipart = gIR->ir->CreateBitCast(ipart, LLType::getFloatTy(gIR->context()), ".im");
66
67         // return {float,float} aggr pair with same bits
68         return DtoAggrPair(rpart, ipart, ".final_cfloat");
69     }
70
71     // {float,float} -> i64
72     LLValue* put(Type*, DValue* dv)
73     {
74         LLValue* v = dv->getRVal();
75
76         // extract real
77         LLValue* r = gIR->ir->CreateExtractValue(v, 0);
78         // cast to i32
79         r = gIR->ir->CreateBitCast(r, LLType::getInt32Ty(gIR->context()));
80         // zext to i64
81         r = gIR->ir->CreateZExt(r, LLType::getInt64Ty(gIR->context()));
82
83         // extract imag
84         LLValue* i = gIR->ir->CreateExtractValue(v, 1);
85         // cast to i32
86         i = gIR->ir->CreateBitCast(i, LLType::getInt32Ty(gIR->context()));
87         // zext to i64
88         i = gIR->ir->CreateZExt(i, LLType::getInt64Ty(gIR->context()));
89         // shift up
90         i = gIR->ir->CreateShl(i, LLConstantInt::get(LLType::getInt64Ty(gIR->context()), 32, false));
91
92         // combine and return
93         return v = gIR->ir->CreateOr(r, i);
94     }
95
96     // {float,float} -> i64
97     const LLType* type(Type*, const LLType* t)
98     {
99         return LLType::getInt64Ty(gIR->context());
100     }
101 };
102
103 //////////////////////////////////////////////////////////////////////////////
104
105 // FIXME: try into eliminating the alloca or if at least check
106 // if it gets optimized away
107
108 // convert byval struct
109 // when
110 struct X86_struct_to_register : ABIRewrite
111 {
112     // int -> struct
113     LLValue* get(Type* dty, DValue* dv)
114     {
115         Logger::println("rewriting int -> struct");
116         LLValue* mem = DtoAlloca(dty, ".int_to_struct");
117         LLValue* v = dv->getRVal();
118         DtoStore(v, DtoBitCast(mem, getPtrToType(v->getType())));
119         return DtoLoad(mem);
120     }
121     // int -> struct (with dst lvalue given)
122     void getL(Type* dty, DValue* dv, llvm::Value* lval)
123     {
124         Logger::println("rewriting int -> struct");
125         LLValue* v = dv->getRVal();
126         DtoStore(v, DtoBitCast(lval, getPtrToType(v->getType())));
127     }
128     // struct -> int
129     LLValue* put(Type* dty, DValue* dv)
130     {
131         Logger::println("rewriting struct -> int");
132         assert(dv->isLVal());
133         LLValue* mem = dv->getLVal();
134         const LLType* t = LLIntegerType::get(gIR->context(), dty->size()*8);
135         return DtoLoad(DtoBitCast(mem, getPtrToType(t)));
136     }
137     const LLType* type(Type* t, const LLType*)
138     {
139         size_t sz = t->size()*8;
140         return LLIntegerType::get(gIR->context(), sz);
141     }
142 };
143
144 //////////////////////////////////////////////////////////////////////////////
145
146 struct X86TargetABI : TargetABI
147 {
148     X87_complex_swap swapComplex;
149     X86_cfloat_rewrite cfloatToInt;
150     X86_struct_to_register structToReg;
151
152     bool returnInArg(TypeFunction* tf)
153     {
154         Type* rt = tf->next->toBasetype();
155         // D only returns structs on the stack
156         if (tf->linkage == LINKd)
157             return (rt->ty == Tstruct);
158         // other ABI's follow C, which is cdouble and creal returned on the stack
159         // as well as structs
160         else
161             return (rt->ty == Tstruct || rt->ty == Tcomplex64 || rt->ty == Tcomplex80);
162     }
163
164     bool passByVal(Type* t)
165     {
166         return t->toBasetype()->ty == Tstruct;
167     }
168
169     void rewriteFunctionType(TypeFunction* tf)
170     {
171         IrFuncTy& fty = tf->fty;
172         Type* rt = fty.ret->type->toBasetype();
173
174         // extern(D)
175         if (tf->linkage == LINKd)
176         {
177             // RETURN VALUE
178
179             // complex {re,im} -> {im,re}
180             if (rt->iscomplex())
181             {
182                 Logger::println("Rewriting complex return value");
183                 fty.ret->rewrite = &swapComplex;
184             }
185
186             // IMPLICIT PARAMETERS
187
188             // mark this/nested params inreg
189             if (fty.arg_this)
190             {
191                 Logger::println("Putting 'this' in register");
192                 fty.arg_this->attrs = llvm::Attribute::InReg;
193             }
194             else if (fty.arg_nest)
195             {
196                 Logger::println("Putting context ptr in register");
197                 fty.arg_nest->attrs = llvm::Attribute::InReg;
198             }
199             else if (IrFuncTyArg* sret = fty.arg_sret)
200             {
201                 Logger::println("Putting sret ptr in register");
202                 // sret and inreg are incompatible, but the ABI requires the
203                 // sret parameter to be in EAX in this situation...
204                 sret->attrs = (sret->attrs | llvm::Attribute::InReg)
205                                 & ~llvm::Attribute::StructRet;
206             }
207             // otherwise try to mark the last param inreg
208             else if (!fty.args.empty())
209             {
210                 // The last parameter is passed in EAX rather than being pushed on the stack if the following conditions are met:
211                 //   * It fits in EAX.
212                 //   * It is not a 3 byte struct.
213                 //   * It is not a floating point type.
214
215                 IrFuncTyArg* last = fty.args.back();
216                 Type* lastTy = last->type->toBasetype();
217                 unsigned sz = lastTy->size();
218
219                 if (last->byref && !last->isByVal())
220                 {
221                     Logger::println("Putting last (byref) parameter in register");
222                     last->attrs |= llvm::Attribute::InReg;
223                 }
224                 else if (!lastTy->isfloating() && (sz == 1 || sz == 2 || sz == 4)) // right?
225                 {
226                     // rewrite the struct into an integer to make inreg work
227                     if (lastTy->ty == Tstruct)
228                     {
229                         last->rewrite = &structToReg;
230                         last->ltype = structToReg.type(last->type, last->ltype);
231                         last->byref = false;
232                         // erase previous attributes
233                         last->attrs = 0;
234                     }
235                     last->attrs |= llvm::Attribute::InReg;
236                 }
237             }
238
239             // FIXME: tf->varargs == 1 need to use C calling convention and vararg mechanism to live up to the spec:
240             // "The caller is expected to clean the stack. _argptr is not passed, it is computed by the callee."
241
242             // EXPLICIT PARAMETERS
243
244             // reverse parameter order
245             // for non variadics
246             if (!fty.args.empty() && tf->varargs != 1)
247             {
248                 fty.reverseParams = true;
249             }
250         }
251
252         // extern(C) and all others
253         else
254         {
255             // RETURN VALUE
256
257             // cfloat -> i64
258             if (tf->next->toBasetype() == Type::tcomplex32)
259             {
260                 fty.ret->rewrite = &cfloatToInt;
261                 fty.ret->ltype = LLType::getInt64Ty(gIR->context());
262             }
263
264             // IMPLICIT PARAMETERS
265
266             // EXPLICIT PARAMETERS
267         }
268     }
269 };
270
271 //////////////////////////////////////////////////////////////////////////////
272 //////////////////////////////////////////////////////////////////////////////
273 ///////////////////            X86-64               //////////////////////////
274 //////////////////////////////////////////////////////////////////////////////
275 //////////////////////////////////////////////////////////////////////////////
276
277 #include "gen/abi-x86-64.h"
278
279 //////////////////////////////////////////////////////////////////////////////
280 //////////////////////////////////////////////////////////////////////////////
281 ///////////////////         Unknown targets         //////////////////////////
282 //////////////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////////////
284
285 // Some reasonable defaults for when we don't know what ABI to use.
286 struct UnknownTargetABI : TargetABI
287 {
288     bool returnInArg(TypeFunction* tf)
289     {
290         return (tf->next->toBasetype()->ty == Tstruct);
291     }
292
293     bool passByVal(Type* t)
294     {
295         return t->toBasetype()->ty == Tstruct;
296     }
297
298     void rewriteFunctionType(TypeFunction* t)
299     {
300         // why?
301     }
302 };
303
304 //////////////////////////////////////////////////////////////////////////////
305 //////////////////////////////////////////////////////////////////////////////
306 //////////////////////////////////////////////////////////////////////////////
307 //////////////////////////////////////////////////////////////////////////////
308 //////////////////////////////////////////////////////////////////////////////
309
310 TargetABI * TargetABI::getTarget()
311 {
312     switch(global.params.cpu)
313     {
314     case ARCHx86:
315         return new X86TargetABI;
316     case ARCHx86_64:
317         return getX86_64TargetABI();
318     default:
319         Logger::cout() << "WARNING: Unknown ABI, guessing...\n";
320         return new UnknownTargetABI;
321     }
322 }
323
324 //////////////////////////////////////////////////////////////////////////////
325 //////////////////////////////////////////////////////////////////////////////
326 //////////////////////////////////////////////////////////////////////////////
327 //////////////////////////////////////////////////////////////////////////////
328 //////////////////////////////////////////////////////////////////////////////
329
330 // A simple ABI for LLVM intrinsics.
331 struct IntrinsicABI : TargetABI
332 {
333     RemoveStructPadding remove_padding;
334
335     bool returnInArg(TypeFunction* tf)
336     {
337         return false;
338     }
339
340     bool passByVal(Type* t)
341     {
342         return false;
343     }
344
345     void fixup(IrFuncTyArg& arg) {
346         assert(arg.type->ty == Tstruct);
347         // TODO: Check that no unions are passed in or returned.
348
349         LLType* abiTy = DtoUnpaddedStructType(arg.type);
350
351         if (abiTy && abiTy != arg.ltype) {
352             arg.ltype = abiTy;
353             arg.rewrite = &remove_padding;
354         }
355     }
356
357     void rewriteFunctionType(TypeFunction* tf)
358     {
359         assert(tf->linkage == LINKintrinsic);
360
361         IrFuncTy& fty = tf->fty;
362
363         if (!fty.arg_sret) {
364             Type* rt = fty.ret->type->toBasetype();
365             if (rt->ty == Tstruct)  {
366                 Logger::println("Intrinsic ABI: Transforming return type");
367                 fixup(*fty.ret);
368             }
369         }
370
371         Logger::println("Intrinsic ABI: Transforming arguments");
372         LOG_SCOPE;
373
374         for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) {
375             IrFuncTyArg& arg = **I;
376
377             if (Logger::enabled())
378                 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
379
380             // Arguments that are in memory are of no interest to us.
381             if (arg.byref)
382                 continue;
383
384             Type* ty = arg.type->toBasetype();
385             if (ty->ty == Tstruct)
386                 fixup(arg);
387
388             if (Logger::enabled())
389                 Logger::cout() << "New arg type: " << *arg.ltype << '\n';
390         }
391     }
392 };
393
394 TargetABI * TargetABI::getIntrinsic()
395 {
396     static IntrinsicABI iabi;
397     return &iabi;
398 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.