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

root/gen/tocall.cpp

Revision 1650:40bd4a0d4870, 19.5 kB (checked in by Tomas Lindquist Olsen, 2 years ago)

Update to work with LLVM 2.7.

Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).

Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.

Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.

Line 
1 #include "gen/llvm.h"
2
3 #include "mtype.h"
4 #include "declaration.h"
5
6 #include "gen/tollvm.h"
7 #include "gen/llvmhelpers.h"
8 #include "gen/irstate.h"
9 #include "gen/dvalue.h"
10 #include "gen/functions.h"
11 #include "gen/abi.h"
12 #include "gen/nested.h"
13
14 #include "gen/logger.h"
15
16 //////////////////////////////////////////////////////////////////////////////////////////
17
18 TypeFunction* DtoTypeFunction(DValue* fnval)
19 {
20     Type* type = fnval->getType()->toBasetype();
21     if (type->ty == Tfunction)
22     {
23          return (TypeFunction*)type;
24     }
25     else if (type->ty == Tdelegate)
26     {
27         Type* next = type->nextOf();
28         assert(next->ty == Tfunction);
29         return (TypeFunction*)next;
30     }
31
32     assert(0 && "cant get TypeFunction* from non lazy/function/delegate");
33     return 0;
34 }
35
36 //////////////////////////////////////////////////////////////////////////////////////////
37
38 llvm::CallingConv::ID DtoCallingConv(Loc loc, LINK l)
39 {
40     if (l == LINKc || l == LINKcpp || l == LINKintrinsic)
41         return llvm::CallingConv::C;
42     else if (l == LINKd || l == LINKdefault)
43     {
44         //TODO: StdCall is not a good base on Windows due to extra name mangling
45         // applied there
46         if (global.params.cpu == ARCHx86)
47             return (global.params.os != OSWindows) ? llvm::CallingConv::X86_StdCall : llvm::CallingConv::C;
48         else
49             return llvm::CallingConv::Fast;
50     }
51     // on the other hand, here, it's exactly what we want!!! TODO: right?
52     else if (l == LINKwindows)
53         return llvm::CallingConv::X86_StdCall;
54     else
55     {
56         error(loc, "unsupported calling convention");
57         fatal();
58     }
59 }
60
61 //////////////////////////////////////////////////////////////////////////////////////////
62
63 DValue* DtoVaArg(Loc& loc, Type* type, Expression* valistArg)
64 {
65     DValue* expelem = valistArg->toElem(gIR);
66     const LLType* llt = DtoType(type);
67     if (DtoIsPassedByRef(type))
68         llt = getPtrToType(llt);
69     // issue a warning for broken va_arg instruction.
70     if (global.params.cpu != ARCHx86)
71         warning("%s: va_arg for C variadic functions is probably broken for anything but x86", loc.toChars());
72     // done
73     return new DImValue(type, gIR->ir->CreateVAArg(expelem->getLVal(), llt, "tmp"));
74 }
75
76 //////////////////////////////////////////////////////////////////////////////////////////
77
78 LLValue* DtoCallableValue(DValue* fn)
79 {
80     Type* type = fn->getType()->toBasetype();
81     if (type->ty == Tfunction)
82     {
83         return fn->getRVal();
84     }
85     else if (type->ty == Tdelegate)
86     {
87         if (fn->isLVal())
88         {
89             LLValue* dg = fn->getLVal();
90             LLValue* funcptr = DtoGEPi(dg, 0, 1);
91             return DtoLoad(funcptr);
92         }
93         else
94         {
95             LLValue* dg = fn->getRVal();
96             assert(isaStruct(dg));
97             return gIR->ir->CreateExtractValue(dg, 1, ".funcptr");
98         }
99     }
100     else
101     {
102         assert(0 && "not a callable type");
103         return NULL;
104     }
105 }
106
107 //////////////////////////////////////////////////////////////////////////////////////////
108
109 const LLFunctionType* DtoExtractFunctionType(const LLType* type)
110 {
111     if (const LLFunctionType* fty = isaFunction(type))
112         return fty;
113     else if (const LLPointerType* pty = isaPointer(type))
114     {
115         if (const LLFunctionType* fty = isaFunction(pty->getElementType()))
116             return fty;
117     }
118     return NULL;
119 }
120
121 //////////////////////////////////////////////////////////////////////////////////////////
122
123 void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::AttributeWithIndex>& attrs, TypeFunction* tf, Expressions* arguments, size_t argidx)
124 {
125     Logger::println("doing d-style variadic arguments");
126     LOG_SCOPE
127
128     std::vector<const LLType*> vtypes;
129
130     // number of non variadic args
131     int begin = Parameter::dim(tf->parameters);
132     Logger::println("num non vararg params = %d", begin);
133
134     // get n args in arguments list
135     size_t n_arguments = arguments ? arguments->dim : 0;
136
137     // build struct with argument types (non variadic args)
138     for (int i=begin; i<n_arguments; i++)
139     {
140         Expression* argexp = (Expression*)arguments->data[i];
141         assert(argexp->type->ty != Ttuple);
142         vtypes.push_back(DtoType(argexp->type));
143         size_t sz = getTypePaddedSize(vtypes.back());
144         size_t asz = (sz + PTRSIZE - 1) & ~(PTRSIZE -1);
145         if (sz != asz)
146         {
147             if (sz < PTRSIZE)
148             {
149                 vtypes.back() = DtoSize_t();
150             }
151             else
152             {
153                 // ok then... so we build some type that is big enough
154                 // and aligned to PTRSIZE
155                 std::vector<const LLType*> gah;
156                 gah.reserve(asz/PTRSIZE);
157                 size_t gah_sz = 0;
158                 while (gah_sz < asz)
159                 {
160                     gah.push_back(DtoSize_t());
161                     gah_sz += PTRSIZE;
162                 }
163                 vtypes.back() = LLStructType::get(gIR->context(), gah, true);
164             }
165         }
166     }
167     const LLStructType* vtype = LLStructType::get(gIR->context(), vtypes);
168
169     if (Logger::enabled())
170         Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n';
171
172     LLValue* mem = DtoRawAlloca(vtype, 0, "_argptr_storage");
173
174     // store arguments in the struct
175     for (int i=begin,k=0; i<n_arguments; i++,k++)
176     {
177         Expression* argexp = (Expression*)arguments->data[i];
178         if (global.params.llvmAnnotate)
179             DtoAnnotation(argexp->toChars());
180         LLValue* argdst = DtoGEPi(mem,0,k);
181         argdst = DtoBitCast(argdst, getPtrToType(DtoType(argexp->type)));
182         DtoVariadicArgument(argexp, argdst);
183     }
184
185     // build type info array
186     const LLType* typeinfotype = DtoType(Type::typeinfo->type);
187     const LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype,vtype->getNumElements());
188
189     llvm::GlobalVariable* typeinfomem =
190         new llvm::GlobalVariable(*gIR->module, typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage");
191     if (Logger::enabled())
192         Logger::cout() << "_arguments storage: " << *typeinfomem << '\n';
193
194     std::vector<LLConstant*> vtypeinfos;
195     for (int i=begin,k=0; i<n_arguments; i++,k++)
196     {
197         Expression* argexp = (Expression*)arguments->data[i];
198         vtypeinfos.push_back(DtoTypeInfoOf(argexp->type));
199     }
200
201     // apply initializer
202     LLConstant* tiinits = LLConstantArray::get(typeinfoarraytype, vtypeinfos);
203     typeinfomem->setInitializer(tiinits);
204
205     // put data in d-array
206     std::vector<LLConstant*> pinits;
207     pinits.push_back(DtoConstSize_t(vtype->getNumElements()));
208     pinits.push_back(llvm::ConstantExpr::getBitCast(typeinfomem, getPtrToType(typeinfotype)));
209     const LLType* tiarrty = DtoType(Type::typeinfo->type->arrayOf());
210     tiinits = LLConstantStruct::get(gIR->context(), pinits, false);
211     LLValue* typeinfoarrayparam = new llvm::GlobalVariable(*gIR->module, tiarrty,
212         true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array");
213
214     llvm::AttributeWithIndex Attr;
215     // specify arguments
216     args.push_back(DtoLoad(typeinfoarrayparam));
217     if (unsigned atts = tf->fty.arg_arguments->attrs) {
218         Attr.Index = argidx;
219         Attr.Attrs = atts;
220         attrs.push_back(Attr);
221     }
222     ++argidx;
223
224     args.push_back(gIR->ir->CreateBitCast(mem, getPtrToType(LLType::getInt8Ty(gIR->context())), "tmp"));
225     if (unsigned atts = tf->fty.arg_argptr->attrs) {
226         Attr.Index = argidx;
227         Attr.Attrs = atts;
228         attrs.push_back(Attr);
229     }
230     ++argidx;
231
232     // pass non variadic args
233     for (int i=0; i<begin; i++)
234     {
235         Parameter* fnarg = Parameter::getNth(tf->parameters, i);
236         DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
237         args.push_back(argval->getRVal());
238
239         if (tf->fty.args[i]->attrs)
240         {
241             llvm::AttributeWithIndex Attr;
242             Attr.Index = argidx;
243             Attr.Attrs = tf->fty.args[i]->attrs;
244             attrs.push_back(Attr);
245         }
246
247         ++argidx;
248     }
249 }
250
251 // FIXME: this function is a mess !
252
253 DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments)
254 {
255     if (Logger::enabled()) {
256         Logger::println("DtoCallFunction()");
257     }
258     LOG_SCOPE
259
260     // the callee D type
261     Type* calleeType = fnval->getType();
262
263     // make sure the callee type has been processed
264     DtoType(calleeType);
265
266     // get func value if any
267     DFuncValue* dfnval = fnval->isFunc();
268
269     // handle special vararg intrinsics
270     bool va_intrinsic = (dfnval && dfnval->func && dfnval->func->isVaIntrinsic());
271
272     // get function type info
273     TypeFunction* tf = DtoTypeFunction(fnval);
274
275     // misc
276     bool retinptr = tf->fty.arg_sret;
277     bool thiscall = tf->fty.arg_this;
278     bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
279     bool nestedcall = tf->fty.arg_nest;
280     bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1);
281
282     llvm::CallingConv::ID callconv = DtoCallingConv(loc, tf->linkage);
283
284     // get callee llvm value
285     LLValue* callable = DtoCallableValue(fnval);
286     const LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType());
287     assert(callableTy);
288
289 //     if (Logger::enabled())
290 //         Logger::cout() << "callable: " << *callable << '\n';
291
292     // get n arguments
293     size_t n_arguments = arguments ? arguments->dim : 0;
294
295     // get llvm argument iterator, for types
296     LLFunctionType::param_iterator argbegin = callableTy->param_begin();
297     LLFunctionType::param_iterator argiter = argbegin;
298
299     // parameter attributes
300     std::vector<llvm::AttributeWithIndex> attrs;
301     llvm::AttributeWithIndex Attr;
302
303     // return attrs
304     if (tf->fty.ret->attrs)
305     {
306         Attr.Index = 0;
307         Attr.Attrs = tf->fty.ret->attrs;
308         attrs.push_back(Attr);
309     }
310
311     // handle implicit arguments
312     std::vector<LLValue*> args;
313     args.reserve(tf->fty.args.size());
314
315     // return in hidden ptr is first
316     if (retinptr)
317     {
318         LLValue* retvar = DtoRawAlloca(argiter->get()->getContainedType(0), 0, ".rettmp");
319         ++argiter;
320         args.push_back(retvar);
321
322         // add attrs for hidden ptr
323         Attr.Index = 1;
324         Attr.Attrs = tf->fty.arg_sret->attrs;
325         assert((Attr.Attrs & (llvm::Attribute::StructRet | llvm::Attribute::InReg))
326             && "Sret arg not sret or inreg?");
327         attrs.push_back(Attr);
328     }
329
330     // then comes a context argument...
331     if(thiscall || delegatecall || nestedcall)
332     {
333         // ... which can be a 'this' argument
334         if (thiscall && dfnval && dfnval->vthis)
335         {
336             LLValue* thisarg = DtoBitCast(dfnval->vthis, argiter->get());
337             ++argiter;
338             args.push_back(thisarg);
339         }
340         // ... or a delegate context arg
341         else if (delegatecall)
342         {
343             LLValue* ctxarg;
344             if (fnval->isLVal())
345             {
346                 ctxarg = DtoLoad(DtoGEPi(fnval->getLVal(), 0,0));
347             }
348             else
349             {
350                 ctxarg = gIR->ir->CreateExtractValue(fnval->getRVal(), 0, ".ptr");
351             }
352             ctxarg = DtoBitCast(ctxarg, argiter->get());
353             ++argiter;
354             args.push_back(ctxarg);
355         }
356         // ... or a nested function context arg
357         else if (nestedcall)
358         {
359             LLValue* contextptr = DtoNestedContext(loc, dfnval->func);
360             contextptr = DtoBitCast(contextptr, getVoidPtrType());
361             ++argiter;
362             args.push_back(contextptr);
363         }
364         else
365         {
366             error(loc, "Context argument required but none given");
367             fatal();
368         }
369
370         // add attributes for context argument
371         if (tf->fty.arg_this && tf->fty.arg_this->attrs)
372         {
373             Attr.Index = retinptr ? 2 : 1;
374             Attr.Attrs = tf->fty.arg_this->attrs;
375             attrs.push_back(Attr);
376         }
377         else if (tf->fty.arg_nest && tf->fty.arg_nest->attrs)
378         {
379             Attr.Index = retinptr ? 2 : 1;
380             Attr.Attrs = tf->fty.arg_nest->attrs;
381             attrs.push_back(Attr);
382         }
383     }
384
385     // handle the rest of the arguments based on param passing style
386
387     // variadic instrinsics need some custom casts
388     if (va_intrinsic)
389     {
390         for (int i=0; i<n_arguments; i++)
391         {
392             Expression* exp = (Expression*)arguments->data[i];
393             DValue* expelem = exp->toElem(gIR);
394             // cast to va_list*
395             LLValue* val = DtoBitCast(expelem->getLVal(), getVoidPtrType());
396             ++argiter;
397             args.push_back(val);
398         }
399     }
400
401     // d style varargs needs a few more hidden arguments as well as special passing
402     else if (dvarargs)
403     {
404         DtoBuildDVarArgList(args, attrs, tf, arguments, argiter-argbegin+1);
405     }
406
407     // otherwise we're looking at a normal function call
408     // or a C style vararg call
409     else
410     {
411         Logger::println("doing normal arguments");
412         if (Logger::enabled()) {
413             Logger::println("Arguments so far: (%d)", (int)args.size());
414             Logger::indent();
415             for (size_t i = 0; i < args.size(); i++) {
416                 Logger::cout() << *args[i] << '\n';
417             }
418             Logger::undent();
419             Logger::cout() << "Function type: " << tf->toChars() << '\n';
420             //Logger::cout() << "LLVM functype: " << *callable->getType() << '\n';
421         }
422
423         size_t n = Parameter::dim(tf->parameters);
424
425         LLSmallVector<unsigned, 10> attrptr(n, 0);
426
427         // do formal params
428         int beg = argiter-argbegin;
429         for (int i=0; i<n; i++)
430         {
431             Parameter* fnarg = Parameter::getNth(tf->parameters, i);
432             assert(fnarg);
433             DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
434
435 #if 0
436             if (Logger::enabled()) {
437                 Logger::cout() << "Argument before ABI: " << *argval->getRVal() << '\n';
438                 Logger::cout() << "Argument type before ABI: " << *DtoType(argval->getType()) << '\n';
439             }
440 #endif
441
442             // give the ABI a say
443             LLValue* arg = tf->fty.putParam(argval->getType(), i, argval);
444
445 #if 0
446             if (Logger::enabled()) {
447                 Logger::cout() << "Argument after ABI: " << *arg << '\n';
448                 Logger::cout() << "Argument type after ABI: " << *arg->getType() << '\n';
449             }
450 #endif
451
452             int j = tf->fty.reverseParams ? beg + n - i - 1 : beg + i;
453
454             // Hack around LDC assuming structs are in memory:
455             // If the function wants a struct, and the argument value is a
456             // pointer to a struct, load from it before passing it in.
457             if (argval->getType()->ty == Tstruct
458                     && isaPointer(arg) && !isaPointer(callableTy->getParamType(j))) {
459                 Logger::println("Loading struct type for function argument");
460                 arg = DtoLoad(arg);
461             }
462
463             // parameter type mismatch, this is hard to get rid of
464             if (arg->getType() != callableTy->getParamType(j))
465             {
466             #if 1
467                 if (Logger::enabled())
468                 {
469                     Logger::cout() << "arg:     " << *arg << '\n';
470                     Logger::cout() << "of type: " << *arg->getType() << '\n';
471                     Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n';
472                 }
473             #endif
474                 arg = DtoBitCast(arg, callableTy->getParamType(j));
475             }
476
477             // param attrs
478             attrptr[i] = tf->fty.args[i]->attrs;
479
480             ++argiter;
481             args.push_back(arg);
482         }
483
484         // reverse the relevant params as well as the param attrs
485         if (tf->fty.reverseParams)
486         {
487             std::reverse(args.begin() + beg, args.end());
488             std::reverse(attrptr.begin(), attrptr.end());
489         }
490
491         // add attributes
492         for (int i = 0; i < n; i++)
493         {
494             if (attrptr[i])
495             {
496                 Attr.Index = beg + i + 1;
497                 Attr.Attrs = attrptr[i];
498                 attrs.push_back(Attr);
499             }
500         }
501
502         // do C varargs
503         if (n_arguments > n)
504         {
505             for (int i=n; i<n_arguments; i++)
506             {
507                 Parameter* fnarg = Parameter::getNth(tf->parameters, i);
508                 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
509                 LLValue* arg = argval->getRVal();
510
511                 // FIXME: do we need any param attrs here ?
512
513                 ++argiter;
514                 args.push_back(arg);
515             }
516         }
517     }
518
519 #if 0
520     if (Logger::enabled())
521     {
522         Logger::println("%lu params passed", args.size());
523         for (int i=0; i<args.size(); ++i) {
524             assert(args[i]);
525             Logger::cout() << "arg["<<i<<"] = " << *args[i] << '\n';
526         }
527     }
528 #endif
529
530     // void returns cannot not be named
531     const char* varname = "";
532     if (callableTy->getReturnType() != LLType::getVoidTy(gIR->context()))
533         varname = "tmp";
534
535 #if 0
536     if (Logger::enabled())
537         Logger::cout() << "Calling: " << *callable << '\n';
538 #endif
539
540     // call the function
541     LLCallSite call = gIR->CreateCallOrInvoke(callable, args.begin(), args.end(), varname);
542
543     // get return value
544     LLValue* retllval = (retinptr) ? args[0] : call.getInstruction();
545
546     // Ignore ABI for intrinsics
547     if (tf->linkage != LINKintrinsic && !retinptr)
548     {
549         // do abi specific return value fixups
550         DImValue dretval(tf->next, retllval);
551         retllval = tf->fty.getRet(tf->next, &dretval);
552     }
553
554     // Hack around LDC assuming structs are in memory:
555     // If the function returns a struct, and the return value is not a
556     // pointer to a struct, store it to a stack slot before continuing.
557     if (tf->next->ty == Tstruct && !isaPointer(retllval)) {
558         Logger::println("Storing return value to stack slot");
559         LLValue* mem = DtoRawAlloca(retllval->getType(), 0);
560         DtoStore(retllval, mem);
561         retllval = mem;
562     }
563
564     // repaint the type if necessary
565     if (resulttype)
566     {
567         Type* rbase = resulttype->toBasetype();
568         Type* nextbase = tf->nextOf()->toBasetype();
569     #if DMDV2
570         rbase = rbase->mutableOf();
571         nextbase = nextbase->mutableOf();
572     #endif
573         if (!rbase->equals(nextbase))
574         {
575             Logger::println("repainting return value from '%s' to '%s'", tf->nextOf()->toChars(), rbase->toChars());
576             switch(rbase->ty)
577             {
578             case Tarray:
579                 retllval = DtoAggrPaint(retllval, DtoType(rbase));
580                 break;
581
582             case Tclass:
583             case Taarray:
584             case Tpointer:
585                 retllval = DtoBitCast(retllval, DtoType(rbase));
586                 break;
587
588             default:
589                 assert(0 && "unhandled repainting of return value");
590             }
591             if (Logger::enabled())
592                 Logger::cout() << "final return value: " << *retllval << '\n';
593         }
594     }
595
596     // set calling convention and parameter attributes
597     llvm::AttrListPtr attrlist = llvm::AttrListPtr::get(attrs.begin(), attrs.end());
598     if (dfnval && dfnval->func)
599     {
600         LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val);
601         if (llfunc && llfunc->isIntrinsic()) // override intrinsic attrs
602             attrlist = llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)llfunc->getIntrinsicID());
603         else
604             call.setCallingConv(callconv);
605     }
606     else
607         call.setCallingConv(callconv);
608     call.setAttributes(attrlist);
609
610     // if we are returning through a pointer arg
611     // make sure we provide a lvalue back!
612     if (retinptr)
613         return new DVarValue(resulttype, retllval);
614
615     return new DImValue(resulttype, retllval);
616 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.