Mercurial > projects > ldc
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 |