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

root/gen/toobj.cpp

Revision 1650:40bd4a0d4870, 27.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 // Copyright (c) 1999-2004 by Digital Mars
2 // All Rights Reserved
3 // written by Walter Bright
4 // www.digitalmars.com
5 // License for redistribution is by either the Artistic License
6 // in artistic.txt, or the GNU General Public License in gnu.txt.
7 // See the included readme.txt for details.
8
9 #include <cstddef>
10 #include <fstream>
11
12 #include "gen/llvm.h"
13 #include "llvm/Analysis/Verifier.h"
14 #include "llvm/Bitcode/ReaderWriter.h"
15 #include "llvm/Module.h"
16 #include "llvm/PassManager.h"
17 #include "llvm/LinkAllPasses.h"
18 #include "llvm/System/Program.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/FormattedStream.h"
22 #include "llvm/Target/TargetMachine.h"
23 #include "llvm/CodeGen/MachineCodeEmitter.h"
24
25 #include "mars.h"
26 #include "module.h"
27 #include "mtype.h"
28 #include "declaration.h"
29 #include "statement.h"
30 #include "enum.h"
31 #include "aggregate.h"
32 #include "init.h"
33 #include "attrib.h"
34 #include "id.h"
35 #include "import.h"
36 #include "template.h"
37 #include "scope.h"
38
39 #include "gen/abi.h"
40 #include "gen/arrays.h"
41 #include "gen/classes.h"
42 #include "gen/cl_options.h"
43 #include "gen/functions.h"
44 #include "gen/irstate.h"
45 #include "gen/llvmhelpers.h"
46 #include "gen/logger.h"
47 #include "gen/optimizer.h"
48 #include "gen/programs.h"
49 #include "gen/rttibuilder.h"
50 #include "gen/runtime.h"
51 #include "gen/structs.h"
52 #include "gen/todebug.h"
53 #include "gen/tollvm.h"
54
55 #include "ir/irvar.h"
56 #include "ir/irmodule.h"
57 #include "ir/irtype.h"
58
59 //////////////////////////////////////////////////////////////////////////////////////////
60
61 static llvm::cl::opt<bool> noVerify("noverify",
62     llvm::cl::desc("Do not run the validation pass before writing bitcode"),
63     llvm::cl::ZeroOrMore);
64
65 //////////////////////////////////////////////////////////////////////////////////////////
66
67 // fwd decl
68 void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out);
69 void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath);
70
71 //////////////////////////////////////////////////////////////////////////////////////////
72
73 llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
74 {
75     bool logenabled = Logger::enabled();
76     if (llvmForceLogging && !logenabled)
77     {
78         Logger::enable();
79     }
80
81     Logger::println("Generating module: %s\n", (md ? md->toChars() : toChars()));
82     LOG_SCOPE;
83
84     if (global.params.verbose_cg)
85         printf("codegen: %s (%s)\n", toPrettyChars(), srcfile->toChars());
86
87     assert(!global.errors);
88
89     // name the module
90     llvm::StringRef mname(toChars());
91     if (md != 0)
92         mname = md->toChars();
93
94     // create a new ir state
95     // TODO look at making the instance static and moving most functionality into IrModule where it belongs
96     IRState ir(new llvm::Module(mname, context));
97     gIR = &ir;
98     ir.dmodule = this;
99
100     // reset all IR data stored in Dsymbols
101     IrDsymbol::resetAll();
102
103     sir->setState(&ir);
104
105     // set target triple
106     ir.module->setTargetTriple(global.params.targetTriple);
107
108     // set final data layout
109     ir.module->setDataLayout(global.params.dataLayout);
110     if (Logger::enabled())
111         Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n';
112
113     // allocate the target abi
114     gABI = TargetABI::getTarget();
115
116     #ifndef DISABLE_DEBUG_INFO
117     // debug info
118     if (global.params.symdebug) {
119         RegisterDwarfSymbols(ir.module);
120         DtoDwarfCompileUnit(this);
121     }
122     #endif
123
124     // handle invalid 'objectÞ module
125     if (!ClassDeclaration::object) {
126         error("is missing 'class Object'");
127         fatal();
128     }
129     if (!ClassDeclaration::classinfo) {
130         error("is missing 'class ClassInfo'");
131         fatal();
132     }
133
134     LLVM_D_InitRuntime();
135
136     // process module members
137     for (int k=0; k < members->dim; k++) {
138         Dsymbol* dsym = (Dsymbol*)(members->data[k]);
139         assert(dsym);
140         dsym->codegen(sir);
141     }
142
143     // emit function bodies
144     sir->emitFunctionBodies();
145
146     // for singleobj-compilation, fully emit all seen template instances
147     if (opts::singleObj)
148     {
149         while (!ir.seenTemplateInstances.empty())
150         {
151             IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end();
152             for (it = ir.seenTemplateInstances.begin(); it != end; ++it)
153                 (*it)->codegen(sir);
154             ir.seenTemplateInstances.clear();
155
156             // emit any newly added function bodies
157             sir->emitFunctionBodies();
158         }
159     }
160
161     // generate ModuleInfo
162     genmoduleinfo();
163
164     // emit usedArray
165     if (!ir.usedArray.empty())
166     {
167         const LLArrayType* usedTy = LLArrayType::get(getVoidPtrType(), ir.usedArray.size());
168         LLConstant* usedInit = LLConstantArray::get(usedTy, ir.usedArray);
169         LLGlobalVariable* usedArray = new LLGlobalVariable(*ir.module, usedTy, true, LLGlobalValue::AppendingLinkage, usedInit, "llvm.used");
170         usedArray->setSection("llvm.metadata");
171     }
172
173     // verify the llvm
174     if (!noVerify) {
175         std::string verifyErr;
176         Logger::println("Verifying module...");
177         LOG_SCOPE;
178         if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr))
179         {
180             error("%s", verifyErr.c_str());
181             fatal();
182         }
183         else {
184             Logger::println("Verification passed!");
185         }
186     }
187
188     gIR = NULL;
189
190     if (llvmForceLogging && !logenabled)
191     {
192         Logger::disable();
193     }
194
195     sir->setState(NULL);
196
197     return ir.module;
198 }
199
200 void writeModule(llvm::Module* m, std::string filename)
201 {
202     // run optimizer
203     bool reverify = ldc_optimize_module(m);
204
205     // verify the llvm
206     if (!noVerify && reverify) {
207         std::string verifyErr;
208         Logger::println("Verifying module... again...");
209         LOG_SCOPE;
210         if (llvm::verifyModule(*m,llvm::ReturnStatusAction,&verifyErr))
211         {
212             //error("%s", verifyErr.c_str());
213             fatal();
214         }
215         else {
216             Logger::println("Verification passed!");
217         }
218     }
219
220     // eventually do our own path stuff, dmd's is a bit strange.
221     typedef llvm::sys::Path LLPath;
222
223     // write LLVM bitcode
224     if (global.params.output_bc) {
225         LLPath bcpath = LLPath(filename);
226         bcpath.eraseSuffix();
227         bcpath.appendSuffix(std::string(global.bc_ext));
228         Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str());
229         std::string errinfo;
230         llvm::raw_fd_ostream bos(bcpath.c_str(), errinfo, llvm::raw_fd_ostream::F_Binary);
231         if (bos.has_error())
232         {
233             error("cannot write LLVM bitcode file '%s': %s", bcpath.c_str(), errinfo.c_str());
234             fatal();
235         }
236         llvm::WriteBitcodeToFile(m, bos);
237     }
238
239     // write LLVM IR
240     if (global.params.output_ll) {
241         LLPath llpath = LLPath(filename);
242         llpath.eraseSuffix();
243         llpath.appendSuffix(std::string(global.ll_ext));
244         Logger::println("Writing LLVM asm to: %s\n", llpath.c_str());
245         std::string errinfo;
246         llvm::raw_fd_ostream aos(llpath.c_str(), errinfo);
247         if (aos.has_error())
248         {
249             error("cannot write LLVM asm file '%s': %s", llpath.c_str(), errinfo.c_str());
250             fatal();
251         }
252         m->print(aos, NULL);
253     }
254
255     // write native assembly
256     if (global.params.output_s || global.params.output_o) {
257         LLPath spath = LLPath(filename);
258         spath.eraseSuffix();
259         spath.appendSuffix(std::string(global.s_ext));
260         if (!global.params.output_s) {
261             spath.createTemporaryFileOnDisk();
262         }
263         Logger::println("Writing native asm to: %s\n", spath.c_str());
264         std::string err;
265         {
266             llvm::raw_fd_ostream out(spath.c_str(), err);
267             if (err.empty())
268             {
269                 write_asm_to_file(*gTargetMachine, *m, out);
270             }
271             else
272             {
273                 error("cannot write native asm: %s", err.c_str());
274                 fatal();
275             }
276         }
277
278         // call gcc to convert assembly to object file
279         if (global.params.output_o) {
280             LLPath objpath = LLPath(filename);
281             assemble(spath, objpath);
282         }
283
284         if (!global.params.output_s) {
285             spath.eraseFromDisk();
286         }
287     }
288 }
289
290 /* ================================================================== */
291
292 // based on llc code, University of Illinois Open Source License
293 void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out)
294 {
295     using namespace llvm;
296
297     // Build up all of the passes that we want to do to the module.
298     FunctionPassManager Passes(&m);
299
300     if (const TargetData *TD = Target.getTargetData())
301         Passes.add(new TargetData(*TD));
302     else
303         Passes.add(new TargetData(&m));
304
305     // Last argument is enum CodeGenOpt::Level OptLevel
306     // debug info doesn't work properly with OptLevel != None!
307     CodeGenOpt::Level LastArg = CodeGenOpt::Default;
308     if (global.params.symdebug || !optimize())
309         LastArg = CodeGenOpt::None;
310     else if (optLevel() >= 3)
311         LastArg = CodeGenOpt::Aggressive;
312
313     llvm::formatted_raw_ostream fout(out);
314     if (Target.addPassesToEmitFile(Passes, fout, TargetMachine::CGFT_AssemblyFile, LastArg))
315         assert(0 && "no support for asm output");
316
317     Passes.doInitialization();
318
319     // Run our queue of passes all at once now, efficiently.
320     for (llvm::Module::iterator I = m.begin(), E = m.end(); I != E; ++I)
321         if (!I->isDeclaration())
322             Passes.run(*I);
323
324     Passes.doFinalization();
325
326     // release module from module provider so we can delete it ourselves
327     //std::string Err;
328     //llvm::Module* rmod = Provider.releaseModule(&Err);
329     //assert(rmod);
330 }
331
332 /* ================================================================== */
333
334 // uses gcc to make an obj out of an assembly file
335 // based on llvm-ld code, University of Illinois Open Source License
336 void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath)
337 {
338     using namespace llvm;
339
340     sys::Path gcc = getGcc();
341
342     // Run GCC to assemble and link the program into native code.
343     //
344     // Note:
345     //  We can't just assemble and link the file with the system assembler
346     //  and linker because we don't know where to put the _start symbol.
347     //  GCC mysteriously knows how to do it.
348     std::vector<std::string> args;
349     args.push_back(gcc.str());
350     args.push_back("-fno-strict-aliasing");
351     args.push_back("-O3");
352     args.push_back("-c");
353     args.push_back("-xassembler");
354     args.push_back(asmpath.str());
355     args.push_back("-o");
356     args.push_back(objpath.str());
357
358     //FIXME: only use this if needed?
359     args.push_back("-fpic");
360
361     //FIXME: enforce 64 bit
362     if (global.params.is64bit)
363         args.push_back("-m64");
364     else
365         // Assume 32-bit?
366         args.push_back("-m32");
367
368     // Now that "args" owns all the std::strings for the arguments, call the c_str
369     // method to get the underlying string array.  We do this game so that the
370     // std::string array is guaranteed to outlive the const char* array.
371     std::vector<const char *> Args;
372     for (unsigned i = 0, e = args.size(); i != e; ++i)
373         Args.push_back(args[i].c_str());
374     Args.push_back(0);
375
376     if (Logger::enabled()) {
377         Logger::println("Assembling with: ");
378         std::vector<const char*>::const_iterator I = Args.begin(), E = Args.end();
379         Stream logstr = Logger::cout();
380         for (; I != E; ++I)
381             if (*I)
382                 logstr << "'" << *I << "'" << " ";
383         logstr << "\n" << std::flush;
384     }
385
386     // Run the compiler to assembly the program.
387     std::string ErrMsg;
388     int R = sys::Program::ExecuteAndWait(
389         gcc, &Args[0], 0, 0, 0, 0, &ErrMsg);
390     if (R)
391     {
392         error("Failed to invoke gcc. %s", ErrMsg.c_str());
393         fatal();
394     }
395 }
396
397
398 /* ================================================================== */
399
400 // the following code generates functions and needs to output
401 // debug info. these macros are useful for that
402 #define DBG_TYPE    ( getPtrToType(llvm::StructType::get(gIR->context(),NULL,NULL)) )
403 #define DBG_CAST(X) ( llvm::ConstantExpr::getBitCast(X, DBG_TYPE) )
404
405 // build module ctor
406
407 llvm::Function* build_module_ctor()
408 {
409     if (gIR->ctors.empty())
410         return NULL;
411
412     size_t n = gIR->ctors.size();
413     if (n == 1)
414         return gIR->ctors[0]->ir.irFunc->func;
415
416     std::string name("_D");
417     name.append(gIR->dmodule->mangle());
418     name.append("6__ctorZ");
419
420     std::vector<const LLType*> argsTy;
421     const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
422     assert(gIR->module->getFunction(name) == NULL);
423     llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
424     fn->setCallingConv(DtoCallingConv(0, LINKd));
425
426     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn);
427     IRBuilder<> builder(bb);
428
429     // debug info
430     #ifndef DISABLE_DEBUG_INFO
431     LLGlobalVariable* subprog;
432     if(global.params.symdebug) {
433         subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV();
434         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
435     }
436     #endif
437
438     for (size_t i=0; i<n; i++) {
439         llvm::Function* f = gIR->ctors[i]->ir.irFunc->func;
440         llvm::CallInst* call = builder.CreateCall(f,"");
441         call->setCallingConv(DtoCallingConv(0, LINKd));
442     }
443
444     // debug info end
445     #ifndef DISABLE_DEBUG_INFO
446     if(global.params.symdebug)
447         builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog));
448     #endif
449
450     builder.CreateRetVoid();
451     return fn;
452 }
453
454 // build module dtor
455
456 static llvm::Function* build_module_dtor()
457 {
458     if (gIR->dtors.empty())
459         return NULL;
460
461     size_t n = gIR->dtors.size();
462     if (n == 1)
463         return gIR->dtors[0]->ir.irFunc->func;
464
465     std::string name("_D");
466     name.append(gIR->dmodule->mangle());
467     name.append("6__dtorZ");
468
469     std::vector<const LLType*> argsTy;
470     const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
471     assert(gIR->module->getFunction(name) == NULL);
472     llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
473     fn->setCallingConv(DtoCallingConv(0, LINKd));
474
475     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn);
476     IRBuilder<> builder(bb);
477
478     #ifndef DISABLE_DEBUG_INFO
479     // debug info
480     LLGlobalVariable* subprog;
481     if(global.params.symdebug) {
482         subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV();
483         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
484     }
485     #endif
486
487     for (size_t i=0; i<n; i++) {
488         llvm::Function* f = gIR->dtors[i]->ir.irFunc->func;
489         llvm::CallInst* call = builder.CreateCall(f,"");
490         call->setCallingConv(DtoCallingConv(0, LINKd));
491     }
492
493     #ifndef DISABLE_DEBUG_INFO
494     // debug info end
495     if(global.params.symdebug)
496         builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog));
497     #endif
498
499     builder.CreateRetVoid();
500     return fn;
501 }
502
503 // build module unittest
504
505 static llvm::Function* build_module_unittest()
506 {
507     if (gIR->unitTests.empty())
508         return NULL;
509
510     size_t n = gIR->unitTests.size();
511     if (n == 1)
512         return gIR->unitTests[0]->ir.irFunc->func;
513
514     std::string name("_D");
515     name.append(gIR->dmodule->mangle());
516     name.append("10__unittestZ");
517
518     std::vector<const LLType*> argsTy;
519     const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
520     assert(gIR->module->getFunction(name) == NULL);
521     llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
522     fn->setCallingConv(DtoCallingConv(0, LINKd));
523
524     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn);
525     IRBuilder<> builder(bb);
526
527     #ifndef DISABLE_DEBUG_INFO
528     // debug info
529     LLGlobalVariable* subprog;
530     if(global.params.symdebug) {
531         subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV();
532         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
533     }
534     #endif
535
536     for (size_t i=0; i<n; i++) {
537         llvm::Function* f = gIR->unitTests[i]->ir.irFunc->func;
538         llvm::CallInst* call = builder.CreateCall(f,"");
539         call->setCallingConv(DtoCallingConv(0, LINKd));
540     }
541
542     #ifndef DISABLE_DEBUG_INFO
543     // debug info end
544     if(global.params.symdebug)
545         builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog));
546     #endif
547
548     builder.CreateRetVoid();
549     return fn;
550 }
551
552 // build ModuleReference and register function, to register the module info in the global linked list
553 static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
554 {
555     // build ctor type
556     const LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<const LLType*>(), false);
557
558     // build ctor name
559     std::string fname = "_D";
560     fname += gIR->dmodule->mangle();
561     fname += "16__moduleinfoCtorZ";
562
563     // build a function that registers the moduleinfo in the global moduleinfo linked list
564     LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module);
565
566     // provide the default initializer
567     const LLStructType* modulerefTy = DtoModuleReferenceType();
568     std::vector<LLConstant*> mrefvalues;
569     mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0)));
570     mrefvalues.push_back(llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1)));
571     LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues);
572
573     // create the ModuleReference node for this module
574     std::string thismrefname = "_D";
575     thismrefname += gIR->dmodule->mangle();
576     thismrefname += "11__moduleRefZ";
577     LLGlobalVariable* thismref = new LLGlobalVariable(*gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname);
578
579     // make sure _Dmodule_ref is declared
580     LLGlobalVariable* mref = gIR->module->getNamedGlobal("_Dmodule_ref");
581     if (!mref)
582         mref = new LLGlobalVariable(*gIR->module, getPtrToType(modulerefTy), false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref");
583
584     // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list
585     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor);
586     IRBuilder<> builder(bb);
587
588     // debug info
589     #ifndef DISABLE_DEBUG_INFO
590     LLGlobalVariable* subprog;
591     if(global.params.symdebug) {
592         subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()).getGV();
593         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
594     }
595     #endif
596
597     // get current beginning
598     LLValue* curbeg = builder.CreateLoad(mref, "current");
599
600     // put current beginning as the next of this one
601     LLValue* gep = builder.CreateStructGEP(thismref, 0, "next");
602     builder.CreateStore(curbeg, gep);
603
604     // replace beginning
605     builder.CreateStore(thismref, mref);
606
607     #ifndef DISABLE_DEBUG_INFO
608     // debug info end
609     if(global.params.symdebug)
610         builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog));
611     #endif
612
613     // return
614     builder.CreateRetVoid();
615
616     return ctor;
617 }
618
619 // Put out instance of ModuleInfo for this Module
620
621 void Module::genmoduleinfo()
622 {
623 //     The layout is:
624 //         {
625 //         char[]          name;
626 //         ModuleInfo[]    importedModules;
627 //         ClassInfo[]     localClasses;
628 //         uint            flags;
629 //
630 //         void function() ctor;
631 //         void function() dtor;
632 //         void function() unitTest;
633 //
634 //         void* xgetMembers;
635 //         void function() ictor;
636 //
637 //         version(D_Version2)
638 //             void*[4] reserved; // useless to us
639 //         }
640
641     // resolve ModuleInfo
642     if (!moduleinfo)
643     {
644         error("object.d is missing the ModuleInfo class");
645         fatal();
646     }
647     // check for patch
648 #if DMDV2
649     else if (moduleinfo->fields.dim != 10)
650 #else
651     else if (moduleinfo->fields.dim != 9)
652 #endif
653     {
654         error("object.d ModuleInfo class is incorrect");
655         fatal();
656     }
657
658     // use the RTTIBuilder
659     RTTIBuilder b(moduleinfo);
660
661     // some types
662     const LLType* moduleinfoTy = moduleinfo->type->irtype->getPA();
663     const LLType* classinfoTy = ClassDeclaration::classinfo->type->irtype->getPA();
664
665     // name
666     b.push_string(toPrettyChars());
667
668     // importedModules[]
669     int aimports_dim = aimports.dim;
670     std::vector<LLConstant*> importInits;
671     LLConstant* c = 0;
672     for (size_t i = 0; i < aimports.dim; i++)
673     {
674         Module *m = (Module *)aimports.data[i];
675         if (!m->needModuleInfo() || m == this)
676             continue;
677
678         // declare the imported module info
679         std::string m_name("_D");
680         m_name.append(m->mangle());
681         m_name.append("8__ModuleZ");
682         llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name);
683         if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name);
684         importInits.push_back(m_gvar);
685     }
686     // has import array?
687     if (!importInits.empty())
688     {
689         const llvm::ArrayType* importArrTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size());
690         c = LLConstantArray::get(importArrTy, importInits);
691         std::string m_name("_D");
692         m_name.append(mangle());
693         m_name.append("9__importsZ");
694         llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name);
695         if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, importArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name);
696         c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importArrTy->getElementType()));
697         c = DtoConstSlice(DtoConstSize_t(importInits.size()), c);
698     }
699     else
700     {
701         c = DtoConstSlice( DtoConstSize_t(0), getNullValue(getPtrToType(moduleinfoTy)) );
702     }
703     b.push(c);
704
705     // localClasses[]
706     ClassDeclarations aclasses;
707     //printf("members->dim = %d\n", members->dim);
708     for (size_t i = 0; i < members->dim; i++)
709     {
710         Dsymbol *member;
711
712         member = (Dsymbol *)members->data[i];
713         //printf("\tmember '%s'\n", member->toChars());
714         member->addLocalClass(&aclasses);
715     }
716     // fill inits
717     std::vector<LLConstant*> classInits;
718     for (size_t i = 0; i < aclasses.dim; i++)
719     {
720         ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i];
721         cd->codegen(Type::sir);
722
723         if (cd->isInterfaceDeclaration())
724         {
725             Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars());
726             continue;
727         }
728         else if (cd->sizeok != 1)
729         {
730             Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars());
731             continue;
732         }
733         Logger::println("class: %s", cd->toPrettyChars());
734         c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy));
735         classInits.push_back(c);
736     }
737     // has class array?
738     if (!classInits.empty())
739     {
740         const llvm::ArrayType* classArrTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size());
741         c = LLConstantArray::get(classArrTy, classInits);
742         std::string m_name("_D");
743         m_name.append(mangle());
744         m_name.append("9__classesZ");
745         assert(gIR->module->getGlobalVariable(m_name) == NULL);
746         llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(*gIR->module, classArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name);
747         c = DtoGEPi(m_gvar, 0, 0);
748         c = DtoConstSlice(DtoConstSize_t(classInits.size()), c);
749     }
750     else
751         c = DtoConstSlice( DtoConstSize_t(0), getNullValue(getPtrToType(getPtrToType(classinfoTy))) );
752     b.push(c);
753
754     // flags (4 means MIstandalone)
755     unsigned mi_flags = needmoduleinfo ? 0 : 4;
756     b.push_uint(mi_flags);
757
758     // function pointer type for next three fields
759     const LLType* fnptrTy = getPtrToType(LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<const LLType*>(), false));
760
761     // ctor
762     llvm::Function* fctor = build_module_ctor();
763     c = fctor ? fctor : getNullValue(fnptrTy);
764     b.push(c);
765
766     // dtor
767     llvm::Function* fdtor = build_module_dtor();
768     c = fdtor ? fdtor : getNullValue(fnptrTy);
769     b.push(c);
770
771     // unitTest
772     llvm::Function* unittest = build_module_unittest();
773     c = unittest ? unittest : getNullValue(fnptrTy);
774     b.push(c);
775
776     // xgetMembers
777     c = getNullValue(getVoidPtrType());
778     b.push(c);
779
780     // ictor
781     c = getNullValue(fnptrTy);
782     b.push(c);
783
784 #if DMDV2
785
786     // void*[4] reserved :/
787     const LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 4);
788     c = getNullValue(AT);
789     b.push(c);
790
791 #endif
792
793     /*Logger::println("MODULE INFO INITIALIZERS");
794     for (size_t i=0; i<initVec.size(); ++i)
795     {
796         Logger::cout() << *initVec[i] << '\n';
797         if (initVec[i]->getType() != moduleinfoTy->getElementType(i))
798             assert(0);
799     }*/
800
801     // create initializer
802     LLConstant* constMI = b.get_constant();
803
804     // create name
805     std::string MIname("_D");
806     MIname.append(mangle());
807     MIname.append("8__ModuleZ");
808
809     // declare global
810     // flags will be modified at runtime so can't make it constant
811
812     // it makes no sense that the our own module info already exists!
813     assert(!gIR->module->getGlobalVariable(MIname));
814     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module, constMI->getType(), false, llvm::GlobalValue::ExternalLinkage, constMI, MIname);
815
816     // build the modulereference and ctor for registering it
817     LLFunction* mictor = build_module_reference_and_ctor(gvar);
818
819     // register this ctor in the magic llvm.global_ctors appending array
820     const LLFunctionType* magicfty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<const LLType*>(), false);
821     std::vector<const LLType*> magictypes;
822     magictypes.push_back(LLType::getInt32Ty(gIR->context()));
823     magictypes.push_back(getPtrToType(magicfty));
824     const LLStructType* magicsty = LLStructType::get(gIR->context(), magictypes);
825
826     // make the constant element
827     std::vector<LLConstant*> magicconstants;
828     magicconstants.push_back(DtoConstUint(65535));
829     magicconstants.push_back(mictor);
830     LLConstant* magicinit = LLConstantStruct::get(magicsty, magicconstants);
831
832     // declare the appending array
833     const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(magicsty, 1);
834     std::vector<LLConstant*> appendInits(1, magicinit);
835     LLConstant* appendInit = LLConstantArray::get(appendArrTy, appendInits);
836     std::string appendName("llvm.global_ctors");
837     llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(*gIR->module, appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName);
838 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.