Mercurial > projects > ldc
comparison gen/tollvm.cpp @ 100:5071469303d4 trunk
[svn r104] TONS OF FIXES.
Split up declaration, constant initializer gen and definition for globals, structs, classes and functions.
Improved ClassInfo support (not complete), not in vtable yet.
Fixed a bunch of forward reference problems.
Much more. Major commit! :)
author | lindquist |
---|---|
date | Fri, 16 Nov 2007 08:21:47 +0100 |
parents | a676a7743642 |
children | 027b8d8b71ec |
comparison
equal
deleted
inserted
replaced
99:a676a7743642 | 100:5071469303d4 |
---|---|
12 #include "gen/irstate.h" | 12 #include "gen/irstate.h" |
13 #include "gen/logger.h" | 13 #include "gen/logger.h" |
14 #include "gen/runtime.h" | 14 #include "gen/runtime.h" |
15 #include "gen/arrays.h" | 15 #include "gen/arrays.h" |
16 #include "gen/dvalue.h" | 16 #include "gen/dvalue.h" |
17 #include "gen/functions.h" | |
17 #include "gen/structs.h" | 18 #include "gen/structs.h" |
19 #include "gen/classes.h" | |
18 | 20 |
19 bool DtoIsPassedByRef(Type* type) | 21 bool DtoIsPassedByRef(Type* type) |
20 { | 22 { |
21 TY t = DtoDType(type)->ty; | 23 TY t = DtoDType(type)->ty; |
22 return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray); | 24 return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray); |
93 case Tvoid: | 95 case Tvoid: |
94 return llvm::Type::VoidTy; | 96 return llvm::Type::VoidTy; |
95 | 97 |
96 // aggregates | 98 // aggregates |
97 case Tstruct: { | 99 case Tstruct: { |
98 if (t->llvmType == 0) | 100 if (!t->llvmType || *t->llvmType == NULL) { |
99 { | |
100 // recursive or cyclic declaration | 101 // recursive or cyclic declaration |
101 if (!gIR->structs.empty()) | 102 if (!gIR->structs.empty()) |
102 { | 103 { |
103 IRStruct* found = 0; | 104 IRStruct* found = 0; |
104 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i) | 105 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i) |
105 { | 106 { |
106 if (t == i->type) | 107 if (t == (*i)->type) |
107 { | 108 { |
108 return i->recty.get(); | 109 return (*i)->recty.get(); |
109 } | 110 } |
110 } | 111 } |
111 } | 112 } |
112 | 113 |
113 // forward declaration | 114 // forward declaration |
114 TypeStruct* ts = (TypeStruct*)t; | 115 TypeStruct* ts = (TypeStruct*)t; |
115 assert(ts->sym); | 116 assert(ts->sym); |
116 ts->sym->toObjFile(); | 117 ts->sym->toObjFile(); |
117 } | 118 } |
118 return t->llvmType; | 119 return t->llvmType->get(); |
119 } | 120 } |
120 | 121 |
121 case Tclass: { | 122 case Tclass: { |
122 if (t->llvmType == 0) | 123 if (!t->llvmType || *t->llvmType == NULL) { |
123 { | |
124 // recursive or cyclic declaration | 124 // recursive or cyclic declaration |
125 if (!gIR->structs.empty()) | 125 if (!gIR->structs.empty()) |
126 { | 126 { |
127 IRStruct* found = 0; | 127 IRStruct* found = 0; |
128 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i) | 128 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i) |
129 { | 129 { |
130 if (t == i->type) | 130 if (t == (*i)->type) |
131 { | 131 { |
132 return llvm::PointerType::get(i->recty.get()); | 132 return llvm::PointerType::get((*i)->recty.get()); |
133 } | 133 } |
134 } | 134 } |
135 } | 135 } |
136 | 136 |
137 // forward declaration | 137 // forward declaration |
138 TypeClass* tc = (TypeClass*)t; | 138 TypeClass* tc = (TypeClass*)t; |
139 assert(tc->sym); | 139 assert(tc->sym); |
140 tc->sym->toObjFile(); | 140 tc->sym->toObjFile(); |
141 } | 141 } |
142 return llvm::PointerType::get(t->llvmType); | 142 return llvm::PointerType::get(t->llvmType->get()); |
143 } | 143 } |
144 | 144 |
145 // functions | 145 // functions |
146 case Tfunction: | 146 case Tfunction: |
147 { | 147 { |
148 if (t->llvmType == 0) { | 148 if (!t->llvmType || *t->llvmType == NULL) { |
149 return DtoFunctionType(t,NULL); | 149 return DtoFunctionType(t,NULL); |
150 } | 150 } |
151 else { | 151 else { |
152 return t->llvmType; | 152 return t->llvmType->get(); |
153 } | 153 } |
154 } | 154 } |
155 | 155 |
156 // delegates | 156 // delegates |
157 case Tdelegate: | 157 case Tdelegate: |
158 { | 158 { |
159 if (t->llvmType == 0) { | 159 if (!t->llvmType || *t->llvmType == NULL) { |
160 return DtoDelegateType(t); | 160 return DtoDelegateType(t); |
161 } | 161 } |
162 else { | 162 else { |
163 return t->llvmType; | 163 return t->llvmType->get(); |
164 } | 164 } |
165 } | 165 } |
166 | 166 |
167 // typedefs | 167 // typedefs |
168 // enum | 168 // enum |
177 default: | 177 default: |
178 printf("trying to convert unknown type with value %d\n", t->ty); | 178 printf("trying to convert unknown type with value %d\n", t->ty); |
179 assert(0); | 179 assert(0); |
180 } | 180 } |
181 return 0; | 181 return 0; |
182 } | |
183 | |
184 ////////////////////////////////////////////////////////////////////////////////////////// | |
185 | |
186 const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain) | |
187 { | |
188 TypeFunction* f = (TypeFunction*)type; | |
189 assert(f != 0); | |
190 | |
191 bool typesafeVararg = false; | |
192 if (f->linkage == LINKd && f->varargs == 1) { | |
193 typesafeVararg = true; | |
194 } | |
195 | |
196 // return value type | |
197 const llvm::Type* rettype; | |
198 const llvm::Type* actualRettype; | |
199 Type* rt = f->next; | |
200 bool retinptr = false; | |
201 bool usesthis = false; | |
202 | |
203 if (ismain) { | |
204 rettype = llvm::Type::Int32Ty; | |
205 actualRettype = rettype; | |
206 } | |
207 else { | |
208 assert(rt); | |
209 if (DtoIsPassedByRef(rt)) { | |
210 rettype = llvm::PointerType::get(DtoType(rt)); | |
211 actualRettype = llvm::Type::VoidTy; | |
212 f->llvmRetInPtr = retinptr = true; | |
213 } | |
214 else { | |
215 rettype = DtoType(rt); | |
216 actualRettype = rettype; | |
217 } | |
218 } | |
219 | |
220 // parameter types | |
221 std::vector<const llvm::Type*> paramvec; | |
222 | |
223 if (retinptr) { | |
224 Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; | |
225 paramvec.push_back(rettype); | |
226 } | |
227 | |
228 if (thistype) { | |
229 paramvec.push_back(thistype); | |
230 usesthis = true; | |
231 } | |
232 | |
233 if (typesafeVararg) { | |
234 ClassDeclaration* ti = Type::typeinfo; | |
235 if (!ti->llvmInitZ) | |
236 ti->toObjFile(); | |
237 assert(ti->llvmInitZ); | |
238 std::vector<const llvm::Type*> types; | |
239 types.push_back(DtoSize_t()); | |
240 types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType()))); | |
241 const llvm::Type* t1 = llvm::StructType::get(types); | |
242 paramvec.push_back(llvm::PointerType::get(t1)); | |
243 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
244 } | |
245 | |
246 size_t n = Argument::dim(f->parameters); | |
247 | |
248 for (int i=0; i < n; ++i) { | |
249 Argument* arg = Argument::getNth(f->parameters, i); | |
250 // ensure scalar | |
251 Type* argT = DtoDType(arg->type); | |
252 assert(argT); | |
253 | |
254 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { | |
255 //assert(arg->vardecl); | |
256 //arg->vardecl->refparam = true; | |
257 } | |
258 else | |
259 arg->llvmCopy = true; | |
260 | |
261 const llvm::Type* at = DtoType(argT); | |
262 if (isaStruct(at)) { | |
263 Logger::println("struct param"); | |
264 paramvec.push_back(llvm::PointerType::get(at)); | |
265 } | |
266 else if (isaArray(at)) { | |
267 Logger::println("sarray param"); | |
268 assert(argT->ty == Tsarray); | |
269 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); | |
270 paramvec.push_back(llvm::PointerType::get(at)); | |
271 } | |
272 else if (llvm::isa<llvm::OpaqueType>(at)) { | |
273 Logger::println("opaque param"); | |
274 assert(argT->ty == Tstruct || argT->ty == Tclass); | |
275 paramvec.push_back(llvm::PointerType::get(at)); | |
276 } | |
277 else { | |
278 if (!arg->llvmCopy) { | |
279 Logger::println("ref param"); | |
280 at = llvm::PointerType::get(at); | |
281 } | |
282 else { | |
283 Logger::println("in param"); | |
284 } | |
285 paramvec.push_back(at); | |
286 } | |
287 } | |
288 | |
289 // construct function type | |
290 bool isvararg = !typesafeVararg && f->varargs; | |
291 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); | |
292 | |
293 f->llvmRetInPtr = retinptr; | |
294 f->llvmUsesThis = usesthis; | |
295 return functype; | |
296 } | |
297 | |
298 ////////////////////////////////////////////////////////////////////////////////////////// | |
299 | |
300 static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl) | |
301 { | |
302 TypeFunction* f = (TypeFunction*)fdecl->type; | |
303 assert(f != 0); | |
304 | |
305 const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
306 std::vector<const llvm::Type*> args; | |
307 | |
308 if (fdecl->llvmInternal == LLVMva_start) { | |
309 args.push_back(i8pty); | |
310 } | |
311 else if (fdecl->llvmInternal == LLVMva_intrinsic) { | |
312 size_t n = Argument::dim(f->parameters); | |
313 for (size_t i=0; i<n; ++i) { | |
314 args.push_back(i8pty); | |
315 } | |
316 } | |
317 else | |
318 assert(0); | |
319 | |
320 const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false); | |
321 f->llvmType = fty; | |
322 return fty; | |
323 } | |
324 | |
325 ////////////////////////////////////////////////////////////////////////////////////////// | |
326 | |
327 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl) | |
328 { | |
329 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { | |
330 return DtoVaFunctionType(fdecl); | |
331 } | |
332 | |
333 // type has already been resolved | |
334 if (fdecl->type->llvmType != 0) { | |
335 return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType); | |
336 } | |
337 | |
338 const llvm::Type* thisty = NULL; | |
339 if (fdecl->needThis()) { | |
340 if (AggregateDeclaration* ad = fdecl->isMember()) { | |
341 Logger::print("isMember = this is: %s\n", ad->type->toChars()); | |
342 thisty = DtoType(ad->type); | |
343 Logger::cout() << "this llvm type: " << *thisty << '\n'; | |
344 if (isaStruct(thisty) || thisty == gIR->topstruct().recty.get()) | |
345 thisty = llvm::PointerType::get(thisty); | |
346 } | |
347 else | |
348 assert(0); | |
349 } | |
350 else if (fdecl->isNested()) { | |
351 thisty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
352 } | |
353 | |
354 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain()); | |
355 fdecl->type->llvmType = functype; | |
356 return functype; | |
357 } | 182 } |
358 | 183 |
359 ////////////////////////////////////////////////////////////////////////////////////////// | 184 ////////////////////////////////////////////////////////////////////////////////////////// |
360 | 185 |
361 const llvm::StructType* DtoDelegateType(Type* t) | 186 const llvm::StructType* DtoDelegateType(Type* t) |
628 return llvm::Type::Int32Ty; | 453 return llvm::Type::Int32Ty; |
629 } | 454 } |
630 | 455 |
631 ////////////////////////////////////////////////////////////////////////////////////////// | 456 ////////////////////////////////////////////////////////////////////////////////////////// |
632 | 457 |
633 void DtoMain() | |
634 { | |
635 // emit main function llvm style | |
636 // int main(int argc, char**argv, char**env); | |
637 | |
638 assert(gIR != 0); | |
639 IRState& ir = *gIR; | |
640 | |
641 assert(ir.emitMain && ir.mainFunc); | |
642 | |
643 // parameter types | |
644 std::vector<const llvm::Type*> pvec; | |
645 pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty); | |
646 const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
647 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
648 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
649 const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty; | |
650 | |
651 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false); | |
652 llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module); | |
653 | |
654 llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func); | |
655 | |
656 // call static ctors | |
657 llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors"); | |
658 llvm::Instruction* apt = new llvm::CallInst(fn,"",bb); | |
659 | |
660 // call user main function | |
661 const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType(); | |
662 llvm::CallInst* call; | |
663 if (mainty->getNumParams() > 0) | |
664 { | |
665 // main with arguments | |
666 assert(mainty->getNumParams() == 1); | |
667 std::vector<llvm::Value*> args; | |
668 llvm::Function* mfn = LLVM_D_GetRuntimeFunction(ir.module,"_d_main_args"); | |
669 | |
670 llvm::Function::arg_iterator argi = func->arg_begin(); | |
671 args.push_back(argi++); | |
672 args.push_back(argi++); | |
673 | |
674 const llvm::Type* at = mainty->getParamType(0)->getContainedType(0); | |
675 llvm::Value* arr = new llvm::AllocaInst(at->getContainedType(1)->getContainedType(0), func->arg_begin(), "argstorage", apt); | |
676 llvm::Value* a = new llvm::AllocaInst(at, "argarray", apt); | |
677 llvm::Value* ptr = DtoGEPi(a,0,0,"tmp",bb); | |
678 llvm::Value* v = args[0]; | |
679 if (v->getType() != DtoSize_t()) | |
680 v = new llvm::ZExtInst(v, DtoSize_t(), "tmp", bb); | |
681 new llvm::StoreInst(v,ptr,bb); | |
682 ptr = DtoGEPi(a,0,1,"tmp",bb); | |
683 new llvm::StoreInst(arr,ptr,bb); | |
684 args.push_back(a); | |
685 new llvm::CallInst(mfn, args.begin(), args.end(), "", bb); | |
686 call = new llvm::CallInst(ir.mainFunc,a,"ret",bb); | |
687 } | |
688 else | |
689 { | |
690 // main with no arguments | |
691 call = new llvm::CallInst(ir.mainFunc,"ret",bb); | |
692 } | |
693 call->setCallingConv(ir.mainFunc->getCallingConv()); | |
694 | |
695 // call static dtors | |
696 fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors"); | |
697 new llvm::CallInst(fn,"",bb); | |
698 | |
699 // return | |
700 new llvm::ReturnInst(call,bb); | |
701 } | |
702 | |
703 ////////////////////////////////////////////////////////////////////////////////////////// | |
704 | |
705 void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) | |
706 { | |
707 Array* arr = &tc->sym->dtors; | |
708 for (size_t i=0; i<arr->dim; i++) | |
709 { | |
710 FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; | |
711 assert(fd->llvmValue); | |
712 new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb()); | |
713 } | |
714 } | |
715 | |
716 ////////////////////////////////////////////////////////////////////////////////////////// | |
717 | |
718 void DtoInitClass(TypeClass* tc, llvm::Value* dst) | |
719 { | |
720 assert(gIR); | |
721 | |
722 assert(tc->llvmType); | |
723 uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t()); | |
724 uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size; | |
725 | |
726 // set vtable field | |
727 llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb()); | |
728 assert(tc->sym->llvmVtbl); | |
729 new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb()); | |
730 | |
731 // copy the static initializer | |
732 if (n > 0) { | |
733 assert(tc->llvmInit); | |
734 assert(dst->getType() == tc->llvmInit->getType()); | |
735 | |
736 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
737 | |
738 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
739 dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb()); | |
740 | |
741 llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb()); | |
742 srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb()); | |
743 | |
744 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
745 std::vector<llvm::Value*> llargs; | |
746 llargs.resize(4); | |
747 llargs[0] = dstarr; | |
748 llargs[1] = srcarr; | |
749 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
750 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
751 | |
752 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
753 } | |
754 } | |
755 | |
756 ////////////////////////////////////////////////////////////////////////////////////////// | |
757 | |
758 llvm::Constant* DtoConstInitializer(Type* type, Initializer* init) | 458 llvm::Constant* DtoConstInitializer(Type* type, Initializer* init) |
759 { | 459 { |
760 llvm::Constant* _init = 0; // may return zero | 460 llvm::Constant* _init = 0; // may return zero |
761 if (!init) | 461 if (!init) |
762 { | 462 { |
785 _init = llvm::Constant::getNullValue(ty); | 485 _init = llvm::Constant::getNullValue(ty); |
786 } | 486 } |
787 else { | 487 else { |
788 Logger::println("unsupported const initializer: %s", init->toChars()); | 488 Logger::println("unsupported const initializer: %s", init->toChars()); |
789 } | 489 } |
490 return _init; | |
491 } | |
492 | |
493 ////////////////////////////////////////////////////////////////////////////////////////// | |
494 | |
495 llvm::Constant* DtoConstFieldInitializer(Type* t, Initializer* init) | |
496 { | |
497 Logger::println("DtoConstFieldInitializer"); | |
498 LOG_SCOPE; | |
499 | |
500 const llvm::Type* _type = DtoType(t); | |
501 | |
502 llvm::Constant* _init = DtoConstInitializer(t, init); | |
503 assert(_init); | |
504 if (_type != _init->getType()) | |
505 { | |
506 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n'; | |
507 if (t->ty == Tsarray) | |
508 { | |
509 const llvm::ArrayType* arrty = isaArray(_type); | |
510 uint64_t n = arrty->getNumElements(); | |
511 std::vector<llvm::Constant*> vals(n,_init); | |
512 _init = llvm::ConstantArray::get(arrty, vals); | |
513 } | |
514 else if (t->ty == Tarray) | |
515 { | |
516 assert(isaStruct(_type)); | |
517 _init = llvm::ConstantAggregateZero::get(_type); | |
518 } | |
519 else if (t->ty == Tstruct) | |
520 { | |
521 const llvm::StructType* structty = isaStruct(_type); | |
522 TypeStruct* ts = (TypeStruct*)t; | |
523 assert(ts); | |
524 assert(ts->sym); | |
525 assert(ts->sym->llvmInitZ); | |
526 _init = ts->sym->llvmInitZ; | |
527 } | |
528 else if (t->ty == Tclass) | |
529 { | |
530 _init = llvm::Constant::getNullValue(_type); | |
531 } | |
532 else { | |
533 Logger::println("failed for type %s", t->toChars()); | |
534 assert(0); | |
535 } | |
536 } | |
537 | |
790 return _init; | 538 return _init; |
791 } | 539 } |
792 | 540 |
793 ////////////////////////////////////////////////////////////////////////////////////////// | 541 ////////////////////////////////////////////////////////////////////////////////////////// |
794 | 542 |
852 { | 600 { |
853 std::vector<llvm::Value*> v(2); | 601 std::vector<llvm::Value*> v(2); |
854 v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false); | 602 v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false); |
855 v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false); | 603 v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false); |
856 return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb()); | 604 return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb()); |
857 } | |
858 | |
859 ////////////////////////////////////////////////////////////////////////////////////////// | |
860 | |
861 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) | |
862 { | |
863 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); | |
864 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); | |
865 llvm::Constant* fn = 0; | |
866 | |
867 if (fdecl->llvmInternal == LLVMva_start) { | |
868 fn = gIR->module->getOrInsertFunction("llvm.va_start", fty); | |
869 assert(fn); | |
870 } | |
871 else if (fdecl->llvmInternal == LLVMva_intrinsic) { | |
872 fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty); | |
873 assert(fn); | |
874 } | |
875 else | |
876 assert(0); | |
877 | |
878 llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn); | |
879 assert(func); | |
880 assert(func->isIntrinsic()); | |
881 fdecl->llvmValue = func; | |
882 return func; | |
883 } | |
884 | |
885 ////////////////////////////////////////////////////////////////////////////////////////// | |
886 | |
887 llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl) | |
888 { | |
889 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { | |
890 return DtoDeclareVaFunction(fdecl); | |
891 } | |
892 | |
893 // mangled name | |
894 char* mangled_name; | |
895 if (fdecl->llvmInternal == LLVMintrinsic) | |
896 mangled_name = fdecl->llvmInternal1; | |
897 else | |
898 mangled_name = fdecl->mangle(); | |
899 | |
900 // unit test special handling | |
901 if (fdecl->isUnitTestDeclaration()) | |
902 { | |
903 assert(0 && "no unittests yet"); | |
904 /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false); | |
905 // make the function | |
906 llvm::Function* func = gIR->module->getFunction(mangled_name); | |
907 if (func == 0) | |
908 func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module); | |
909 func->setCallingConv(llvm::CallingConv::Fast); | |
910 fdecl->llvmValue = func; | |
911 return func; | |
912 */ | |
913 } | |
914 | |
915 // regular function | |
916 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); | |
917 assert(f != 0); | |
918 | |
919 if (fdecl->llvmValue != 0) { | |
920 if (!llvm::isa<llvm::Function>(fdecl->llvmValue)) | |
921 { | |
922 Logger::cout() << *fdecl->llvmValue << '\n'; | |
923 assert(0); | |
924 } | |
925 return llvm::cast<llvm::Function>(fdecl->llvmValue); | |
926 } | |
927 | |
928 Logger::print("FuncDeclaration::toObjFile(%s): %s\n", fdecl->needThis()?"this":"static",fdecl->toChars()); | |
929 LOG_SCOPE; | |
930 | |
931 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) { | |
932 error("intrinsics cannot have function bodies"); | |
933 fatal(); | |
934 } | |
935 | |
936 // construct function | |
937 const llvm::FunctionType* functype = (f->llvmType == 0) ? DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType); | |
938 | |
939 // make the function | |
940 llvm::Function* func = gIR->module->getFunction(mangled_name); | |
941 if (func == 0) { | |
942 func = new llvm::Function(functype,DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module); | |
943 } | |
944 | |
945 if (fdecl->llvmInternal != LLVMintrinsic) | |
946 func->setCallingConv(DtoCallingConv(f->linkage)); | |
947 | |
948 fdecl->llvmValue = func; | |
949 f->llvmType = functype; | |
950 assert(llvm::isa<llvm::FunctionType>(f->llvmType)); | |
951 | |
952 if (fdecl->isMain()) { | |
953 gIR->mainFunc = func; | |
954 } | |
955 | |
956 // name parameters | |
957 llvm::Function::arg_iterator iarg = func->arg_begin(); | |
958 int k = 0; | |
959 if (f->llvmRetInPtr) { | |
960 iarg->setName("retval"); | |
961 f->llvmRetArg = iarg; | |
962 ++iarg; | |
963 } | |
964 if (f->llvmUsesThis) { | |
965 iarg->setName("this"); | |
966 ++iarg; | |
967 } | |
968 int varargs = -1; | |
969 if (f->linkage == LINKd && f->varargs == 1) | |
970 varargs = 0; | |
971 for (; iarg != func->arg_end(); ++iarg) | |
972 { | |
973 Argument* arg = Argument::getNth(f->parameters, k++); | |
974 //arg->llvmValue = iarg; | |
975 //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); | |
976 if (arg && arg->ident != 0) { | |
977 if (arg->vardecl) { | |
978 arg->vardecl->llvmValue = iarg; | |
979 } | |
980 iarg->setName(arg->ident->toChars()); | |
981 } | |
982 else if (!arg && varargs >= 0) { | |
983 if (varargs == 0) { | |
984 iarg->setName("_arguments"); | |
985 fdecl->llvmArguments = iarg; | |
986 } | |
987 else if (varargs == 1) { | |
988 iarg->setName("_argptr"); | |
989 fdecl->llvmArgPtr = iarg; | |
990 } | |
991 else | |
992 assert(0); | |
993 varargs++; | |
994 } | |
995 else { | |
996 iarg->setName("unnamed"); | |
997 } | |
998 } | |
999 | |
1000 Logger::cout() << "func decl: " << *func << '\n'; | |
1001 | |
1002 return func; | |
1003 } | 605 } |
1004 | 606 |
1005 ////////////////////////////////////////////////////////////////////////////////////////// | 607 ////////////////////////////////////////////////////////////////////////////////////////// |
1006 | 608 |
1007 llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty) | 609 llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty) |
1172 llvm::Value* DtoNestedVariable(VarDeclaration* vd) | 774 llvm::Value* DtoNestedVariable(VarDeclaration* vd) |
1173 { | 775 { |
1174 FuncDeclaration* fd = vd->toParent()->isFuncDeclaration(); | 776 FuncDeclaration* fd = vd->toParent()->isFuncDeclaration(); |
1175 assert(fd != NULL); | 777 assert(fd != NULL); |
1176 | 778 |
1177 IRFunction* fcur = &gIR->func(); | 779 IRFunction* fcur = gIR->func(); |
1178 FuncDeclaration* f = fcur->decl; | 780 FuncDeclaration* f = fcur->decl; |
1179 | 781 |
1180 // on this stack | 782 // on this stack |
1181 if (fd == f) { | 783 if (fd == f) { |
1182 llvm::Value* v = DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp"); | 784 llvm::Value* v = DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp"); |
1278 else if (t->ty == Tclass) { | 880 else if (t->ty == Tclass) { |
1279 assert(t2->ty == Tclass); | 881 assert(t2->ty == Tclass); |
1280 // assignment to this in constructor special case | 882 // assignment to this in constructor special case |
1281 if (lhs->isThis()) { | 883 if (lhs->isThis()) { |
1282 llvm::Value* tmp = rhs->getRVal(); | 884 llvm::Value* tmp = rhs->getRVal(); |
1283 FuncDeclaration* fdecl = gIR->func().decl; | 885 FuncDeclaration* fdecl = gIR->func()->decl; |
1284 // respecify the this param | 886 // respecify the this param |
1285 if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar)) | 887 if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar)) |
1286 fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint()); | 888 fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint()); |
1287 DtoStore(tmp, fdecl->llvmThisVar); | 889 DtoStore(tmp, fdecl->llvmThisVar); |
1288 } | 890 } |
1714 } | 1316 } |
1715 gIR->ir->CreateStore(DtoConstBool(true), gflag); | 1317 gIR->ir->CreateStore(DtoConstBool(true), gflag); |
1716 gIR->ir->CreateBr(endinitbb); | 1318 gIR->ir->CreateBr(endinitbb); |
1717 gIR->scope() = IRScope(endinitbb,oldend); | 1319 gIR->scope() = IRScope(endinitbb,oldend); |
1718 } | 1320 } |
1321 | |
1322 ////////////////////////////////////////////////////////////////////////////////////////// | |
1323 | |
1324 void DtoDefineDsymbol(Dsymbol* dsym) | |
1325 { | |
1326 if (StructDeclaration* sd = dsym->isStructDeclaration()) { | |
1327 DtoDefineStruct(sd); | |
1328 } | |
1329 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { | |
1330 DtoDefineClass(cd); | |
1331 } | |
1332 else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | |
1333 DtoDefineFunc(fd); | |
1334 } | |
1335 else { | |
1336 error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars()); | |
1337 assert(0 && "unsupported dsymbol for DtoDefineDsymbol"); | |
1338 } | |
1339 } | |
1340 | |
1341 ////////////////////////////////////////////////////////////////////////////////////////// | |
1342 | |
1343 void DtoConstInitDsymbol(Dsymbol* dsym) | |
1344 { | |
1345 if (StructDeclaration* sd = dsym->isStructDeclaration()) { | |
1346 DtoConstInitStruct(sd); | |
1347 } | |
1348 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { | |
1349 DtoConstInitClass(cd); | |
1350 } | |
1351 else if (VarDeclaration* vd = dsym->isVarDeclaration()) { | |
1352 DtoConstInitGlobal(vd); | |
1353 } | |
1354 else { | |
1355 error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars()); | |
1356 assert(0 && "unsupported dsymbol for DtoInitDsymbol"); | |
1357 } | |
1358 } | |
1359 | |
1360 ////////////////////////////////////////////////////////////////////////////////////////// | |
1361 | |
1362 void DtoConstInitGlobal(VarDeclaration* vd) | |
1363 { | |
1364 Logger::println("DtoConstInitGlobal(%s)", vd->toChars()); | |
1365 LOG_SCOPE; | |
1366 | |
1367 if (vd->llvmDModule) return; | |
1368 vd->llvmDModule = gIR->dmodule; | |
1369 | |
1370 bool emitRTstaticInit = false; | |
1371 | |
1372 llvm::Constant* _init = 0; | |
1373 if (vd->parent && vd->parent->isFuncDeclaration() && vd->init && vd->init->isExpInitializer()) { | |
1374 _init = DtoConstInitializer(vd->type, NULL); | |
1375 emitRTstaticInit = true; | |
1376 } | |
1377 else { | |
1378 _init = DtoConstInitializer(vd->type, vd->init); | |
1379 } | |
1380 | |
1381 const llvm::Type* _type = DtoType(vd->type); | |
1382 Type* t = DtoDType(vd->type); | |
1383 | |
1384 //Logger::cout() << "initializer: " << *_init << '\n'; | |
1385 if (_type != _init->getType()) { | |
1386 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; | |
1387 // zero initalizer | |
1388 if (_init->isNullValue()) | |
1389 _init = llvm::Constant::getNullValue(_type); | |
1390 // pointer to global constant (struct.init) | |
1391 else if (llvm::isa<llvm::GlobalVariable>(_init)) | |
1392 { | |
1393 assert(_init->getType()->getContainedType(0) == _type); | |
1394 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); | |
1395 assert(t->ty == Tstruct); | |
1396 TypeStruct* ts = (TypeStruct*)t; | |
1397 assert(ts->sym->llvmInitZ); | |
1398 _init = ts->sym->llvmInitZ; | |
1399 } | |
1400 // array single value init | |
1401 else if (isaArray(_type)) | |
1402 { | |
1403 _init = DtoConstStaticArray(_type, _init); | |
1404 } | |
1405 else { | |
1406 Logger::cout() << "Unexpected initializer type: " << *_type << '\n'; | |
1407 //assert(0); | |
1408 } | |
1409 } | |
1410 | |
1411 bool istempl = false; | |
1412 if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) { | |
1413 istempl = true; | |
1414 } | |
1415 | |
1416 if (_init && _init->getType() != _type) | |
1417 _type = _init->getType(); | |
1418 llvm::cast<llvm::OpaqueType>(vd->llvmIRGlobal->type.get())->refineAbstractTypeTo(_type); | |
1419 _type = vd->llvmIRGlobal->type.get(); | |
1420 assert(!_type->isAbstract()); | |
1421 | |
1422 llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->llvmValue); | |
1423 if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl)) | |
1424 { | |
1425 gvar->setInitializer(_init); | |
1426 } | |
1427 | |
1428 if (emitRTstaticInit) | |
1429 DtoLazyStaticInit(istempl, gvar, vd->init, t); | |
1430 } |