comparison gen/main.cpp @ 989:420ef073448d

Forgot new files that were supposed to be in last commit.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Thu, 26 Feb 2009 14:13:27 +0100
parents
children 4f12ec3216cf
comparison
equal deleted inserted replaced
988:2667e3a145be 989:420ef073448d
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 "llvm/Target/SubtargetFeature.h"
8 #include "llvm/Target/TargetMachine.h"
9 #include "llvm/Target/TargetMachineRegistry.h"
10 #include "llvm/LinkAllVMCore.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <assert.h>
15 #include <limits.h>
16
17 #if POSIX
18 #include <errno.h>
19 #elif _WIN32
20 #include <windows.h>
21 #endif
22
23 #include "mem.h"
24 #include "root.h"
25
26 #include "mars.h"
27 #include "module.h"
28 #include "mtype.h"
29 #include "id.h"
30 #include "cond.h"
31
32 #include "gen/logger.h"
33 #include "gen/linker.h"
34 #include "gen/irstate.h"
35
36 #include "gen/cl_options.h"
37 #include "gen/cl_helpers.h"
38 using namespace opts;
39
40 extern void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
41 extern void backend_init();
42 extern void backend_term();
43
44 static cl::opt<bool> noDefaultLib("nodefaultlib",
45 cl::desc("Don't add a default library for linking implicitly"),
46 cl::ZeroOrMore);
47
48 static ArrayAdapter impPathsStore("I", global.params.imppath);
49 static cl::list<std::string, ArrayAdapter> importPaths("I",
50 cl::desc("Where to look for imports"),
51 cl::value_desc("path"),
52 cl::location(impPathsStore),
53 cl::Prefix);
54
55 static ArrayAdapter defaultLibStore("defaultlib", global.params.defaultlibnames);
56 static cl::list<std::string, ArrayAdapter> defaultlibs("defaultlib",
57 cl::desc("Set default libraries for non-debug build"),
58 cl::value_desc("lib,..."),
59 cl::location(defaultLibStore),
60 cl::CommaSeparated);
61
62 static ArrayAdapter debugLibStore("debuglib", global.params.debuglibnames);
63 static cl::list<std::string, ArrayAdapter> debuglibs("debuglib",
64 cl::desc("Set default libraries for debug build"),
65 cl::value_desc("lib,..."),
66 cl::location(debugLibStore),
67 cl::CommaSeparated);
68
69 void printVersion() {
70 printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n",
71 global.ldc_version, global.version, global.llvm_version, global.copyright, global.written);
72 printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n"
73 "LDC Homepage: http://www.dsource.org/projects/ldc\n");
74 }
75
76 // Helper function to handle -d-debug=* and -d-version=*
77 static void processVersions(std::vector<std::string>& list, char* type,
78 void (*setLevel)(unsigned), void (*addIdent)(const char*)) {
79 typedef std::vector<std::string>::iterator It;
80
81 for(It I = list.begin(), E = list.end(); I != E; ++I) {
82 const char* value = I->c_str();
83 if (isdigit(value[0])) {
84 errno = 0;
85 char* end;
86 long level = strtol(value, &end, 10);
87 if (*end || errno || level > INT_MAX) {
88 error("Invalid %s level: %s", type, I->c_str());
89 } else {
90 setLevel((unsigned)level);
91 }
92 } else {
93 char* cstr = mem.strdup(value);
94 if (Lexer::isValidIdentifier(cstr)) {
95 addIdent(cstr);
96 continue;
97 } else {
98 error("Invalid %s identifier or level: '%s'", type, I->c_str());
99 }
100 }
101 }
102 }
103
104 // Helper function to handle -of, -od, etc.
105 static void initFromString(char*& dest, const cl::opt<std::string>& src) {
106 dest = 0;
107 if (src.getNumOccurrences() != 0) {
108 if (src.empty())
109 error("Expected argument to '-%s'", src.ArgStr);
110 dest = mem.strdup(src.c_str());
111 }
112 }
113
114 int main(int argc, char** argv)
115 {
116 Array files;
117 char *p, *ext;
118 Module *m;
119 int status = EXIT_SUCCESS;
120
121 // Set some default values
122 #if _WIN32
123 char buf[MAX_PATH];
124 GetModuleFileName(NULL, buf, MAX_PATH);
125 global.params.argv0 = buf;
126 #else
127 global.params.argv0 = argv[0];
128 #endif
129 global.params.useSwitchError = 1;
130
131 global.params.linkswitches = new Array();
132 global.params.libfiles = new Array();
133 global.params.objfiles = new Array();
134 global.params.ddocfiles = new Array();
135
136 // Set predefined version identifiers
137 VersionCondition::addPredefinedGlobalIdent("LLVM");
138 VersionCondition::addPredefinedGlobalIdent("LDC");
139 VersionCondition::addPredefinedGlobalIdent("all");
140
141 // read the inifile
142 #if DMDV2
143 inifile(global.params.argv0, "ldc2.conf");
144 #else
145 inifile(global.params.argv0, "ldc.conf");
146 #endif
147
148 // merge DFLAGS into argc/argv
149 getenv_setargv("DFLAGS", &argc, &argv);
150 #if 0
151 for (int i = 0; i < argc; i++)
152 {
153 printf("argv[%d] = '%s'\n", i, argv[i]);
154 }
155 #endif
156
157 // Handle fixed-up arguments!
158 cl::SetVersionPrinter(&printVersion);
159 cl::ParseCommandLineOptions(argc, argv, "LLVM-based D Compiler\n");
160
161 global.params.optimize = (global.params.optimizeLevel >= 0);
162
163 // Negated options
164 global.params.link = !compileOnly;
165 global.params.obj = !dontWriteObj;
166 global.params.useInlineAsm = !noAsm;
167
168 // String options: std::string --> char*
169 initFromString(global.params.objname, objectFile);
170 initFromString(global.params.objdir, objectDir);
171
172 initFromString(global.params.docdir, ddocDir);
173 initFromString(global.params.docname, ddocFile);
174 global.params.doDocComments |=
175 global.params.docdir || global.params.docname;
176
177 #ifdef _DH
178 initFromString(global.params.hdrdir, hdrDir);
179 initFromString(global.params.hdrname, hdrFile);
180 global.params.doHdrGeneration |=
181 global.params.hdrdir || global.params.hdrname;
182 #endif
183
184 processVersions(debugArgs, "debug",
185 DebugCondition::setGlobalLevel,
186 DebugCondition::addGlobalIdent);
187 processVersions(versions, "version",
188 VersionCondition::setGlobalLevel,
189 VersionCondition::addGlobalIdent);
190
191 global.params.output_o =
192 opts::output_o == cl::BOU_UNSET
193 ? OUTPUTFLAGdefault
194 : opts::output_o == cl::BOU_TRUE
195 ? OUTPUTFLAGset
196 : OUTPUTFLAGno;
197 global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno;
198 global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno;
199 global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno;
200
201 if (global.params.run || !runargs.empty()) {
202 // FIXME: how to properly detect the presence of a PositionalEatsArgs
203 // option without parameters? We want to emit an error in that case...
204 // You'd think getNumOccurrences would do it, but it just returns the
205 // number of parameters)
206 // NOTE: Hacked around it by detecting -run in getenv_setargv(), where
207 // we're looking for it anyway, and pre-setting the flag...
208 global.params.run = true;
209 if (!runargs.empty()) {
210 files.push(mem.strdup(runargs[0].c_str()));
211 } else {
212 global.params.run = false;
213 error("Expected at least one argument to '-run'\n");
214 }
215 }
216
217
218 files.reserve(fileList.size());
219 typedef std::vector<std::string>::iterator It;
220 for(It I = fileList.begin(), E = fileList.end(); I != E; ++I)
221 if (!I->empty())
222 files.push(mem.strdup(I->c_str()));
223
224 if (global.errors)
225 {
226 fatal();
227 }
228 if (files.dim == 0)
229 {
230 cl::PrintHelpMessage();
231 return EXIT_FAILURE;
232 }
233
234 Array* libs;
235 if (global.params.symdebug)
236 libs = global.params.debuglibnames;
237 else
238 libs = global.params.defaultlibnames;
239
240 if (libs)
241 {
242 for (int i = 0; i < libs->dim; i++)
243 {
244 char *arg = (char *)mem.malloc(64);
245 strcpy(arg, "-l");
246 strncat(arg, (char *)libs->data[i], 64);
247 global.params.linkswitches->push(arg);
248 }
249 }
250 else if (!noDefaultLib)
251 {
252 char *arg;
253 arg = (char *)mem.malloc(64);
254 strcpy(arg, "-lldc-runtime");
255 global.params.linkswitches->push(arg);
256 arg = (char *)mem.malloc(64);
257 strcpy(arg, "-ltango-cc-tango");
258 global.params.linkswitches->push(arg);
259 arg = (char *)mem.malloc(64);
260 strcpy(arg, "-ltango-gc-basic");
261 global.params.linkswitches->push(arg);
262 // pass the runtime again to resolve issues
263 // with linking order
264 arg = (char *)mem.malloc(64);
265 strcpy(arg, "-lldc-runtime");
266 global.params.linkswitches->push(arg);
267 }
268
269 if (global.params.run)
270 quiet = 1;
271
272 if (global.params.useUnitTests)
273 global.params.useAssert = 1;
274
275 // LDC output determination
276
277 // if we don't link, autodetect target from extension
278 if(!global.params.link && global.params.objname) {
279 ext = FileName::ext(global.params.objname);
280 bool autofound = false;
281 if (!ext) {
282 // keep things as they are
283 } else if (strcmp(ext, global.ll_ext) == 0) {
284 global.params.output_ll = OUTPUTFLAGset;
285 autofound = true;
286 } else if (strcmp(ext, global.bc_ext) == 0) {
287 global.params.output_bc = OUTPUTFLAGset;
288 autofound = true;
289 } else if (strcmp(ext, global.s_ext) == 0) {
290 global.params.output_s = OUTPUTFLAGset;
291 autofound = true;
292 } else if (strcmp(ext, global.obj_ext) == 0) {
293 global.params.output_o = OUTPUTFLAGset;
294 autofound = true;
295 } else {
296 // append dot, so forceExt won't change existing name even if it contains dots
297 size_t len = strlen(global.params.objname);
298 size_t extlen = strlen(".");
299 char* s = (char *)mem.malloc(len + 1 + extlen + 1);
300 memcpy(s, global.params.objname, len);
301 s[len] = '.';
302 s[len+1+extlen] = 0;
303 global.params.objname = s;
304
305 }
306 if(autofound && global.params.output_o == OUTPUTFLAGdefault)
307 global.params.output_o = OUTPUTFLAGno;
308 }
309
310 // only link if possible
311 if (!global.params.obj || !global.params.output_o)
312 global.params.link = 0;
313
314 if (global.params.link)
315 {
316 global.params.exefile = global.params.objname;
317 if (files.dim > 1)
318 global.params.objname = NULL;
319 }
320 else if (global.params.run)
321 {
322 error("flags conflict with -run");
323 fatal();
324 }
325 else
326 {
327 if (global.params.objname && files.dim > 1)
328 {
329 error("multiple source files, but only one .obj name");
330 fatal();
331 }
332 }
333
334 // create a proper target
335 llvm::Module mod("dummy");
336
337 // did the user override the target triple?
338 if (mTargetTriple.empty())
339 {
340 if (mArch != 0)
341 {
342 error("you must specify a target triple as well with -mtriple when using the -march option");
343 fatal();
344 }
345 global.params.targetTriple = DEFAULT_TARGET_TRIPLE;
346 }
347 else
348 {
349 global.params.targetTriple = mTargetTriple.c_str();
350 }
351
352 mod.setTargetTriple(global.params.targetTriple);
353
354 // Allocate target machine. First, check whether the user has
355 // explicitly specified an architecture to compile for.
356 if (mArch == 0)
357 {
358 std::string Err;
359 mArch = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(mod, Err);
360 if (mArch == 0)
361 {
362 error("failed to auto-select target '%s', please use the -march option");
363 fatal();
364 }
365 }
366
367 // Package up features to be passed to target/subtarget
368 std::string FeaturesStr;
369 if (mCPU.size() || mAttrs.size())
370 {
371 llvm::SubtargetFeatures Features;
372 Features.setCPU(mCPU);
373 for (unsigned i = 0; i != mAttrs.size(); ++i)
374 Features.AddFeature(mAttrs[i]);
375 FeaturesStr = Features.getString();
376 }
377
378 std::auto_ptr<llvm::TargetMachine> target(mArch->CtorFn(mod, FeaturesStr));
379 assert(target.get() && "Could not allocate target machine!");
380 gTargetMachine = target.get();
381 gTargetData = gTargetMachine->getTargetData();
382
383 // get final data layout
384 std::string datalayout = gTargetData->getStringRepresentation();
385 global.params.dataLayout = datalayout.c_str();
386
387 global.params.llvmArch = mArch->Name;
388
389 if (strcmp(global.params.llvmArch,"x86")==0) {
390 VersionCondition::addPredefinedGlobalIdent("X86");
391 global.params.isLE = true;
392 global.params.is64bit = false;
393 global.params.cpu = ARCHx86;
394 if (global.params.useInlineAsm) {
395 VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
396 }
397 }
398 else if (strcmp(global.params.llvmArch,"x86-64")==0) {
399 VersionCondition::addPredefinedGlobalIdent("X86_64");
400 global.params.isLE = true;
401 global.params.is64bit = true;
402 global.params.cpu = ARCHx86_64;
403 if (global.params.useInlineAsm) {
404 VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
405 }
406 }
407 else if (strcmp(global.params.llvmArch,"ppc32")==0) {
408 VersionCondition::addPredefinedGlobalIdent("PPC");
409 global.params.isLE = false;
410 global.params.is64bit = false;
411 global.params.cpu = ARCHppc;
412 }
413 else if (strcmp(global.params.llvmArch,"ppc64")==0) {
414 VersionCondition::addPredefinedGlobalIdent("PPC64");
415 global.params.isLE = false;
416 global.params.is64bit = true;
417 global.params.cpu = ARCHppc_64;
418 }
419 else if (strcmp(global.params.llvmArch,"arm")==0) {
420 VersionCondition::addPredefinedGlobalIdent("ARM");
421 global.params.isLE = true;
422 global.params.is64bit = false;
423 global.params.cpu = ARCHarm;
424 }
425 else if (strcmp(global.params.llvmArch,"thumb")==0) {
426 VersionCondition::addPredefinedGlobalIdent("Thumb");
427 global.params.isLE = true;
428 global.params.is64bit = false;
429 global.params.cpu = ARCHthumb;
430 }
431 else {
432 error("invalid cpu architecture specified: %s", global.params.llvmArch);
433 fatal();
434 }
435
436 // endianness
437 if (global.params.isLE) {
438 VersionCondition::addPredefinedGlobalIdent("LittleEndian");
439 }
440 else {
441 VersionCondition::addPredefinedGlobalIdent("BigEndian");
442 }
443
444 // a generic 64bit version
445 // why isn't this in D to begin with ?
446 if (global.params.is64bit) {
447 VersionCondition::addPredefinedGlobalIdent("LLVM64");
448 }
449
450 // parse the OS out of the target triple
451 // see http://gcc.gnu.org/install/specific.html for details
452 // also llvm's different SubTargets have useful information
453 std::string triple = global.params.targetTriple;
454 size_t npos = std::string::npos;
455
456 // windows
457 // FIXME: win64
458 if (triple.find("windows") != npos || triple.find("win32") != npos || triple.find("mingw") != npos)
459 {
460 global.params.os = OSWindows;
461 VersionCondition::addPredefinedGlobalIdent("Windows");
462 VersionCondition::addPredefinedGlobalIdent("Win32");
463 VersionCondition::addPredefinedGlobalIdent("mingw32");
464 }
465 // FIXME: cygwin
466 else if (triple.find("cygwin") != npos)
467 {
468 error("CygWin is not yet supported");
469 fatal();
470 }
471 // linux
472 else if (triple.find("linux") != npos)
473 {
474 global.params.os = OSLinux;
475 VersionCondition::addPredefinedGlobalIdent("linux");
476 VersionCondition::addPredefinedGlobalIdent("Posix");
477 }
478 // darwin
479 else if (triple.find("-darwin") != npos)
480 {
481 global.params.os = OSMacOSX;
482 VersionCondition::addPredefinedGlobalIdent("OSX");
483 VersionCondition::addPredefinedGlobalIdent("darwin");
484 VersionCondition::addPredefinedGlobalIdent("Posix");
485 }
486 // freebsd
487 else if (triple.find("-freebsd") != npos)
488 {
489 global.params.os = OSFreeBSD;
490 VersionCondition::addPredefinedGlobalIdent("freebsd");
491 VersionCondition::addPredefinedGlobalIdent("Posix");
492 }
493 // solaris
494 else if (triple.find("-solaris") != npos)
495 {
496 global.params.os = OSSolaris;
497 VersionCondition::addPredefinedGlobalIdent("solaris");
498 VersionCondition::addPredefinedGlobalIdent("Posix");
499 }
500 // unsupported
501 else
502 {
503 error("target triple '%s' is not supported", global.params.targetTriple);
504 fatal();
505 }
506
507 // added in 1.039
508 if (global.params.doDocComments)
509 VersionCondition::addPredefinedGlobalIdent("D_Ddoc");
510
511 // Initialization
512 Type::init();
513 Id::initialize();
514 Module::init();
515 initPrecedence();
516
517 backend_init();
518
519 //printf("%d source files\n",files.dim);
520
521 // Build import search path
522 if (global.params.imppath)
523 {
524 for (int i = 0; i < global.params.imppath->dim; i++)
525 {
526 char *path = (char *)global.params.imppath->data[i];
527 Array *a = FileName::splitPath(path);
528
529 if (a)
530 {
531 if (!global.path)
532 global.path = new Array();
533 global.path->append(a);
534 }
535 }
536 }
537
538 // Build string import search path
539 if (global.params.fileImppath)
540 {
541 for (int i = 0; i < global.params.fileImppath->dim; i++)
542 {
543 char *path = (char *)global.params.fileImppath->data[i];
544 Array *a = FileName::splitPath(path);
545
546 if (a)
547 {
548 if (!global.filePath)
549 global.filePath = new Array();
550 global.filePath->append(a);
551 }
552 }
553 }
554
555 // Create Modules
556 Array modules;
557 modules.reserve(files.dim);
558 for (int i = 0; i < files.dim; i++)
559 { Identifier *id;
560 char *ext;
561 char *name;
562
563 p = (char *) files.data[i];
564
565 p = FileName::name(p); // strip path
566 ext = FileName::ext(p);
567 if (ext)
568 {
569 #if POSIX
570 if (strcmp(ext, global.obj_ext) == 0 ||
571 strcmp(ext, global.bc_ext) == 0)
572 #else
573 if (stricmp(ext, global.obj_ext) == 0 ||
574 stricmp(ext, global.bc_ext) == 0)
575 #endif
576 {
577 global.params.objfiles->push(files.data[i]);
578 continue;
579 }
580
581 #if POSIX
582 if (strcmp(ext, "a") == 0)
583 #elif __MINGW32__
584 if (stricmp(ext, "a") == 0)
585 #else
586 if (stricmp(ext, "lib") == 0)
587 #endif
588 {
589 global.params.libfiles->push(files.data[i]);
590 continue;
591 }
592
593 if (strcmp(ext, global.ddoc_ext) == 0)
594 {
595 global.params.ddocfiles->push(files.data[i]);
596 continue;
597 }
598
599 #if !POSIX
600 if (stricmp(ext, "res") == 0)
601 {
602 global.params.resfile = (char *)files.data[i];
603 continue;
604 }
605
606 if (stricmp(ext, "def") == 0)
607 {
608 global.params.deffile = (char *)files.data[i];
609 continue;
610 }
611
612 if (stricmp(ext, "exe") == 0)
613 {
614 global.params.exefile = (char *)files.data[i];
615 continue;
616 }
617 #endif
618
619 if (stricmp(ext, global.mars_ext) == 0 ||
620 stricmp(ext, global.hdr_ext) == 0 ||
621 stricmp(ext, "htm") == 0 ||
622 stricmp(ext, "html") == 0 ||
623 stricmp(ext, "xhtml") == 0)
624 {
625 ext--; // skip onto '.'
626 assert(*ext == '.');
627 name = (char *)mem.malloc((ext - p) + 1);
628 memcpy(name, p, ext - p);
629 name[ext - p] = 0; // strip extension
630
631 if (name[0] == 0 ||
632 strcmp(name, "..") == 0 ||
633 strcmp(name, ".") == 0)
634 {
635 Linvalid:
636 error("invalid file name '%s'", (char *)files.data[i]);
637 fatal();
638 }
639 }
640 else
641 { error("unrecognized file extension %s\n", ext);
642 fatal();
643 }
644 }
645 else
646 { name = p;
647 if (!*name)
648 goto Linvalid;
649 }
650
651 id = new Identifier(name, 0);
652 m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration);
653 modules.push(m);
654 }
655
656 // Read files, parse them
657 for (int i = 0; i < modules.dim; i++)
658 {
659 m = (Module *)modules.data[i];
660 if (global.params.verbose)
661 printf("parse %s\n", m->toChars());
662 if (!Module::rootModule)
663 Module::rootModule = m;
664 m->importedFrom = m;
665 m->read(0);
666 m->parse();
667 m->buildTargetFiles();
668 m->deleteObjFile();
669 if (m->isDocFile)
670 {
671 m->gendocfile();
672
673 // Remove m from list of modules
674 modules.remove(i);
675 i--;
676 }
677 }
678 if (global.errors)
679 fatal();
680 #ifdef _DH
681 if (global.params.doHdrGeneration)
682 {
683 /* Generate 'header' import files.
684 * Since 'header' import files must be independent of command
685 * line switches and what else is imported, they are generated
686 * before any semantic analysis.
687 */
688 for (int i = 0; i < modules.dim; i++)
689 {
690 m = (Module *)modules.data[i];
691 if (global.params.verbose)
692 printf("import %s\n", m->toChars());
693 m->genhdrfile();
694 }
695 }
696 if (global.errors)
697 fatal();
698 #endif
699
700 // Do semantic analysis
701 for (int i = 0; i < modules.dim; i++)
702 {
703 m = (Module *)modules.data[i];
704 if (global.params.verbose)
705 printf("semantic %s\n", m->toChars());
706 m->semantic();
707 }
708 if (global.errors)
709 fatal();
710
711 // Do pass 2 semantic analysis
712 for (int i = 0; i < modules.dim; i++)
713 {
714 m = (Module *)modules.data[i];
715 if (global.params.verbose)
716 printf("semantic2 %s\n", m->toChars());
717 m->semantic2();
718 }
719 if (global.errors)
720 fatal();
721
722 // Do pass 3 semantic analysis
723 for (int i = 0; i < modules.dim; i++)
724 {
725 m = (Module *)modules.data[i];
726 if (global.params.verbose)
727 printf("semantic3 %s\n", m->toChars());
728 m->semantic3();
729 }
730 if (global.errors)
731 fatal();
732
733 #if !IN_LLVM
734 // Scan for functions to inline
735 if (global.params.useInline)
736 {
737 /* The problem with useArrayBounds and useAssert is that the
738 * module being linked to may not have generated them, so if
739 * we inline functions from those modules, the symbols for them will
740 * not be found at link time.
741 */
742 if (!global.params.useArrayBounds && !global.params.useAssert)
743 {
744 #endif
745 // Do pass 3 semantic analysis on all imported modules,
746 // since otherwise functions in them cannot be inlined
747 for (int i = 0; i < Module::amodules.dim; i++)
748 {
749 m = (Module *)Module::amodules.data[i];
750 if (global.params.verbose)
751 printf("semantic3 %s\n", m->toChars());
752 m->semantic3();
753 }
754 if (global.errors)
755 fatal();
756 #if !IN_LLVM
757 }
758
759 for (int i = 0; i < modules.dim; i++)
760 {
761 m = (Module *)modules.data[i];
762 if (global.params.verbose)
763 printf("inline scan %s\n", m->toChars());
764 m->inlineScan();
765 }
766 }
767 #endif
768 if (global.errors)
769 fatal();
770
771 // Generate output files
772 for (int i = 0; i < modules.dim; i++)
773 {
774 m = (Module *)modules.data[i];
775 if (global.params.verbose)
776 printf("code %s\n", m->toChars());
777 if (global.params.obj)
778 {
779 m->genobjfile(0);
780 global.params.objfiles->push(m->objfile->name->str);
781 }
782 if (global.errors)
783 m->deleteObjFile();
784 else
785 {
786 if (global.params.doDocComments)
787 m->gendocfile();
788 }
789 }
790
791 backend_term();
792 if (global.errors)
793 fatal();
794
795 if (!global.params.objfiles->dim)
796 {
797 if (global.params.link)
798 error("no object files to link");
799 }
800 else
801 {
802 if (global.params.link)
803 //status = runLINK();
804 linkObjToExecutable(global.params.argv0);
805
806 if (global.params.run)
807 {
808 if (!status)
809 {
810 status = runExectuable();
811
812 /* Delete .obj files and .exe file
813 */
814 for (int i = 0; i < modules.dim; i++)
815 {
816 m = (Module *)modules.data[i];
817 m->deleteObjFile();
818 }
819 deleteExecutable();
820 }
821 }
822 }
823
824 return status;
825 }