comparison gen/functions.cpp @ 217:0806379a5eca trunk

[svn r233] Added: -oq command line option for writing fully qualified object names. Added: started support for x86 80bit floating point. Changed: aggregates passed by value now use the llvm 'byval' parameter attribute, also lays ground work for using other attributes. Changed: eliminated a lot more std::vectorS, these showed up pretty much at the top when profiling! Changed: performed other misc. cleanups. Changed: halt expression now call the new llvm trap intrinsic instead of an assert(0). Changed: dstress suite now passes -O0 by default, this only eliminates unreferenced globals, which speeds up linking quite a bit.
author lindquist
date Thu, 05 Jun 2008 06:38:36 +0200
parents a58d8f4b84df
children 74701ba40398
comparison
equal deleted inserted replaced
216:3d022aa016ae 217:0806379a5eca
49 actualRettype = rettype; 49 actualRettype = rettype;
50 } 50 }
51 else { 51 else {
52 assert(rt); 52 assert(rt);
53 Type* rtfin = DtoDType(rt); 53 Type* rtfin = DtoDType(rt);
54 if (DtoIsPassedByRef(rt)) { 54 if (DtoIsReturnedInArg(rt)) {
55 rettype = getPtrToType(DtoType(rt)); 55 rettype = getPtrToType(DtoType(rt));
56 actualRettype = llvm::Type::VoidTy; 56 actualRettype = llvm::Type::VoidTy;
57 f->llvmRetInPtr = retinptr = true; 57 f->llvmRetInPtr = retinptr = true;
58 } 58 }
59 else { 59 else {
92 // do nothing? 92 // do nothing?
93 } 93 }
94 94
95 size_t n = Argument::dim(f->parameters); 95 size_t n = Argument::dim(f->parameters);
96 96
97 int nbyval = 0;
98
99 llvm::PAListPtr palist;
100
97 for (int i=0; i < n; ++i) { 101 for (int i=0; i < n; ++i) {
98 Argument* arg = Argument::getNth(f->parameters, i); 102 Argument* arg = Argument::getNth(f->parameters, i);
99 // ensure scalar 103 // ensure scalar
100 Type* argT = DtoDType(arg->type); 104 Type* argT = DtoDType(arg->type);
101 assert(argT); 105 assert(argT);
102 106
107 bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
108
103 const LLType* at = DtoType(argT); 109 const LLType* at = DtoType(argT);
104 if (isaStruct(at)) { 110 if (isaStruct(at)) {
105 Logger::println("struct param"); 111 Logger::println("struct param");
106 paramvec.push_back(getPtrToType(at)); 112 paramvec.push_back(getPtrToType(at));
113 arg->llvmByVal = !refOrOut;
107 } 114 }
108 else if (isaArray(at)) { 115 else if (isaArray(at)) {
109 Logger::println("sarray param"); 116 Logger::println("sarray param");
110 assert(argT->ty == Tsarray); 117 assert(argT->ty == Tsarray);
111 //paramvec.push_back(getPtrToType(at->getContainedType(0))); 118 //paramvec.push_back(getPtrToType(at->getContainedType(0)));
112 paramvec.push_back(getPtrToType(at)); 119 paramvec.push_back(getPtrToType(at));
120 arg->llvmByVal = !refOrOut;
113 } 121 }
114 else if (llvm::isa<llvm::OpaqueType>(at)) { 122 else if (llvm::isa<llvm::OpaqueType>(at)) {
115 Logger::println("opaque param"); 123 Logger::println("opaque param");
116 assert(argT->ty == Tstruct || argT->ty == Tclass); 124 assert(argT->ty == Tstruct || argT->ty == Tclass);
117 paramvec.push_back(getPtrToType(at)); 125 paramvec.push_back(getPtrToType(at));
118 } 126 }
119 else { 127 else {
120 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { 128 if (refOrOut) {
121 Logger::println("by ref param"); 129 Logger::println("by ref param");
122 at = getPtrToType(at); 130 at = getPtrToType(at);
123 } 131 }
124 else { 132 else {
125 Logger::println("in param"); 133 Logger::println("in param");
126 } 134 }
127 paramvec.push_back(at); 135 paramvec.push_back(at);
128 } 136 }
129 } 137
138 if (arg->llvmByVal)
139 nbyval++;
140 }
141
142 //warning("set %d byval args for type: %s", nbyval, f->toChars());
130 143
131 // construct function type 144 // construct function type
132 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; 145 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
133 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); 146 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
134 147
135 f->llvmRetInPtr = retinptr; 148 f->llvmRetInPtr = retinptr;
136 f->llvmUsesThis = usesthis; 149 f->llvmUsesThis = usesthis;
137 150
138 //if (!f->ir.type) 151 f->ir.type = new llvm::PATypeHolder(functype);
139 f->ir.type = new llvm::PATypeHolder(functype);
140 //else
141 //assert(functype == f->ir.type->get());
142 152
143 return functype; 153 return functype;
144 } 154 }
145 155
146 ////////////////////////////////////////////////////////////////////////////////////////// 156 //////////////////////////////////////////////////////////////////////////////////////////
375 else // fall back to C, it should be the right thing to do 385 else // fall back to C, it should be the right thing to do
376 func->setCallingConv(llvm::CallingConv::C); 386 func->setCallingConv(llvm::CallingConv::C);
377 387
378 fdecl->ir.irFunc->func = func; 388 fdecl->ir.irFunc->func = func;
379 assert(llvm::isa<llvm::FunctionType>(f->ir.type->get())); 389 assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
390
391 // parameter attributes
392 if (f->parameters)
393 {
394 int llidx = 1;
395 if (f->llvmRetInPtr) ++llidx;
396 if (f->llvmUsesThis) ++llidx;
397 if (f->linkage == LINKd && f->varargs == 1)
398 llidx += 2;
399
400 int funcNumArgs = func->getArgumentList().size();
401 std::vector<llvm::ParamAttrsWithIndex> attrs;
402 int k = 0;
403
404 int nbyval = 0;
405
406 for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k)
407 {
408 Argument* fnarg = (Argument*)f->parameters->data[k];
409 assert(fnarg);
410 if (fnarg->llvmByVal)
411 {
412 llvm::ParamAttrsWithIndex PAWI;
413 PAWI.Index = llidx;
414 PAWI.Attrs = llvm::ParamAttr::ByVal;
415 attrs.push_back(PAWI);
416 nbyval++;
417 }
418 }
419
420 //warning("set %d byval args for function: %s", nbyval, func->getName().c_str());
421
422 if (nbyval) {
423 llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
424 func->setParamAttrs(palist);
425 }
426 }
380 427
381 // main 428 // main
382 if (fdecl->isMain()) { 429 if (fdecl->isMain()) {
383 gIR->mainFunc = func; 430 gIR->mainFunc = func;
384 } 431 }
773 if (arg->isVar() || arg->isLRValue()) 820 if (arg->isVar() || arg->isLRValue())
774 arg = new DImValue(argexp->type, arg->getLVal(), false); 821 arg = new DImValue(argexp->type, arg->getLVal(), false);
775 else 822 else
776 arg = new DImValue(argexp->type, arg->getRVal(), false); 823 arg = new DImValue(argexp->type, arg->getRVal(), false);
777 } 824 }
778 // aggregate arg 825 // byval arg, but expr has no storage yet
779 else if (DtoIsPassedByRef(argexp->type)) 826 else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
780 { 827 {
781 LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint()); 828 LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
782 DVarValue* vv = new DVarValue(argexp->type, alloc, true); 829 DVarValue* vv = new DVarValue(argexp->type, alloc, true);
783 DtoAssign(vv, arg); 830 DtoAssign(vv, arg);
784 arg = vv; 831 arg = vv;
785 }
786 // normal arg (basic/value type)
787 else
788 {
789 // nothing to do
790 } 832 }
791 833
792 return arg; 834 return arg;
793 } 835 }
794 836