comparison gen/toobj.cpp @ 86:fd32135dca3e trunk

[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!! Lots of bugfixes. Added support for special foreach on strings. Added std.array, std.utf, std.ctype and std.uni to phobos. Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author lindquist
date Sat, 03 Nov 2007 14:44:58 +0100
parents gen/toobj.c@f869c636a113
children 058d3925950e
comparison
equal deleted inserted replaced
85:f869c636a113 86:fd32135dca3e
1
2 // Copyright (c) 1999-2004 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <cstddef>
11 #include <iostream>
12 #include <fstream>
13
14 #include "gen/llvm.h"
15 #include "llvm/Analysis/Verifier.h"
16 #include "llvm/Bitcode/ReaderWriter.h"
17 #include "llvm/Target/TargetMachine.h"
18 #include "llvm/Target/TargetMachineRegistry.h"
19
20 #include "mars.h"
21 #include "module.h"
22 #include "mtype.h"
23 #include "declaration.h"
24 #include "statement.h"
25 #include "enum.h"
26 #include "aggregate.h"
27 #include "init.h"
28 #include "attrib.h"
29 #include "id.h"
30 #include "import.h"
31 #include "template.h"
32 #include "scope.h"
33
34 #include "gen/irstate.h"
35 #include "gen/elem.h"
36 #include "gen/logger.h"
37 #include "gen/tollvm.h"
38 #include "gen/arrays.h"
39 #include "gen/todebug.h"
40 #include "gen/runtime.h"
41
42 //////////////////////////////////////////////////////////////////////////////////////////
43
44 void
45 Module::genobjfile()
46 {
47 Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n';
48 LOG_SCOPE;
49
50 // start by deleting the old object file
51 deleteObjFile();
52
53 // create a new ir state
54 IRState ir;
55 gIR = &ir;
56 ir.dmodule = this;
57
58 // name the module
59 std::string mname(toChars());
60 if (md != 0)
61 mname = md->toChars();
62 ir.module = new llvm::Module(mname);
63
64 // set target stuff
65 std::string target_triple(global.params.tt_arch);
66 target_triple.append(global.params.tt_os);
67 ir.module->setTargetTriple(target_triple);
68 ir.module->setDataLayout(global.params.data_layout);
69
70 // heavily inspired by tools/llc/llc.cpp:200-230
71 const llvm::TargetMachineRegistry::Entry* targetEntry;
72 std::string targetError;
73 targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError);
74 assert(targetEntry && "Failed to find a static target for module");
75 std::auto_ptr<llvm::TargetMachine> targetPtr(targetEntry->CtorFn(*ir.module, "")); // TODO: replace "" with features
76 assert(targetPtr.get() && "Could not allocate target machine!");
77 llvm::TargetMachine &targetMachine = *targetPtr.get();
78 gTargetData = targetMachine.getTargetData();
79
80 // debug info
81 if (global.params.symdebug) {
82 RegisterDwarfSymbols(ir.module);
83 ir.dwarfCompileUnit = DtoDwarfCompileUnit(this);
84 }
85
86 // process module members
87 for (int k=0; k < members->dim; k++) {
88 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
89 assert(dsym);
90 dsym->toObjFile();
91 }
92
93 gTargetData = 0;
94
95 // emit the llvm main function if necessary
96 if (ir.emitMain) {
97 DtoMain();
98 }
99
100 // verify the llvm
101 if (!global.params.novalidate) {
102 std::string verifyErr;
103 Logger::println("Verifying module...");
104 if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr))
105 {
106 error("%s", verifyErr.c_str());
107 fatal();
108 }
109 else {
110 Logger::println("Verification passed!");
111 }
112 }
113
114 // run passes
115 // TODO
116
117 // write bytecode
118 {
119 Logger::println("Writing LLVM bitcode\n");
120 std::ofstream bos(bcfile->name->toChars(), std::ios::binary);
121 llvm::WriteBitcodeToFile(ir.module, bos);
122 }
123
124 // disassemble ?
125 if (global.params.disassemble) {
126 Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars());
127 std::ofstream aos(llfile->name->toChars());
128 ir.module->print(aos);
129 }
130
131 delete ir.module;
132 gIR = NULL;
133 }
134
135 /* ================================================================== */
136
137 // Put out instance of ModuleInfo for this Module
138
139 void Module::genmoduleinfo()
140 {
141 }
142
143 /* ================================================================== */
144
145 void Dsymbol::toObjFile()
146 {
147 Logger::println("Ignoring Dsymbol::toObjFile for %s", toChars());
148 }
149
150 /* ================================================================== */
151
152 void Declaration::toObjFile()
153 {
154 Logger::println("Ignoring Declaration::toObjFile for %s", toChars());
155 }
156
157 /* ================================================================== */
158
159 void InterfaceDeclaration::toObjFile()
160 {
161 Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
162 }
163
164 /* ================================================================== */
165
166 void StructDeclaration::toObjFile()
167 {
168 TypeStruct* ts = (TypeStruct*)DtoDType(type);
169 if (llvmType != 0)
170 return;
171
172 static int sdi = 0;
173 Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars());
174 LOG_SCOPE;
175
176 gIR->structs.push_back(IRStruct(ts));
177
178 for (int k=0; k < members->dim; k++) {
179 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
180 dsym->toObjFile();
181 }
182
183 Logger::println("doing struct fields");
184
185 llvm::StructType* structtype = 0;
186 std::vector<llvm::Constant*> fieldinits;
187
188 if (gIR->topstruct().offsets.empty())
189 {
190 std::vector<const llvm::Type*> fieldtypes;
191 Logger::println("has no fields");
192 fieldtypes.push_back(llvm::Type::Int8Ty);
193 fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
194 structtype = llvm::StructType::get(fieldtypes);
195 }
196 else
197 {
198 Logger::println("has fields");
199 std::vector<const llvm::Type*> fieldtypes;
200 unsigned prevsize = (unsigned)-1;
201 unsigned lastoffset = (unsigned)-1;
202 const llvm::Type* fieldtype = NULL;
203 llvm::Constant* fieldinit = NULL;
204 size_t fieldpad = 0;
205 int idx = 0;
206 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
207 // first iteration
208 if (lastoffset == (unsigned)-1) {
209 lastoffset = i->first;
210 assert(lastoffset == 0);
211 fieldtype = DtoType(i->second.var->type);
212 fieldinit = i->second.init;
213 prevsize = gTargetData->getTypeSize(fieldtype);
214 i->second.var->llvmFieldIndex = idx;
215 }
216 // colliding offset?
217 else if (lastoffset == i->first) {
218 const llvm::Type* t = DtoType(i->second.var->type);
219 size_t s = gTargetData->getTypeSize(t);
220 if (s > prevsize) {
221 fieldpad += s - prevsize;
222 prevsize = s;
223 }
224 llvmHasUnions = true;
225 i->second.var->llvmFieldIndex = idx;
226 }
227 // intersecting offset?
228 else if (i->first < (lastoffset + prevsize)) {
229 const llvm::Type* t = DtoType(i->second.var->type);
230 size_t s = gTargetData->getTypeSize(t);
231 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
232 llvmHasUnions = true;
233 i->second.var->llvmFieldIndex = idx;
234 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
235 }
236 // fresh offset
237 else {
238 // commit the field
239 fieldtypes.push_back(fieldtype);
240 fieldinits.push_back(fieldinit);
241 if (fieldpad) {
242 // match up with below
243 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
244 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
245 fieldtypes.push_back(c->getType());
246 fieldinits.push_back(c);
247 idx++;
248 }
249
250 idx++;
251
252 // start new
253 lastoffset = i->first;
254 fieldtype = DtoType(i->second.var->type);
255 fieldinit = i->second.init;
256 prevsize = gTargetData->getTypeSize(fieldtype);
257 i->second.var->llvmFieldIndex = idx;
258 fieldpad = 0;
259 }
260 }
261 fieldtypes.push_back(fieldtype);
262 fieldinits.push_back(fieldinit);
263 if (fieldpad) {
264 // match up with above
265 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
266 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
267 fieldtypes.push_back(c->getType());
268 fieldinits.push_back(c);
269 }
270
271 Logger::println("creating struct type");
272 structtype = llvm::StructType::get(fieldtypes);
273 }
274
275 // refine abstract types for stuff like: struct S{S* next;}
276 if (gIR->topstruct().recty != 0)
277 {
278 llvm::PATypeHolder& pa = gIR->topstruct().recty;
279 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
280 structtype = llvm::cast<llvm::StructType>(pa.get());
281 }
282
283 ts->llvmType = structtype;
284 llvmType = structtype;
285
286 if (parent->isModule()) {
287 gIR->module->addTypeName(mangle(),ts->llvmType);
288 }
289
290 // generate static data
291 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
292 llvm::Constant* _init = 0;
293
294 // always generate the constant initalizer
295 if (!zeroInit) {
296 Logger::println("Not zero initialized");
297 //assert(tk == gIR->gIR->topstruct()().size());
298 #ifndef LLVMD_NO_LOGGER
299 Logger::cout() << "struct type: " << *structtype << '\n';
300 for (size_t k=0; k<fieldinits.size(); ++k) {
301 Logger::cout() << "Type:" << '\n';
302 Logger::cout() << *fieldinits[k]->getType() << '\n';
303 Logger::cout() << "Value:" << '\n';
304 Logger::cout() << *fieldinits[k] << '\n';
305 }
306 Logger::cout() << "Initializer printed" << '\n';
307 #endif
308 llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits);
309 }
310 else {
311 Logger::println("Zero initialized");
312 llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
313 }
314
315 // only provide the constant initializer for the defining module
316 if (getModule() == gIR->dmodule)
317 {
318 _init = llvmInitZ;
319 }
320
321 std::string initname("_D");
322 initname.append(mangle());
323 initname.append("6__initZ");
324 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module);
325 ts->llvmInit = initvar;
326
327 // generate member function definitions
328 gIR->topstruct().queueFuncs = false;
329 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
330 size_t n = mfs.size();
331 for (size_t i=0; i<n; ++i) {
332 mfs[i]->toObjFile();
333 }
334
335 llvmDModule = gIR->dmodule;
336
337 gIR->structs.pop_back();
338
339 // generate typeinfo
340 if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
341 type->getTypeInfo(NULL);
342 }
343
344 /* ================================================================== */
345
346 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
347 {
348 // start at the bottom of the inheritance chain
349 if (cd->baseClass != 0) {
350 unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
351 if (o != (unsigned)-1)
352 return o;
353 }
354
355 // check this class
356 unsigned i;
357 for (i=0; i<cd->fields.dim; ++i) {
358 VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
359 if (os == vd->offset)
360 return i+idx;
361 }
362 idx += i;
363
364 return (unsigned)-1;
365 }
366
367 void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
368 {
369 unsigned idx = 0;
370 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
371 assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
372 result.push_back(r+1); // vtable is 0
373 }
374
375 /* ================================================================== */
376
377 static void LLVM_AddBaseClassData(BaseClasses* bcs)
378 {
379 // add base class data members first
380 for (int j=0; j<bcs->dim; j++)
381 {
382 BaseClass* bc = (BaseClass*)(bcs->data[j]);
383 assert(bc);
384 Logger::println("Adding base class members of %s", bc->base->toChars());
385 LOG_SCOPE;
386
387 LLVM_AddBaseClassData(&bc->base->baseclasses);
388 for (int k=0; k < bc->base->members->dim; k++) {
389 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
390 if (dsym->isVarDeclaration())
391 {
392 dsym->toObjFile();
393 }
394 }
395 }
396 }
397
398 void ClassDeclaration::toObjFile()
399 {
400 TypeClass* ts = (TypeClass*)DtoDType(type);
401 if (ts->llvmType != 0 || llvmInProgress)
402 return;
403
404 llvmInProgress = true;
405
406 static int fdi = 0;
407 Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars());
408 LOG_SCOPE;
409
410 gIR->structs.push_back(IRStruct(ts));
411 gIR->classes.push_back(this);
412
413 // add vtable
414 llvm::PATypeHolder pa = llvm::OpaqueType::get();
415 const llvm::Type* vtabty = llvm::PointerType::get(pa);
416
417 std::vector<const llvm::Type*> fieldtypes;
418 fieldtypes.push_back(vtabty);
419
420 std::vector<llvm::Constant*> fieldinits;
421 fieldinits.push_back(0);
422
423 // base classes first
424 LLVM_AddBaseClassData(&baseclasses);
425
426 // then add own members
427 for (int k=0; k < members->dim; k++) {
428 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
429 dsym->toObjFile();
430 }
431
432 // fill out fieldtypes/inits
433 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
434 fieldtypes.push_back(DtoType(i->second.var->type));
435 fieldinits.push_back(i->second.init);
436 }
437
438 llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
439 // refine abstract types for stuff like: class C {C next;}
440 if (gIR->topstruct().recty != 0)
441 {
442 llvm::PATypeHolder& pa = gIR->topstruct().recty;
443 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
444 structtype = llvm::cast<llvm::StructType>(pa.get());
445 }
446
447 ts->llvmType = structtype;
448 llvmType = structtype;
449
450 bool needs_definition = false;
451 if (parent->isModule()) {
452 gIR->module->addTypeName(mangle(),ts->llvmType);
453 needs_definition = (getModule() == gIR->dmodule);
454 }
455 else {
456 assert(0 && "class parent is not a module");
457 }
458
459 // generate vtable
460 llvm::GlobalVariable* svtblVar = 0;
461 std::vector<llvm::Constant*> sinits;
462 std::vector<const llvm::Type*> sinits_ty;
463 sinits.reserve(vtbl.dim);
464 sinits_ty.reserve(vtbl.dim);
465
466 for (int k=0; k < vtbl.dim; k++)
467 {
468 Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
469 assert(dsym);
470 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
471
472 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
473 fd->toObjFile();
474 assert(fd->llvmValue);
475 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
476 sinits.push_back(c);
477 sinits_ty.push_back(c->getType());
478 }
479 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
480 const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
481 llvm::Constant* c = llvm::Constant::getNullValue(cty);
482 sinits.push_back(c);
483 sinits_ty.push_back(cty);
484 }
485 else
486 assert(0);
487 }
488
489 const llvm::StructType* svtbl_ty = 0;
490 if (!sinits.empty())
491 {
492 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
493
494 std::string varname("_D");
495 varname.append(mangle());
496 varname.append("6__vtblZ");
497
498 std::string styname(mangle());
499 styname.append("__vtblTy");
500
501 svtbl_ty = llvm::StructType::get(sinits_ty);
502 gIR->module->addTypeName(styname, svtbl_ty);
503 svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
504
505 llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
506 if (needs_definition)
507 svtblVar->setInitializer(llvmConstVtbl);
508 llvmVtbl = svtblVar;
509 }
510
511 ////////////////////////////////////////////////////////////////////////////////
512
513 // refine for final vtable type
514 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
515 svtbl_ty = llvm::cast<llvm::StructType>(pa.get());
516 structtype = llvm::cast<llvm::StructType>(gIR->topstruct().recty.get());
517 ts->llvmType = structtype;
518 llvmType = structtype;
519
520 // generate initializer
521 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
522 llvm::Constant* _init = 0;
523
524 // first field is always the vtable
525 assert(svtblVar != 0);
526 fieldinits[0] = svtblVar;
527
528 llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits);
529 assert(_init);
530
531 std::string initname("_D");
532 initname.append(mangle());
533 initname.append("6__initZ");
534 //Logger::cout() << *_init << '\n';
535 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
536 ts->llvmInit = initvar;
537
538 if (needs_definition) {
539 initvar->setInitializer(_init);
540 // generate member functions
541 gIR->topstruct().queueFuncs = false;
542 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
543 size_t n = mfs.size();
544 for (size_t i=0; i<n; ++i) {
545 mfs[i]->toObjFile();
546 }
547 }
548
549 gIR->classes.pop_back();
550 gIR->structs.pop_back();
551
552 llvmInProgress = false;
553 }
554
555 /******************************************
556 * Get offset of base class's vtbl[] initializer from start of csym.
557 * Returns ~0 if not this csym.
558 */
559
560 unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
561 {
562 return ~0;
563 }
564
565 /* ================================================================== */
566
567 void VarDeclaration::toObjFile()
568 {
569 Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
570 LOG_SCOPE;
571 llvm::Module* M = gIR->module;
572
573 if (aliassym)
574 {
575 toAlias()->toObjFile();
576 return;
577 }
578
579 // global variable or magic
580 if (isDataseg())
581 {
582 if (llvmTouched) return;
583 else llvmTouched = true;
584
585 bool _isconst = false;
586 if (isConst() && (init && !init->isExpInitializer()))
587 _isconst = true;
588
589 llvm::GlobalValue::LinkageTypes _linkage;
590 bool istempl = false;
591 if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
592 _linkage = llvm::GlobalValue::WeakLinkage;
593 istempl = true;
594 }
595 else if (parent && parent->isFuncDeclaration())
596 _linkage = llvm::GlobalValue::InternalLinkage;
597 else
598 _linkage = DtoLinkage(protection, storage_class);
599
600 Type* t = DtoDType(type);
601
602 const llvm::Type* _type = DtoType(t);
603 assert(_type);
604
605 llvm::Constant* _init = 0;
606 bool _signed = !type->isunsigned();
607
608 Logger::println("Creating global variable");
609 std::string _name(mangle());
610
611 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
612 llvmValue = gvar;
613
614 if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl))
615 {
616 if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) {
617 _init = DtoConstInitializer(t, NULL);
618 // create a flag to make sure initialization only happens once
619 llvm::GlobalValue::LinkageTypes gflaglink = istempl ? llvm::GlobalValue::WeakLinkage : llvm::GlobalValue::InternalLinkage;
620 std::string gflagname(_name);
621 gflagname.append("__initflag");
622 llvm::GlobalVariable* gflag = new llvm::GlobalVariable(llvm::Type::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,M);
623
624 // check flag and do init if not already done
625 llvm::BasicBlock* oldend = gIR->scopeend();
626 llvm::BasicBlock* initbb = new llvm::BasicBlock("ifnotinit",gIR->topfunc(),oldend);
627 llvm::BasicBlock* endinitbb = new llvm::BasicBlock("ifnotinitend",gIR->topfunc(),oldend);
628 llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
629 gIR->ir->CreateCondBr(cond, initbb, endinitbb);
630 gIR->scope() = IRScope(initbb,endinitbb);
631 elem* ie = DtoInitializer(init);
632 if (!ie->inPlace()) {
633 DValue* dst = new DVarValue(t, gvar, true);
634 DtoAssign(dst, ie);
635 delete dst;
636 }
637 gIR->ir->CreateStore(DtoConstBool(true), gflag);
638 gIR->ir->CreateBr(endinitbb);
639 gIR->scope() = IRScope(endinitbb,oldend);
640 }
641 else {
642 _init = DtoConstInitializer(t, init);
643 }
644
645 //Logger::cout() << "initializer: " << *_init << '\n';
646 if (_type != _init->getType()) {
647 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
648 // zero initalizer
649 if (_init->isNullValue())
650 _init = llvm::Constant::getNullValue(_type);
651 // pointer to global constant (struct.init)
652 else if (llvm::isa<llvm::GlobalVariable>(_init))
653 {
654 assert(_init->getType()->getContainedType(0) == _type);
655 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
656 assert(t->ty == Tstruct);
657 TypeStruct* ts = (TypeStruct*)t;
658 assert(ts->sym->llvmInitZ);
659 _init = ts->sym->llvmInitZ;
660 }
661 // array single value init
662 else if (llvm::isa<llvm::ArrayType>(_type))
663 {
664 _init = DtoConstStaticArray(_type, _init);
665 }
666 else {
667 Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
668 //assert(0);
669 }
670 }
671
672 Logger::cout() << "final init = " << *_init << '\n';
673 gvar->setInitializer(_init);
674 }
675
676 llvmDModule = gIR->dmodule;
677
678 //if (storage_class & STCprivate)
679 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
680 }
681
682 // inside aggregate declaration. declare a field.
683 else
684 {
685 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
686
687 Type* t = DtoDType(type);
688 const llvm::Type* _type = DtoType(t);
689
690 llvm::Constant*_init = DtoConstInitializer(t, init);
691 assert(_init);
692 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
693 if (_type != _init->getType())
694 {
695 if (t->ty == Tsarray)
696 {
697 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type);
698 uint64_t n = arrty->getNumElements();
699 std::vector<llvm::Constant*> vals(n,_init);
700 _init = llvm::ConstantArray::get(arrty, vals);
701 }
702 else if (t->ty == Tarray)
703 {
704 assert(llvm::isa<llvm::StructType>(_type));
705 _init = llvm::ConstantAggregateZero::get(_type);
706 }
707 else if (t->ty == Tstruct)
708 {
709 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
710 TypeStruct* ts = (TypeStruct*)t;
711 assert(ts);
712 assert(ts->sym);
713 assert(ts->sym->llvmInitZ);
714 _init = ts->sym->llvmInitZ;
715 }
716 else if (t->ty == Tclass)
717 {
718 _init = llvm::Constant::getNullValue(_type);
719 }
720 else {
721 Logger::println("failed for type %s", type->toChars());
722 assert(0);
723 }
724 }
725
726 // add the field in the IRStruct
727 gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init)));
728 }
729
730 Logger::println("VarDeclaration::toObjFile is done");
731 }
732
733 /* ================================================================== */
734
735 void TypedefDeclaration::toObjFile()
736 {
737 static int tdi = 0;
738 Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
739 LOG_SCOPE;
740
741 // generate typeinfo
742 type->getTypeInfo(NULL);
743 }
744
745 /* ================================================================== */
746
747 void EnumDeclaration::toObjFile()
748 {
749 Logger::println("Ignoring EnumDeclaration::toObjFile for %s", toChars());
750 }
751
752 /* ================================================================== */
753
754 void FuncDeclaration::toObjFile()
755 {
756 if (llvmDModule) {
757 assert(llvmValue != 0);
758 return;
759 }
760
761 if (llvmRunTimeHack) {
762 Logger::println("runtime hack func chars: %s", toChars());
763 if (!llvmValue)
764 llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, toChars());
765 return;
766 }
767
768 if (isUnitTestDeclaration()) {
769 Logger::println("*** ATTENTION: ignoring unittest declaration: %s", toChars());
770 return;
771 }
772
773 Type* t = DtoDType(type);
774 TypeFunction* f = (TypeFunction*)t;
775
776 bool declareOnly = false;
777 if (parent)
778 {
779 if (TemplateInstance* tinst = parent->isTemplateInstance()) {
780 TemplateDeclaration* tempdecl = tinst->tempdecl;
781 if (tempdecl->llvmInternal == LLVMva_start)
782 {
783 Logger::println("magic va_start found");
784 llvmInternal = LLVMva_start;
785 declareOnly = true;
786 }
787 else if (tempdecl->llvmInternal == LLVMva_arg)
788 {
789 Logger::println("magic va_arg found");
790 llvmInternal = LLVMva_arg;
791 return;
792 }
793 }
794 }
795
796 llvm::Function* func = DtoDeclareFunction(this);
797
798 if (declareOnly)
799 return;
800
801 if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) {
802 if (!llvmQueued) {
803 Logger::println("queueing %s", toChars());
804 gIR->topstruct().funcs.push_back(this);
805 llvmQueued = true;
806 }
807 return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
808 }
809
810 // debug info
811 if (global.params.symdebug) {
812 llvmDwarfSubProgram = DtoDwarfSubProgram(this);
813 }
814
815 assert(f->llvmType);
816 const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
817
818 // template instances should have weak linkage
819 if (parent && DtoIsTemplateInstance(parent)) {
820 func->setLinkage(llvm::GlobalValue::WeakLinkage);
821 }
822
823 // only members of the current module maybe be defined
824 if (getModule() == gIR->dmodule || DtoIsTemplateInstance(parent))
825 {
826 llvmDModule = gIR->dmodule;
827
828 // handle static constructor / destructor
829 if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) {
830 const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
831 //Logger::cout() << "static ctor type: " << *sctor_type << '\n';
832
833 llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue);
834 //Logger::cout() << "static ctor func: " << *sctor_func << '\n';
835
836 llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
837
838 //Logger::cout() << "static ctor init: " << *sctor_init << '\n';
839
840 // output the llvm.global_ctors array
841 const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
842 llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
843 }
844
845 // function definition
846 if (fbody != 0)
847 {
848 gIR->functions.push_back(IRFunction(this));
849 gIR->func().func = func;
850
851 // first make absolutely sure the type is up to date
852 f->llvmType = llvmValue->getType()->getContainedType(0);
853
854 //Logger::cout() << "func type: " << *f->llvmType << '\n';
855
856 // this handling
857 if (f->llvmUsesThis) {
858 Logger::println("uses this");
859 if (f->llvmRetInPtr)
860 llvmThisVar = ++func->arg_begin();
861 else
862 llvmThisVar = func->arg_begin();
863 assert(llvmThisVar != 0);
864 }
865
866 if (isMain())
867 gIR->emitMain = true;
868
869 llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
870 llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
871
872 //assert(gIR->scopes.empty());
873 gIR->scopes.push_back(IRScope(beginbb, endbb));
874
875 // create alloca point
876 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
877 gIR->func().allocapoint = f->llvmAllocaPoint;
878
879 // give arguments storage
880 size_t n = Argument::dim(f->parameters);
881 for (int i=0; i < n; ++i) {
882 Argument* arg = Argument::getNth(f->parameters, i);
883 if (arg && arg->vardecl) {
884 VarDeclaration* vd = arg->vardecl;
885 if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))
886 continue;
887 llvm::Value* a = vd->llvmValue;
888 assert(a);
889 std::string s(a->getName());
890 Logger::println("giving argument '%s' storage", s.c_str());
891 s.append("_storage");
892 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint);
893 gIR->ir->CreateStore(a,v);
894 vd->llvmValue = v;
895 }
896 else {
897 Logger::println("*** ATTENTION: some unknown argument: %s", arg ? arg->toChars() : 0);
898 }
899 }
900
901 // debug info
902 if (global.params.symdebug) DtoDwarfFuncStart(this);
903
904 llvm::Value* parentNested = NULL;
905 if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) {
906 parentNested = fd->llvmNested;
907 }
908
909 // construct nested variables struct
910 if (!llvmNestedVars.empty() || parentNested) {
911 std::vector<const llvm::Type*> nestTypes;
912 int j = 0;
913 if (parentNested) {
914 nestTypes.push_back(parentNested->getType());
915 j++;
916 }
917 for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
918 VarDeclaration* vd = *i;
919 vd->llvmNestedIndex = j++;
920 if (vd->isParameter()) {
921 assert(vd->llvmValue);
922 nestTypes.push_back(vd->llvmValue->getType());
923 }
924 else {
925 nestTypes.push_back(DtoType(vd->type));
926 }
927 }
928 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
929 Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
930 llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint);
931 if (parentNested) {
932 assert(llvmThisVar);
933 llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp");
934 gIR->ir->CreateStore(ptr, DtoGEPi(llvmNested, 0,0, "tmp"));
935 }
936 for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
937 VarDeclaration* vd = *i;
938 if (vd->isParameter()) {
939 gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp"));
940 vd->llvmValue = llvmNested;
941 }
942 }
943 }
944
945 // copy _argptr to a memory location
946 if (f->linkage == LINKd && f->varargs == 1)
947 {
948 llvm::Value* argptrmem = new llvm::AllocaInst(llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint());
949 new llvm::StoreInst(llvmArgPtr, argptrmem, gIR->scopebb());
950 llvmArgPtr = argptrmem;
951 }
952
953 // output function body
954 fbody->toIR(gIR);
955
956 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
957 // in automatically, so we do it here.
958 if (!isMain()) {
959 if (!gIR->scopereturned()) {
960 // pass the previous block into this block
961 if (global.params.symdebug) DtoDwarfFuncEnd(this);
962 if (func->getReturnType() == llvm::Type::VoidTy) {
963 new llvm::ReturnInst(gIR->scopebb());
964 }
965 else {
966 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
967 }
968 }
969 }
970
971 // erase alloca point
972 f->llvmAllocaPoint->eraseFromParent();
973 f->llvmAllocaPoint = 0;
974 gIR->func().allocapoint = 0;
975
976 gIR->scopes.pop_back();
977
978 // get rid of the endentry block, it's never used
979 assert(!func->getBasicBlockList().empty());
980 func->getBasicBlockList().pop_back();
981
982 // if the last block is empty now, it must be unreachable or it's a bug somewhere else
983 // would be nice to figure out how to assert that this is correct
984 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
985 if (lastbb->empty()) {
986 if (lastbb->getNumUses() == 0)
987 lastbb->eraseFromParent();
988 else {
989 new llvm::UnreachableInst(lastbb);
990 /*if (func->getReturnType() == llvm::Type::VoidTy) {
991 new llvm::ReturnInst(lastbb);
992 }
993 else {
994 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb);
995 }*/
996 }
997 }
998
999 gIR->functions.pop_back();
1000 }
1001 }
1002 }