comparison dmd/mars.c @ 988:2667e3a145be

- Fixed LLVM style CL args for D2. - Moved main() into its own file gen/main.cpp - Fixed basic cross compilation - removed the option for setting OS - added support for llc's mattr, mcpu and mtriple switches - added basic ABI abstraction for return value rewrites, it's not perfect and will probably be completely rewritten once I get to handling parameter rewrites as well. - x86-64 extern(C) abi for cfloat returns now match (llvm-)gcc.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Thu, 26 Feb 2009 14:11:49 +0100
parents a8cb25d478c4
children f0b6549055ab
comparison
equal deleted inserted replaced
987:73ff89728d85 988:2667e3a145be
34 #include "id.h" 34 #include "id.h"
35 #include "cond.h" 35 #include "cond.h"
36 #include "expression.h" 36 #include "expression.h"
37 #include "lexer.h" 37 #include "lexer.h"
38 38
39 #include "gen/logger.h"
40 #include "gen/linker.h"
41 #include "revisions.h" 39 #include "revisions.h"
42
43 #include "gen/cl_options.h"
44 #include "gen/cl_helpers.h"
45 using namespace opts;
46
47
48 static cl::opt<bool> forceBE("forcebe",
49 cl::desc("Force big-endian"),
50 cl::Hidden,
51 cl::ZeroOrMore);
52
53 static cl::opt<bool> noDefaultLib("nodefaultlib",
54 cl::desc("Don't add a default library for linking implicitly"),
55 cl::ZeroOrMore);
56
57 static ArrayAdapter impPathsStore("I", global.params.imppath);
58 static cl::list<std::string, ArrayAdapter> importPaths("I",
59 cl::desc("Where to look for imports"),
60 cl::value_desc("path"),
61 cl::location(impPathsStore),
62 cl::Prefix);
63
64 static ArrayAdapter defaultLibStore("defaultlib", global.params.defaultlibnames);
65 static cl::list<std::string, ArrayAdapter> defaultlibs("defaultlib",
66 cl::desc("Set default libraries for non-debug build"),
67 cl::value_desc("lib,..."),
68 cl::location(defaultLibStore),
69 cl::CommaSeparated);
70
71 static ArrayAdapter debugLibStore("debuglib", global.params.debuglibnames);
72 static cl::list<std::string, ArrayAdapter> debuglibs("debuglib",
73 cl::desc("Set default libraries for debug build"),
74 cl::value_desc("lib,..."),
75 cl::location(debugLibStore),
76 cl::CommaSeparated);
77
78
79 void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
80 40
81 Global global; 41 Global global;
82 42
83 Global::Global() 43 Global::Global()
84 { 44 {
184 { 144 {
185 #ifdef DEBUG 145 #ifdef DEBUG
186 *(char*)0=0; 146 *(char*)0=0;
187 #endif 147 #endif
188 } 148 }
189
190 extern void backend_init();
191 extern void backend_term();
192
193 void printVersion() {
194 printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n",
195 global.ldc_version, global.version, global.llvm_version, global.copyright, global.written);
196 printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n"
197 "LDC Homepage: http://www.dsource.org/projects/ldc\n");
198 }
199
200 // Helper function to handle -d-debug=* and -d-version=*
201 static void processVersions(std::vector<std::string>& list, char* type,
202 void (*setLevel)(unsigned), void (*addIdent)(char*)) {
203 typedef std::vector<std::string>::iterator It;
204
205 for(It I = list.begin(), E = list.end(); I != E; ++I) {
206 const char* value = I->c_str();
207 if (isdigit(value[0])) {
208 errno = 0;
209 char* end;
210 long level = strtol(value, &end, 10);
211 if (*end || errno || level > INT_MAX) {
212 error("Invalid %s level: %s", type, I->c_str());
213 } else {
214 setLevel((unsigned)level);
215 }
216 } else {
217 char* cstr = mem.strdup(value);
218 if (Lexer::isValidIdentifier(cstr)) {
219 addIdent(cstr);
220 continue;
221 } else {
222 error("Invalid %s identifier or level: '%s'", type, I->c_str());
223 }
224 }
225 }
226 }
227
228 // Helper function to handle -of, -od, etc.
229 static void initFromString(char*& dest, const cl::opt<std::string>& src) {
230 dest = 0;
231 if (src.getNumOccurrences() != 0) {
232 if (src.empty())
233 error("Expected argument to '-%s'", src.ArgStr);
234 dest = mem.strdup(src.c_str());
235 }
236 }
237
238 int main(int argc, char *argv[])
239 {
240 int i;
241 Array files;
242 char *p, *ext;
243 Module *m;
244 int status = EXIT_SUCCESS;
245
246 // Set default values
247 #if _WIN32
248 char buf[MAX_PATH];
249 GetModuleFileName(NULL, buf, MAX_PATH);
250 global.params.argv0 = buf;
251 #else
252 global.params.argv0 = argv[0];
253 #endif
254 global.params.useSwitchError = 1;
255
256 global.params.linkswitches = new Array();
257 global.params.libfiles = new Array();
258 global.params.objfiles = new Array();
259 global.params.ddocfiles = new Array();
260
261 global.params.is64bit = sizeof(void*) == 8 ? 1 : 0;
262
263 uint16_t endiantest = 0xFF00;
264 uint8_t endianres = ((uint8_t*)&endiantest)[0];
265 if (endianres == 0x00)
266 global.params.isLE = true;
267 else if (endianres == 0xFF)
268 global.params.isLE = false;
269 else {
270 error("Endian test is broken");
271 fatal();
272 }
273
274 // Predefine version identifiers
275 #if IN_LLVM
276 VersionCondition::addPredefinedGlobalIdent("LLVM");
277 VersionCondition::addPredefinedGlobalIdent("LDC");
278 #endif
279
280 // setup default target os to be build os
281 #if _WIN32
282 global.params.os = OSWindows;
283 #elif linux
284 global.params.os = OSLinux;
285 #elif __APPLE__
286 global.params.os = OSMacOSX;
287 #elif __FreeBSD__
288 global.params.os = OSFreeBSD;
289 #elif defined (__SVR4) && defined (__sun)
290 global.params.os = OSSolaris;
291 #else
292 #error Unsupported OS
293 #endif /* linux */
294
295 assert(global.params.os != OSinvalid);
296
297 //VersionCondition::addPredefinedGlobalIdent("D_Bits");
298 VersionCondition::addPredefinedGlobalIdent("all");
299
300 //#if _WIN32
301 // inifile(global.params.argv0, "ldc.ini");
302 //#elif POSIX
303 inifile(global.params.argv0, "ldc.conf");
304 //#else
305 //#error
306 //#endif
307 getenv_setargv("DFLAGS", &argc, &argv);
308
309 #if 0
310 for (i = 0; i < argc; i++)
311 {
312 printf("argv[%d] = '%s'\n", i, argv[i]);
313 }
314 #endif
315
316 cl::SetVersionPrinter(&printVersion);
317 cl::ParseCommandLineOptions(argc, argv, "LLVM-based D Compiler\n");
318
319 global.params.optimize = (global.params.optimizeLevel >= 0);
320
321 // Negated options
322 global.params.link = !compileOnly;
323 global.params.obj = !dontWriteObj;
324 global.params.useInlineAsm = !noAsm;
325
326 // String options: std::string --> char*
327 initFromString(global.params.objname, objectFile);
328 initFromString(global.params.objdir, objectDir);
329
330 initFromString(global.params.docdir, ddocDir);
331 initFromString(global.params.docname, ddocFile);
332 global.params.doDocComments |=
333 global.params.docdir || global.params.docname;
334
335 #ifdef _DH
336 initFromString(global.params.hdrdir, hdrDir);
337 initFromString(global.params.hdrname, hdrFile);
338 global.params.doHdrGeneration |=
339 global.params.hdrdir || global.params.hdrname;
340 #endif
341
342 processVersions(debugArgs, "debug",
343 DebugCondition::setGlobalLevel,
344 DebugCondition::addGlobalIdent);
345 processVersions(versions, "version",
346 VersionCondition::setGlobalLevel,
347 VersionCondition::addGlobalIdent);
348
349 global.params.output_o =
350 opts::output_o == cl::BOU_UNSET
351 ? OUTPUTFLAGdefault
352 : opts::output_o == cl::BOU_TRUE
353 ? OUTPUTFLAGset
354 : OUTPUTFLAGno;
355 global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno;
356 global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno;
357 global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno;
358
359 if (global.params.run || !runargs.empty()) {
360 // FIXME: how to properly detect the presence of a PositionalEatsArgs
361 // option without parameters? We want to emit an error in that case...
362 // You'd think getNumOccurrences would do it, but it just returns the
363 // number of parameters)
364 // NOTE: Hacked around it by detecting -run in getenv_setargv(), where
365 // we're looking for it anyway, and pre-setting the flag...
366 global.params.run = true;
367 if (!runargs.empty()) {
368 files.push(mem.strdup(runargs[0].c_str()));
369 } else {
370 global.params.run = false;
371 error("Expected at least one argument to '-run'\n");
372 }
373 }
374
375 if (mArch)
376 global.params.llvmArch = mArch->Name;
377
378 files.reserve(fileList.size());
379 typedef std::vector<std::string>::iterator It;
380 for(It I = fileList.begin(), E = fileList.end(); I != E; ++I)
381 if (!I->empty())
382 files.push(mem.strdup(I->c_str()));
383
384 if (global.errors)
385 {
386 fatal();
387 }
388 if (files.dim == 0)
389 {
390 cl::PrintHelpMessage();
391 return EXIT_FAILURE;
392 }
393
394 Array* libs;
395 if (global.params.symdebug)
396 libs = global.params.debuglibnames;
397 else
398 libs = global.params.defaultlibnames;
399
400 if (libs)
401 {
402 for (int i = 0; i < libs->dim; i++)
403 {
404 char *arg = (char *)mem.malloc(64);
405 strcpy(arg, "-l");
406 strncat(arg, (char *)libs->data[i], 64);
407 global.params.linkswitches->push(arg);
408 }
409 }
410 else if (!noDefaultLib)
411 {
412 char *arg;
413 arg = (char *)mem.malloc(64);
414 strcpy(arg, "-lldc-runtime");
415 global.params.linkswitches->push(arg);
416 arg = (char *)mem.malloc(64);
417 strcpy(arg, "-ltango-cc-tango");
418 global.params.linkswitches->push(arg);
419 arg = (char *)mem.malloc(64);
420 strcpy(arg, "-ltango-gc-basic");
421 global.params.linkswitches->push(arg);
422 // pass the runtime again to resolve issues
423 // with linking order
424 arg = (char *)mem.malloc(64);
425 strcpy(arg, "-lldc-runtime");
426 global.params.linkswitches->push(arg);
427 }
428
429 if (global.params.run)
430 quiet = 1;
431
432 if (global.params.useUnitTests)
433 global.params.useAssert = 1;
434
435 // LDC output determination
436
437 // if we don't link, autodetect target from extension
438 if(!global.params.link && global.params.objname) {
439 ext = FileName::ext(global.params.objname);
440 bool autofound = false;
441 if (!ext) {
442 // keep things as they are
443 } else if (strcmp(ext, global.ll_ext) == 0) {
444 global.params.output_ll = OUTPUTFLAGset;
445 autofound = true;
446 } else if (strcmp(ext, global.bc_ext) == 0) {
447 global.params.output_bc = OUTPUTFLAGset;
448 autofound = true;
449 } else if (strcmp(ext, global.s_ext) == 0) {
450 global.params.output_s = OUTPUTFLAGset;
451 autofound = true;
452 } else if (strcmp(ext, global.obj_ext) == 0) {
453 global.params.output_o = OUTPUTFLAGset;
454 autofound = true;
455 } else {
456 // append dot, so forceExt won't change existing name even if it contains dots
457 size_t len = strlen(global.params.objname);
458 size_t extlen = strlen(".");
459 char* s = (char *)mem.malloc(len + 1 + extlen + 1);
460 memcpy(s, global.params.objname, len);
461 s[len] = '.';
462 s[len+1+extlen] = 0;
463 global.params.objname = s;
464
465 }
466 if(autofound && global.params.output_o == OUTPUTFLAGdefault)
467 global.params.output_o = OUTPUTFLAGno;
468 }
469
470 // only link if possible
471 if (!global.params.obj || !global.params.output_o)
472 global.params.link = 0;
473
474 if (global.params.link)
475 {
476 global.params.exefile = global.params.objname;
477 if (files.dim > 1)
478 global.params.objname = NULL;
479 }
480 else if (global.params.run)
481 {
482 error("flags conflict with -run");
483 fatal();
484 }
485 else
486 {
487 if (global.params.objname && files.dim > 1)
488 {
489 error("multiple source files, but only one .obj name");
490 fatal();
491 }
492 }
493
494 bool allowForceEndianness = false;
495
496 if (global.params.llvmArch == 0) {
497 #if defined(__x86_64__) || defined(_M_X64)
498 global.params.llvmArch = "x86-64";
499 #elif defined(__i386__) || defined(_M_IX86)
500 global.params.llvmArch = "x86";
501 #elif defined(__ppc__) || defined(_M_PPC)
502 if (global.params.is64bit)
503 global.params.llvmArch = "ppc64";
504 else
505 global.params.llvmArch = "ppc32";
506 #elif defined(__arm__)
507 global.params.llvmArch = "arm";
508 #elif defined(__thumb__)
509 global.params.llvmArch = "thumb";
510 #else
511 #error
512 #endif
513 }
514
515 if (strcmp(global.params.llvmArch,"x86")==0) {
516 VersionCondition::addPredefinedGlobalIdent("X86");
517 global.params.isLE = true;
518 global.params.is64bit = false;
519 global.params.cpu = ARCHx86;
520 if (global.params.useInlineAsm) {
521 VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
522 }
523 }
524 else if (strcmp(global.params.llvmArch,"x86-64")==0) {
525 VersionCondition::addPredefinedGlobalIdent("X86_64");
526 global.params.isLE = true;
527 global.params.is64bit = true;
528 global.params.cpu = ARCHx86_64;
529 if (global.params.useInlineAsm) {
530 VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
531 }
532 }
533 else if (strcmp(global.params.llvmArch,"ppc32")==0) {
534 VersionCondition::addPredefinedGlobalIdent("PPC");
535 global.params.isLE = false;
536 global.params.is64bit = false;
537 global.params.cpu = ARCHppc;
538 }
539 else if (strcmp(global.params.llvmArch,"ppc64")==0) {
540 VersionCondition::addPredefinedGlobalIdent("PPC64");
541 global.params.isLE = false;
542 global.params.is64bit = true;
543 global.params.cpu = ARCHppc_64;
544 }
545 else if (strcmp(global.params.llvmArch,"arm")==0) {
546 VersionCondition::addPredefinedGlobalIdent("ARM");
547 global.params.isLE = true;
548 global.params.is64bit = false;
549 global.params.cpu = ARCHarm;
550 }
551 else if (strcmp(global.params.llvmArch,"thumb")==0) {
552 VersionCondition::addPredefinedGlobalIdent("Thumb");
553 global.params.isLE = true;
554 global.params.is64bit = false;
555 global.params.cpu = ARCHthumb;
556 }
557 else {
558 error("invalid cpu architecture specified: %s", global.params.llvmArch);
559 }
560
561 assert(global.params.cpu != ARCHinvalid);
562
563 if (allowForceEndianness && forceBE) {
564 VersionCondition::addPredefinedGlobalIdent("BigEndian");
565 global.params.isLE = false;
566 }
567 else if (global.params.isLE) {
568 VersionCondition::addPredefinedGlobalIdent("LittleEndian");
569 }
570 else {
571 VersionCondition::addPredefinedGlobalIdent("BigEndian");
572 }
573
574 if (global.params.is64bit) {
575 VersionCondition::addPredefinedGlobalIdent("LLVM64");
576 }
577
578
579 // setup version idents and tt_os for chosen target os
580 switch(global.params.os)
581 {
582 case OSWindows:
583 // TODO Win64 stuff!
584 VersionCondition::addPredefinedGlobalIdent("Windows");
585 VersionCondition::addPredefinedGlobalIdent("Win32");
586 VersionCondition::addPredefinedGlobalIdent("mingw32");
587 break;
588
589 case OSLinux:
590 VersionCondition::addPredefinedGlobalIdent("linux");
591 VersionCondition::addPredefinedGlobalIdent("Posix");
592 break;
593
594 case OSMacOSX:
595 VersionCondition::addPredefinedGlobalIdent("OSX");
596 VersionCondition::addPredefinedGlobalIdent("darwin");
597 VersionCondition::addPredefinedGlobalIdent("Posix");
598 break;
599
600 case OSFreeBSD:
601 VersionCondition::addPredefinedGlobalIdent("freebsd");
602 VersionCondition::addPredefinedGlobalIdent("Posix");
603 break;
604
605 case OSSolaris:
606 VersionCondition::addPredefinedGlobalIdent("solaris");
607 VersionCondition::addPredefinedGlobalIdent("Posix");
608 break;
609
610 default:
611 assert(false && "Target OS not supported");
612 }
613
614 if (!global.params.targetTriple)
615 global.params.targetTriple = DEFAULT_TARGET_TRIPLE;
616
617 Logger::println("Target triple: %s", global.params.targetTriple);
618
619 // build a minimal data layout so llvm can find the target
620 global.params.dataLayout = global.params.isLE
621 ? (char*)(global.params.is64bit ? "e-p:64:64" : "e-p:32:32")
622 : (char*)(global.params.is64bit ? "E-p:64:64" : "E-p:32:32");
623 Logger::println("Layout: %s", global.params.dataLayout);
624
625 // added in 1.039
626 if (global.params.doDocComments)
627 VersionCondition::addPredefinedGlobalIdent("D_Ddoc");
628
629 // Initialization
630 Type::init();
631 Id::initialize();
632 Module::init();
633 initPrecedence();
634
635 backend_init();
636
637 //printf("%d source files\n",files.dim);
638
639 // Build import search path
640 if (global.params.imppath)
641 {
642 for (i = 0; i < global.params.imppath->dim; i++)
643 {
644 char *path = (char *)global.params.imppath->data[i];
645 Array *a = FileName::splitPath(path);
646
647 if (a)
648 {
649 if (!global.path)
650 global.path = new Array();
651 global.path->append(a);
652 }
653 }
654 }
655
656 // Build string import search path
657 if (global.params.fileImppath)
658 {
659 for (i = 0; i < global.params.fileImppath->dim; i++)
660 {
661 char *path = (char *)global.params.fileImppath->data[i];
662 Array *a = FileName::splitPath(path);
663
664 if (a)
665 {
666 if (!global.filePath)
667 global.filePath = new Array();
668 global.filePath->append(a);
669 }
670 }
671 }
672
673 // Create Modules
674 Array modules;
675 modules.reserve(files.dim);
676 for (i = 0; i < files.dim; i++)
677 { Identifier *id;
678 char *ext;
679 char *name;
680
681 p = (char *) files.data[i];
682
683 p = FileName::name(p); // strip path
684 ext = FileName::ext(p);
685 if (ext)
686 {
687 #if POSIX
688 if (strcmp(ext, global.obj_ext) == 0 ||
689 strcmp(ext, global.bc_ext) == 0)
690 #else
691 if (stricmp(ext, global.obj_ext) == 0 ||
692 stricmp(ext, global.bc_ext) == 0)
693 #endif
694 {
695 global.params.objfiles->push(files.data[i]);
696 continue;
697 }
698
699 #if POSIX
700 if (strcmp(ext, "a") == 0)
701 #elif __MINGW32__
702 if (stricmp(ext, "a") == 0)
703 #else
704 if (stricmp(ext, "lib") == 0)
705 #endif
706 {
707 global.params.libfiles->push(files.data[i]);
708 continue;
709 }
710
711 if (strcmp(ext, global.ddoc_ext) == 0)
712 {
713 global.params.ddocfiles->push(files.data[i]);
714 continue;
715 }
716
717 #if !POSIX
718 if (stricmp(ext, "res") == 0)
719 {
720 global.params.resfile = (char *)files.data[i];
721 continue;
722 }
723
724 if (stricmp(ext, "def") == 0)
725 {
726 global.params.deffile = (char *)files.data[i];
727 continue;
728 }
729
730 if (stricmp(ext, "exe") == 0)
731 {
732 global.params.exefile = (char *)files.data[i];
733 continue;
734 }
735 #endif
736
737 if (stricmp(ext, global.mars_ext) == 0 ||
738 stricmp(ext, global.hdr_ext) == 0 ||
739 stricmp(ext, "htm") == 0 ||
740 stricmp(ext, "html") == 0 ||
741 stricmp(ext, "xhtml") == 0)
742 {
743 ext--; // skip onto '.'
744 assert(*ext == '.');
745 name = (char *)mem.malloc((ext - p) + 1);
746 memcpy(name, p, ext - p);
747 name[ext - p] = 0; // strip extension
748
749 if (name[0] == 0 ||
750 strcmp(name, "..") == 0 ||
751 strcmp(name, ".") == 0)
752 {
753 Linvalid:
754 error("invalid file name '%s'", (char *)files.data[i]);
755 fatal();
756 }
757 }
758 else
759 { error("unrecognized file extension %s\n", ext);
760 fatal();
761 }
762 }
763 else
764 { name = p;
765 if (!*name)
766 goto Linvalid;
767 }
768
769 id = new Identifier(name, 0);
770 m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration);
771 modules.push(m);
772 }
773
774 // Read files, parse them
775 for (i = 0; i < modules.dim; i++)
776 {
777 m = (Module *)modules.data[i];
778 if (global.params.verbose)
779 printf("parse %s\n", m->toChars());
780 if (!Module::rootModule)
781 Module::rootModule = m;
782 m->importedFrom = m;
783 m->read(0);
784 m->parse();
785 m->buildTargetFiles();
786 m->deleteObjFile();
787 if (m->isDocFile)
788 {
789 m->gendocfile();
790
791 // Remove m from list of modules
792 modules.remove(i);
793 i--;
794 }
795 }
796 if (global.errors)
797 fatal();
798 #ifdef _DH
799 if (global.params.doHdrGeneration)
800 {
801 /* Generate 'header' import files.
802 * Since 'header' import files must be independent of command
803 * line switches and what else is imported, they are generated
804 * before any semantic analysis.
805 */
806 for (i = 0; i < modules.dim; i++)
807 {
808 m = (Module *)modules.data[i];
809 if (global.params.verbose)
810 printf("import %s\n", m->toChars());
811 m->genhdrfile();
812 }
813 }
814 if (global.errors)
815 fatal();
816 #endif
817
818 // Do semantic analysis
819 for (i = 0; i < modules.dim; i++)
820 {
821 m = (Module *)modules.data[i];
822 if (global.params.verbose)
823 printf("semantic %s\n", m->toChars());
824 m->semantic();
825 }
826 if (global.errors)
827 fatal();
828
829 // Do pass 2 semantic analysis
830 for (i = 0; i < modules.dim; i++)
831 {
832 m = (Module *)modules.data[i];
833 if (global.params.verbose)
834 printf("semantic2 %s\n", m->toChars());
835 m->semantic2();
836 }
837 if (global.errors)
838 fatal();
839
840 // Do pass 3 semantic analysis
841 for (i = 0; i < modules.dim; i++)
842 {
843 m = (Module *)modules.data[i];
844 if (global.params.verbose)
845 printf("semantic3 %s\n", m->toChars());
846 m->semantic3();
847 }
848 if (global.errors)
849 fatal();
850
851 #if !IN_LLVM
852 // Scan for functions to inline
853 if (global.params.useInline)
854 {
855 /* The problem with useArrayBounds and useAssert is that the
856 * module being linked to may not have generated them, so if
857 * we inline functions from those modules, the symbols for them will
858 * not be found at link time.
859 */
860 if (!global.params.useArrayBounds && !global.params.useAssert)
861 {
862 #endif
863 // Do pass 3 semantic analysis on all imported modules,
864 // since otherwise functions in them cannot be inlined
865 for (i = 0; i < Module::amodules.dim; i++)
866 {
867 m = (Module *)Module::amodules.data[i];
868 if (global.params.verbose)
869 printf("semantic3 %s\n", m->toChars());
870 m->semantic3();
871 }
872 if (global.errors)
873 fatal();
874 #if !IN_LLVM
875 }
876
877 for (i = 0; i < modules.dim; i++)
878 {
879 m = (Module *)modules.data[i];
880 if (global.params.verbose)
881 printf("inline scan %s\n", m->toChars());
882 m->inlineScan();
883 }
884 }
885 #endif
886 if (global.errors)
887 fatal();
888
889 // Generate output files
890 for (i = 0; i < modules.dim; i++)
891 {
892 m = (Module *)modules.data[i];
893 if (global.params.verbose)
894 printf("code %s\n", m->toChars());
895 if (global.params.obj)
896 {
897 m->genobjfile(0);
898 global.params.objfiles->push(m->objfile->name->str);
899 }
900 if (global.errors)
901 m->deleteObjFile();
902 else
903 {
904 if (global.params.doDocComments)
905 m->gendocfile();
906 }
907 }
908
909 backend_term();
910 if (global.errors)
911 fatal();
912
913 if (!global.params.objfiles->dim)
914 {
915 if (global.params.link)
916 error("no object files to link");
917 }
918 else
919 {
920 if (global.params.link)
921 //status = runLINK();
922 linkObjToExecutable(global.params.argv0);
923
924 if (global.params.run)
925 {
926 if (!status)
927 {
928 status = runExectuable();
929
930 /* Delete .obj files and .exe file
931 */
932 for (i = 0; i < modules.dim; i++)
933 {
934 m = (Module *)modules.data[i];
935 m->deleteObjFile();
936 }
937 deleteExecutable();
938 }
939 }
940 }
941
942 return status;
943 }
944
945
946 149
947 /*********************************** 150 /***********************************
948 * Parse and append contents of environment variable envvar 151 * Parse and append contents of environment variable envvar
949 * to argc and argv[]. 152 * to argc and argv[].
950 * The string is separated into arguments, processing \ and ". 153 * The string is separated into arguments, processing \ and ".