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

root/gen/main.cpp

Revision 1650:40bd4a0d4870, 29.9 kB (checked in by Tomas Lindquist Olsen, 4 months 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 // Pulled out of dmd/mars.c
2
3 // some things are taken from llvm's llc tool
4 // which uses the llvm license
5
6 #include "gen/llvm.h"
7 #include "gen/llvm-version.h"
8 #include "llvm/LinkAllVMCore.h"
9 #include "llvm/Linker.h"
10 #include "llvm/LLVMContext.h"
11 #include "llvm/System/Signals.h"
12 #include "llvm/Target/SubtargetFeature.h"
13 #include "llvm/Target/TargetMachine.h"
14 #include "llvm/Target/TargetOptions.h"
15 #include "llvm/Target/TargetRegistry.h"
16 #include "llvm/Target/TargetSelect.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <assert.h>
21 #include <limits.h>
22
23 #if POSIX
24 #include <errno.h>
25 #elif _WIN32
26 #include <windows.h>
27 #endif
28
29 #include "rmem.h"
30 #include "root.h"
31
32 #include "mars.h"
33 #include "module.h"
34 #include "mtype.h"
35 #include "id.h"
36 #include "cond.h"
37
38 #include "gen/logger.h"
39 #include "gen/linkage.h"
40 #include "gen/linker.h"
41 #include "gen/irstate.h"
42 #include "gen/optimizer.h"
43 #include "gen/toobj.h"
44 #include "gen/metadata.h"
45 #include "gen/passes/Passes.h"
46
47 #include "gen/cl_options.h"
48 #include "gen/cl_helpers.h"
49 using namespace opts;
50
51 #include "gen/configfile.h"
52
53 extern void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
54 extern void backend_init();
55 extern void backend_term();
56
57 static cl::opt<bool> noDefaultLib("nodefaultlib",
58     cl::desc("Don't add a default library for linking implicitly"),
59     cl::ZeroOrMore);
60
61 static ArrayAdapter impPathsStore("I", global.params.imppath);
62 static cl::list<std::string, ArrayAdapter> importPaths("I",
63     cl::desc("Where to look for imports"),
64     cl::value_desc("path"),
65     cl::location(impPathsStore),
66     cl::Prefix);
67
68 static ArrayAdapter defaultLibStore("defaultlib", global.params.defaultlibnames);
69 static cl::list<std::string, ArrayAdapter> defaultlibs("defaultlib",
70     cl::desc("Set default libraries for non-debug build"),
71     cl::value_desc("lib,..."),
72     cl::location(defaultLibStore),
73     cl::CommaSeparated);
74
75 static ArrayAdapter debugLibStore("debuglib", global.params.debuglibnames);
76 static cl::list<std::string, ArrayAdapter> debuglibs("debuglib",
77     cl::desc("Set default libraries for debug build"),
78     cl::value_desc("lib,..."),
79     cl::location(debugLibStore),
80     cl::CommaSeparated);
81
82 void printVersion() {
83     printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n",
84     global.ldc_version, global.version, global.llvm_version, global.copyright, global.written);
85     printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n"
86            "LDC Homepage: http://www.dsource.org/projects/ldc\n");
87 }
88
89 // Helper function to handle -d-debug=* and -d-version=*
90 static void processVersions(std::vector<std::string>& list, char* type,
91         void (*setLevel)(unsigned), void (*addIdent)(const char*)) {
92     typedef std::vector<std::string>::iterator It;
93
94     for(It I = list.begin(), E = list.end(); I != E; ++I) {
95         const char* value = I->c_str();
96         if (isdigit(value[0])) {
97             errno = 0;
98             char* end;
99             long level = strtol(value, &end, 10);
100             if (*end || errno || level > INT_MAX) {
101                 error("Invalid %s level: %s", type, I->c_str());
102             } else {
103                 setLevel((unsigned)level);
104             }
105         } else {
106             char* cstr = mem.strdup(value);
107             if (Lexer::isValidIdentifier(cstr)) {
108                 addIdent(cstr);
109                 continue;
110             } else {
111                 error("Invalid %s identifier or level: '%s'", type, I->c_str());
112             }
113         }
114     }
115 }
116
117 // Helper function to handle -of, -od, etc.
118 static void initFromString(char*& dest, const cl::opt<std::string>& src) {
119     dest = 0;
120     if (src.getNumOccurrences() != 0) {
121         if (src.empty())
122             error("Expected argument to '-%s'", src.ArgStr);
123         dest = mem.strdup(src.c_str());
124     }
125 }
126
127 int main(int argc, char** argv)
128 {
129     // stack trace on signals
130     llvm::sys::PrintStackTraceOnErrorSignal();
131
132     Array files;
133     char *p, *ext;
134     Module *m;
135     int status = EXIT_SUCCESS;
136
137     // Set some default values
138 #if _WIN32
139     char buf[MAX_PATH];
140     GetModuleFileName(NULL, buf, MAX_PATH);
141     global.params.argv0 = buf;
142 #else
143     global.params.argv0 = argv[0];
144 #endif
145     global.params.useSwitchError = 1;
146
147     global.params.linkswitches = new Array();
148     global.params.libfiles = new Array();
149     global.params.objfiles = new Array();
150     global.params.ddocfiles = new Array();
151
152     global.params.moduleDeps = NULL;
153     global.params.moduleDepsFile = NULL;
154
155     // Set predefined version identifiers
156     VersionCondition::addPredefinedGlobalIdent("LLVM");
157     VersionCondition::addPredefinedGlobalIdent("LDC");
158     VersionCondition::addPredefinedGlobalIdent("all");
159 #if DMDV2
160     VersionCondition::addPredefinedGlobalIdent("D_Version2");
161 #endif
162
163     // merge DFLAGS environment variable into argc/argv
164     getenv_setargv("DFLAGS", &argc, &argv);
165 #if 0
166     for (int i = 0; i < argc; i++)
167     {
168     printf("argv[%d] = '%s'\n", i, argv[i]);
169     }
170 #endif
171
172     // build complete fixed up list of command line arguments
173     std::vector<const char*> final_args;
174     final_args.reserve(argc);
175
176     // insert command line args until -run is reached
177     int run_argnum = 1;
178     while (run_argnum < argc && strncmp(argv[run_argnum], "-run", 4) != 0)
179         ++run_argnum;
180     final_args.insert(final_args.end(), &argv[0], &argv[run_argnum]);
181
182     // read the configuration file
183     ConfigFile cfg_file;
184
185     // just ignore errors for now, they are still printed
186 #if DMDV2
187 #define CFG_FILENAME "ldc2.conf"
188 #else
189 #define CFG_FILENAME "ldc.conf"
190 #endif
191     cfg_file.read(global.params.argv0, (void*)main, CFG_FILENAME);
192 #undef CFG_FILENAME
193
194     // insert config file additions to the argument list
195     final_args.insert(final_args.end(), cfg_file.switches_begin(), cfg_file.switches_end());
196
197     // insert -run and everything beyond
198     final_args.insert(final_args.end(), &argv[run_argnum], &argv[argc]);
199
200 #if 0
201     for (size_t i = 0; i < final_args.size(); ++i)
202     {
203         printf("final_args[%zu] = %s\n", i, final_args[i]);
204     }
205 #endif
206
207     // Handle fixed-up arguments!
208     cl::SetVersionPrinter(&printVersion);
209     cl::ParseCommandLineOptions(final_args.size(), (char**)&final_args[0], "LLVM-based D Compiler\n", true);
210
211     // Print config file path if -v was passed
212     if (global.params.verbose) {
213         const std::string& path = cfg_file.path();
214         if (!path.empty())
215             printf("config    %s\n", path.c_str());
216     }
217
218     // Negated options
219     global.params.link = !compileOnly;
220     global.params.obj = !dontWriteObj;
221     global.params.useInlineAsm = !noAsm;
222
223     // String options: std::string --> char*
224     initFromString(global.params.objname, objectFile);
225     initFromString(global.params.objdir, objectDir);
226
227     initFromString(global.params.docdir, ddocDir);
228     initFromString(global.params.docname, ddocFile);
229     global.params.doDocComments |=
230         global.params.docdir || global.params.docname;
231
232 #ifdef _DH
233     initFromString(global.params.hdrdir, hdrDir);
234     initFromString(global.params.hdrname, hdrFile);
235     global.params.doHdrGeneration |=
236         global.params.hdrdir || global.params.hdrname;
237 #endif
238
239     initFromString(global.params.moduleDepsFile, moduleDepsFile);
240     if (global.params.moduleDepsFile != NULL)
241     {
242          global.params.moduleDeps = new OutBuffer;
243     }
244
245     processVersions(debugArgs, "debug",
246         DebugCondition::setGlobalLevel,
247         DebugCondition::addGlobalIdent);
248     processVersions(versions, "version",
249         VersionCondition::setGlobalLevel,
250         VersionCondition::addGlobalIdent);
251
252     global.params.output_o =
253         (opts::output_o == cl::BOU_UNSET
254             && !(opts::output_bc || opts::output_ll || opts::output_s))
255         ? OUTPUTFLAGdefault
256         : opts::output_o == cl::BOU_TRUE
257             ? OUTPUTFLAGset
258             : OUTPUTFLAGno;
259     global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno;
260     global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno;
261     global.params.output_s  = opts::output_s  ? OUTPUTFLAGset : OUTPUTFLAGno;
262
263     templateLinkage =
264         opts::linkonceTemplates ? LLGlobalValue::LinkOnceODRLinkage
265                                 : LLGlobalValue::WeakODRLinkage;
266
267     if (global.params.run || !runargs.empty()) {
268         // FIXME: how to properly detect the presence of a PositionalEatsArgs
269         // option without parameters? We want to emit an error in that case...
270         // You'd think getNumOccurrences would do it, but it just returns the
271         // number of parameters)
272         // NOTE: Hacked around it by detecting -run in getenv_setargv(), where
273         // we're looking for it anyway, and pre-setting the flag...
274         global.params.run = true;
275         if (!runargs.empty()) {
276             files.push(mem.strdup(runargs[0].c_str()));
277         } else {
278             global.params.run = false;
279             error("Expected at least one argument to '-run'\n");
280         }
281     }
282
283
284     files.reserve(fileList.size());
285     typedef std::vector<std::string>::iterator It;
286     for(It I = fileList.begin(), E = fileList.end(); I != E; ++I)
287         if (!I->empty())
288             files.push(mem.strdup(I->c_str()));
289
290     if (global.errors)
291     {
292         fatal();
293     }
294     if (files.dim == 0)
295     {
296         cl::PrintHelpMessage();
297         return EXIT_FAILURE;
298     }
299
300     Array* libs;
301     if (global.params.symdebug)
302     {
303         libs = global.params.debuglibnames;
304         llvm::NoFramePointerElim = true;
305     }
306     else
307         libs = global.params.defaultlibnames;
308
309     if (!noDefaultLib)
310     {
311         if (libs)
312         {
313             for (int i = 0; i < libs->dim; i++)
314             {
315                 char* lib = (char *)libs->data[i];
316                 char *arg = (char *)mem.malloc(strlen(lib) + 3);
317                 strcpy(arg, "-l");
318                 strcpy(arg+2, lib);
319                 global.params.linkswitches->push(arg);
320             }
321         }
322         else
323         {
324 #if DMDV2
325             global.params.linkswitches->push(mem.strdup("-ldruntime-ldc"));
326 #else
327             global.params.linkswitches->push(mem.strdup("-lldc-runtime"));
328             global.params.linkswitches->push(mem.strdup("-ltango-cc-tango"));
329             global.params.linkswitches->push(mem.strdup("-ltango-gc-basic"));
330             // pass the runtime again to resolve issues
331             // with linking order
332             global.params.linkswitches->push(mem.strdup("-lldc-runtime"));
333 #endif
334         }
335     }
336
337     if (global.params.run)
338         quiet = 1;
339
340     if (global.params.useUnitTests)
341         global.params.useAssert = 1;
342
343     // LDC output determination
344
345     // if we don't link, autodetect target from extension
346     if(!global.params.link && global.params.objname) {
347         ext = FileName::ext(global.params.objname);
348         bool autofound = false;
349         if (!ext) {
350             // keep things as they are
351         } else if (strcmp(ext, global.ll_ext) == 0) {
352             global.params.output_ll = OUTPUTFLAGset;
353             autofound = true;
354         } else if (strcmp(ext, global.bc_ext) == 0) {
355             global.params.output_bc = OUTPUTFLAGset;
356             autofound = true;
357         } else if (strcmp(ext, global.s_ext) == 0) {
358             global.params.output_s = OUTPUTFLAGset;
359             autofound = true;
360         } else if (strcmp(ext, global.obj_ext) == 0) {
361             global.params.output_o = OUTPUTFLAGset;
362             autofound = true;
363         } else {
364             // append dot, so forceExt won't change existing name even if it contains dots
365             size_t len = strlen(global.params.objname);
366             size_t extlen = strlen(".");
367             char* s = (char *)mem.malloc(len + 1 + extlen + 1);
368             memcpy(s, global.params.objname, len);
369             s[len] = '.';
370             s[len+1+extlen] = 0;
371             global.params.objname = s;
372
373         }
374         if(autofound && global.params.output_o == OUTPUTFLAGdefault)
375             global.params.output_o = OUTPUTFLAGno;
376     }
377
378     // only link if possible
379     if (!global.params.obj || !global.params.output_o)
380         global.params.link = 0;
381
382     if (global.params.link)
383     {
384         global.params.exefile = global.params.objname;
385         if (files.dim > 1)
386             global.params.objname = NULL;
387     }
388     else if (global.params.run)
389     {
390         error("flags conflict with -run");
391         fatal();
392     }
393     else
394     {
395         if (global.params.objname && files.dim > 1 && !singleObj)
396         {
397             error("multiple source files, but only one .obj name");
398             fatal();
399         }
400     }
401
402     // create a proper target
403     Ir ir;
404
405     // check -m32/64 sanity
406     if (m32bits && m64bits)
407         error("cannot use both -m32 and -m64 options");
408     else if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty()))
409         error("-m32 and -m64 switches cannot be used together with -march and -mtriple switches");
410     if (global.errors)
411         fatal();
412
413     // override triple if needed
414     const char* defaultTriple = DEFAULT_TARGET_TRIPLE;
415     if ((sizeof(void*) == 4 && m64bits) || (sizeof(void*) == 8 && m32bits))
416     {
417         defaultTriple = DEFAULT_ALT_TARGET_TRIPLE;
418     }
419
420     // did the user override the target triple?
421     if (mTargetTriple.empty())
422     {
423         if (!mArch.empty())
424         {
425             error("you must specify a target triple as well with -mtriple when using the -march option");
426             fatal();
427         }
428         global.params.targetTriple = defaultTriple;
429     }
430     else
431     {
432         global.params.targetTriple = mTargetTriple.c_str();
433     }
434
435     std::string triple = global.params.targetTriple;
436
437     // Allocate target machine.
438
439     // first initialize llvm
440 #define LLVM_TARGET(A) LLVMInitialize##A##TargetInfo(); LLVMInitialize##A##Target(); LLVMInitialize##A##AsmPrinter();
441 // this is defined to be LLVM_TARGET(target name 1) LLVM_TARGET(target name 2) ...
442 LDC_TARGETS
443 #undef LLVM_TARGET
444
445     const llvm::Target *theTarget = NULL;
446     // Check whether the user has explicitly specified an architecture to compile for.
447     if (mArch.empty())
448     {
449         std::string Err;
450         theTarget = llvm::TargetRegistry::lookupTarget(triple, Err);
451         if (theTarget == 0)
452         {
453             error("failed to auto-select target: %s, please use the -march option", Err.c_str());
454             fatal();
455         }
456     }
457     else
458     {
459         for (llvm::TargetRegistry::iterator it = llvm::TargetRegistry::begin(),
460              ie = llvm::TargetRegistry::end(); it != ie; ++it)
461         {
462             if (mArch == it->getName())
463             {
464                 theTarget = &*it;
465                 break;
466             }
467         }
468
469         if (!theTarget)
470         {
471             error("invalid target '%s'", mArch.c_str());
472             fatal();
473         }
474     }
475
476     // Package up features to be passed to target/subtarget
477     std::string FeaturesStr;
478     if (mCPU.size() || mAttrs.size())
479     {
480         llvm::SubtargetFeatures Features;
481         Features.setCPU(mCPU);
482         for (unsigned i = 0; i != mAttrs.size(); ++i)
483         Features.AddFeature(mAttrs[i]);
484         FeaturesStr = Features.getString();
485     }
486
487     // FIXME
488     //std::auto_ptr<llvm::TargetMachine> target(theTarget->createTargetMachine(triple, FeaturesStr));
489     //assert(target.get() && "Could not allocate target machine!");
490     //gTargetMachine = target.get();
491
492     llvm::TargetMachine* target = theTarget->createTargetMachine(triple, FeaturesStr);
493     gTargetMachine = target;
494
495     gTargetData = target->getTargetData();
496
497     // get final data layout
498     std::string datalayout = gTargetData->getStringRepresentation();
499     global.params.dataLayout = datalayout.c_str();
500
501     global.params.llvmArch = theTarget->getName();
502
503     if (strcmp(global.params.llvmArch,"x86")==0) {
504         VersionCondition::addPredefinedGlobalIdent("X86");
505         global.params.isLE = true;
506         global.params.is64bit = false;
507         global.params.cpu = ARCHx86;
508         if (global.params.useInlineAsm) {
509             VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
510         }
511     }
512     else if (strcmp(global.params.llvmArch,"x86-64")==0) {
513         VersionCondition::addPredefinedGlobalIdent("X86_64");
514         global.params.isLE = true;
515         global.params.is64bit = true;
516         global.params.cpu = ARCHx86_64;
517         if (global.params.useInlineAsm) {
518             VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86_64");
519         }
520     }
521     else if (strcmp(global.params.llvmArch,"ppc32")==0) {
522         VersionCondition::addPredefinedGlobalIdent("PPC");
523         global.params.isLE = false;
524         global.params.is64bit = false;
525         global.params.cpu = ARCHppc;
526     }
527     else if (strcmp(global.params.llvmArch,"ppc64")==0) {
528         VersionCondition::addPredefinedGlobalIdent("PPC64");
529         global.params.isLE = false;
530         global.params.is64bit = true;
531         global.params.cpu = ARCHppc_64;
532     }
533     else if (strcmp(global.params.llvmArch,"arm")==0) {
534         VersionCondition::addPredefinedGlobalIdent("ARM");
535         global.params.isLE = true;
536         global.params.is64bit = false;
537         global.params.cpu = ARCHarm;
538     }
539     else if (strcmp(global.params.llvmArch,"thumb")==0) {
540         VersionCondition::addPredefinedGlobalIdent("Thumb");
541         global.params.isLE = true;
542         global.params.is64bit = false;
543         global.params.cpu = ARCHthumb;
544     }
545     else {
546         error("invalid cpu architecture specified: %s", global.params.llvmArch);
547         fatal();
548     }
549
550     // endianness
551     if (global.params.isLE) {
552         VersionCondition::addPredefinedGlobalIdent("LittleEndian");
553     }
554     else {
555         VersionCondition::addPredefinedGlobalIdent("BigEndian");
556     }
557
558     // a generic 64bit version
559     if (global.params.is64bit) {
560         VersionCondition::addPredefinedGlobalIdent("LLVM64");
561         // FIXME: is this always correct?
562         VersionCondition::addPredefinedGlobalIdent("D_LP64");
563     }
564
565     // parse the OS out of the target triple
566     // see http://gcc.gnu.org/install/specific.html for details
567     // also llvm's different SubTargets have useful information
568     size_t npos = std::string::npos;
569
570     // windows
571     // FIXME: win64
572     if (triple.find("windows") != npos || triple.find("win32") != npos || triple.find("mingw") != npos)
573     {
574         global.params.os = OSWindows;
575         VersionCondition::addPredefinedGlobalIdent("Windows");
576         VersionCondition::addPredefinedGlobalIdent("Win32");
577         VersionCondition::addPredefinedGlobalIdent("mingw32");
578     }
579     // FIXME: cygwin
580     else if (triple.find("cygwin") != npos)
581     {
582         error("CygWin is not yet supported");
583         fatal();
584     }
585     // linux
586     else if (triple.find("linux") != npos)
587     {
588         global.params.os = OSLinux;
589         VersionCondition::addPredefinedGlobalIdent("linux");
590         VersionCondition::addPredefinedGlobalIdent("Posix");
591     }
592     // darwin
593     else if (triple.find("-darwin") != npos)
594     {
595         global.params.os = OSMacOSX;
596         VersionCondition::addPredefinedGlobalIdent("OSX");
597         VersionCondition::addPredefinedGlobalIdent("darwin");
598         VersionCondition::addPredefinedGlobalIdent("Posix");
599     }
600     // freebsd
601     else if (triple.find("-freebsd") != npos)
602     {
603         global.params.os = OSFreeBSD;
604         VersionCondition::addPredefinedGlobalIdent("freebsd");
605         VersionCondition::addPredefinedGlobalIdent("FreeBSD");
606         VersionCondition::addPredefinedGlobalIdent("Posix");
607     }
608     // solaris
609     else if (triple.find("-solaris") != npos)
610     {
611         global.params.os = OSSolaris;
612         VersionCondition::addPredefinedGlobalIdent("solaris");
613         VersionCondition::addPredefinedGlobalIdent("Solaris");
614         VersionCondition::addPredefinedGlobalIdent("Posix");
615     }
616     // unsupported
617     else
618     {
619         error("target '%s' is not yet supported", global.params.targetTriple);
620         fatal();
621     }
622
623     // added in 1.039
624     if (global.params.doDocComments)
625         VersionCondition::addPredefinedGlobalIdent("D_Ddoc");
626
627 #if DMDV2
628     // unittests?
629     if (global.params.useUnitTests)
630         VersionCondition::addPredefinedGlobalIdent("unittest");
631 #endif
632
633     // Initialization
634     Type::init(&ir);
635     Id::initialize();
636     Module::init();
637     initPrecedence();
638
639     backend_init();
640
641     //printf("%d source files\n",files.dim);
642
643     // Build import search path
644     if (global.params.imppath)
645     {
646         for (int i = 0; i < global.params.imppath->dim; i++)
647         {
648             char *path = (char *)global.params.imppath->data[i];
649             Array *a = FileName::splitPath(path);
650
651             if (a)
652             {
653                 if (!global.path)
654                     global.path = new Array();
655                 global.path->append(a);
656             }
657         }
658     }
659
660     // Build string import search path
661     if (global.params.fileImppath)
662     {
663         for (int i = 0; i < global.params.fileImppath->dim; i++)
664         {
665             char *path = (char *)global.params.fileImppath->data[i];
666             Array *a = FileName::splitPath(path);
667
668             if (a)
669             {
670                 if (!global.filePath)
671                     global.filePath = new Array();
672                 global.filePath->append(a);
673             }
674         }
675     }
676
677     // Create Modules
678     Array modules;
679     modules.reserve(files.dim);
680     for (int i = 0; i < files.dim; i++)
681     {   Identifier *id;
682         char *ext;
683         char *name;
684
685         p = (char *) files.data[i];
686
687         p = FileName::name(p);      // strip path
688         ext = FileName::ext(p);
689         if (ext)
690         {
691 #if POSIX
692             if (strcmp(ext, global.obj_ext) == 0 ||
693             strcmp(ext, global.bc_ext) == 0)
694 #else
695             if (stricmp(ext, global.obj_ext) == 0 ||
696             stricmp(ext, global.bc_ext) == 0)
697 #endif
698             {
699                 global.params.objfiles->push(files.data[i]);
700                 continue;
701             }
702
703 #if POSIX
704             if (strcmp(ext, "a") == 0)
705 #elif __MINGW32__
706             if (stricmp(ext, "a") == 0)
707 #else
708             if (stricmp(ext, "lib") == 0)
709 #endif
710             {
711                 global.params.libfiles->push(files.data[i]);
712                 continue;
713             }
714
715             if (strcmp(ext, global.ddoc_ext) == 0)
716             {
717                 global.params.ddocfiles->push(files.data[i]);
718                 continue;
719             }
720
721 #if !POSIX
722             if (stricmp(ext, "res") == 0)
723             {
724                 global.params.resfile = (char *)files.data[i];
725                 continue;
726             }
727
728             if (stricmp(ext, "def") == 0)
729             {
730                 global.params.deffile = (char *)files.data[i];
731                 continue;
732             }
733
734             if (stricmp(ext, "exe") == 0)
735             {
736                 global.params.exefile = (char *)files.data[i];
737                 continue;
738             }
739 #endif
740
741             if (stricmp(ext, global.mars_ext) == 0 ||
742             stricmp(ext, global.hdr_ext) == 0 ||
743             stricmp(ext, "htm") == 0 ||
744             stricmp(ext, "html") == 0 ||
745             stricmp(ext, "xhtml") == 0)
746             {
747                 ext--;          // skip onto '.'
748                 assert(*ext == '.');
749                 name = (char *)mem.malloc((ext - p) + 1);
750                 memcpy(name, p, ext - p);
751                 name[ext - p] = 0;      // strip extension
752
753                 if (name[0] == 0 ||
754                     strcmp(name, "..") == 0 ||
755                     strcmp(name, ".") == 0)
756                 {
757             Linvalid:
758                     error("invalid file name '%s'", (char *)files.data[i]);
759                     fatal();
760                 }
761             }
762             else
763             {   error("unrecognized file extension %s\n", ext);
764                 fatal();
765             }
766         }
767         else
768         {   name = p;
769             if (!*name)
770             goto Linvalid;
771         }
772
773         id = new Identifier(name, 0);
774         m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration);
775         modules.push(m);
776     }
777
778     // Read files, parse them
779     for (int i = 0; i < modules.dim; i++)
780     {
781         m = (Module *)modules.data[i];
782         if (global.params.verbose)
783             printf("parse     %s\n", m->toChars());
784         if (!Module::rootModule)
785             Module::rootModule = m;
786         m->importedFrom = m;
787         m->read(0);
788         m->parse();
789         m->buildTargetFiles(singleObj);
790         m->deleteObjFile();
791         if (m->isDocFile)
792         {
793             m->gendocfile();
794
795             // Remove m from list of modules
796             modules.remove(i);
797             i--;
798         }
799     }
800     if (global.errors)
801         fatal();
802 #ifdef _DH
803     if (global.params.doHdrGeneration)
804     {
805         /* Generate 'header' import files.
806          * Since 'header' import files must be independent of command
807          * line switches and what else is imported, they are generated
808          * before any semantic analysis.
809          */
810         for (int i = 0; i < modules.dim; i++)
811         {
812             m = (Module *)modules.data[i];
813             if (global.params.verbose)
814                 printf("import    %s\n", m->toChars());
815             m->genhdrfile();
816         }
817     }
818     if (global.errors)
819         fatal();
820 #endif
821
822     // load all unconditional imports for better symbol resolving
823     for (int i = 0; i < modules.dim; i++)
824     {
825        m = (Module *)modules.data[i];
826        if (global.params.verbose)
827            printf("importall %s\n", m->toChars());
828        m->importAll(0);
829     }
830     if (global.errors)
831        fatal();
832
833     // Do semantic analysis
834     for (int i = 0; i < modules.dim; i++)
835     {
836         m = (Module *)modules.data[i];
837         if (global.params.verbose)
838             printf("semantic  %s\n", m->toChars());
839         m->semantic();
840     }
841     if (global.errors)
842         fatal();
843
844     // Do pass 2 semantic analysis
845     for (int i = 0; i < modules.dim; i++)
846     {
847         m = (Module *)modules.data[i];
848         if (global.params.verbose)
849             printf("semantic2 %s\n", m->toChars());
850         m->semantic2();
851     }
852     if (global.errors)
853         fatal();
854
855     // Do pass 3 semantic analysis
856     for (int i = 0; i < modules.dim; i++)
857     {
858         m = (Module *)modules.data[i];
859         if (global.params.verbose)
860             printf("semantic3 %s\n", m->toChars());
861         m->semantic3();
862     }
863     if (global.errors)
864         fatal();
865
866 #if !IN_LLVM
867     // Scan for functions to inline
868     if (global.params.useInline)
869     {
870         /* The problem with useArrayBounds and useAssert is that the
871          * module being linked to may not have generated them, so if
872          * we inline functions from those modules, the symbols for them will
873          * not be found at link time.
874          */
875         if (!global.params.useArrayBounds && !global.params.useAssert)
876 #else
877     // This doesn't play nice with debug info at the moment
878     if (!global.params.symdebug && willInline())
879     {
880         global.params.useAvailableExternally = true;
881         Logger::println("Running some extra semantic3's for inlining purposes");
882 #endif
883         {
884             // Do pass 3 semantic analysis on all imported modules,
885             // since otherwise functions in them cannot be inlined
886             for (int i = 0; i < Module::amodules.dim; i++)
887             {
888                 m = (Module *)Module::amodules.data[i];
889                 if (global.params.verbose)
890                     printf("semantic3 %s\n", m->toChars());
891                 m->semantic3();
892             }
893             if (global.errors)
894                 fatal();
895         }
896
897 #if !IN_LLVM
898         for (int i = 0; i < modules.dim; i++)
899         {
900             m = (Module *)modules.data[i];
901             if (global.params.verbose)
902                 printf("inline scan %s\n", m->toChars());
903             m->inlineScan();
904         }
905 #endif
906     }
907     if (global.errors)
908         fatal();
909
910     // write module dependencies to file if requested
911     if (global.params.moduleDepsFile != NULL)
912     {
913         assert (global.params.moduleDepsFile != NULL);
914
915         File deps(global.params.moduleDepsFile);
916         OutBuffer* ob = global.params.moduleDeps;
917         deps.setbuffer((void*)ob->data, ob->offset);
918         deps.write();
919     }
920
921     // collects llvm modules to be linked if singleobj is passed
922     std::vector<llvm::Module*> llvmModules;
923     llvm::LLVMContext& context = llvm::getGlobalContext();
924
925     // Generate output files
926     for (int i = 0; i < modules.dim; i++)
927     {
928         m = (Module *)modules.data[i];
929         if (global.params.verbose)
930             printf("code      %s\n", m->toChars());
931         if (global.params.obj)
932         {
933             llvm::Module* lm = m->genLLVMModule(context, &ir);
934             if (!singleObj)
935             {
936                 m->deleteObjFile();
937                 writeModule(lm, m->objfile->name->str);
938                 global.params.objfiles->push(m->objfile->name->str);
939                 delete lm;
940             }
941             else
942                 llvmModules.push_back(lm);
943         }
944         if (global.errors)
945             m->deleteObjFile();
946         else
947         {
948             if (global.params.doDocComments)
949             m->gendocfile();
950         }
951     }
952
953     // internal linking for singleobj
954     if (singleObj && llvmModules.size() > 0)
955     {
956         Module* m = (Module*)modules.data[0];
957         char* name = m->toChars();
958         char* filename = m->objfile->name->str;
959
960         llvm::Linker linker(name, name, context);
961
962         std::string errormsg;
963         for (int i = 0; i < llvmModules.size(); i++)
964         {
965             if(linker.LinkInModule(llvmModules[i], &errormsg))
966                 error("%s", errormsg.c_str());
967             delete llvmModules[i];
968         }
969
970         m->deleteObjFile();
971         writeModule(linker.getModule(), filename);
972         global.params.objfiles->push(filename);
973     }
974
975     backend_term();
976     if (global.errors)
977         fatal();
978
979     if (!global.params.objfiles->dim)
980     {
981         if (global.params.link)
982             error("no object files to link");
983     }
984     else
985     {
986         if (global.params.link)
987             status = linkObjToExecutable(global.params.argv0);
988
989         if (global.params.run)
990         {
991             if (!status)
992             {
993                 status = runExecutable();
994
995                 /* Delete .obj files and .exe file
996                  */
997                 for (int i = 0; i < modules.dim; i++)
998                 {
999                     m = (Module *)modules.data[i];
1000                     m->deleteObjFile();
1001                 }
1002                 deleteExecutable();
1003             }
1004         }
1005     }
1006
1007     return status;
1008 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.