Mercurial > projects > ldc
diff dmd2/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 | 0749c0757a43 |
children | 123812e02bc8 |
line wrap: on
line diff
--- a/dmd2/mars.c Wed Feb 25 19:30:06 2009 +0100 +++ b/dmd2/mars.c Thu Feb 26 14:11:49 2009 +0100 @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -36,13 +36,8 @@ #include "expression.h" #include "lexer.h" -#include "gen/logger.h" -#include "gen/linker.h" - #include "revisions.h" -void getenv_setargv(const char *envvar, int *pargc, char** *pargv); - Global global; Global::Global() @@ -62,27 +57,32 @@ obj_ext_alt = "obj"; #endif - copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen"; + copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; version = "v2.021"; - ldc_version = "0.1"; + ldc_version = LDC_REV; + llvm_version = LLVM_REV; global.structalign = 8; - memset(¶ms, 0, sizeof(Param)); + // This should only be used as a global, so the other fields are + // automatically initialized to zero when the program is loaded. + // In particular, DO NOT zero-initialize .params here (like DMD + // does) because command-line options initialize some of those + // fields to non-zero defaults, and do so from constructors that + // may run before this one. } char *Loc::toChars() const { OutBuffer buf; - char *p; if (filename) { - buf.printf("%s", filename); + buf.printf("%s", filename); } if (linnum) - buf.printf("(%d)", linnum); + buf.printf("(%d)", linnum); buf.writeByte(0); return (char *)buf.extractData(); } @@ -109,16 +109,16 @@ { if (!global.gag) { - char *p = loc.toChars(); + char *p = loc.toChars(); - if (*p) - fprintf(stdmsg, "%s: ", p); - mem.free(p); + if (*p) + fprintf(stdmsg, "%s: ", p); + mem.free(p); - fprintf(stdmsg, "Error: "); - vfprintf(stdmsg, format, ap); - fprintf(stdmsg, "\n"); - fflush(stdmsg); + fprintf(stdmsg, "Error: "); + vfprintf(stdmsg, format, ap); + fprintf(stdmsg, "\n"); + fflush(stdmsg); } global.errors++; } @@ -147,1154 +147,6 @@ #endif } -extern void backend_init(); -extern void backend_term(); - -void usage() -{ - printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n", - global.ldc_version, global.version, global.llvm_version, global.copyright, global.written); - printf("\ -D Language Documentation: http://www.digitalmars.com/d/2.0/index.html\n\ -LDC Homepage: http://www.dsource.org/projects/ldc\n\ -Usage:\n\ - ldc files.d ... { -switch }\n\ -\n\ - files.d D source files\n%s\ - -o- do not write object file\n\ - -od<objdir> write object files to directory <objdir>\n\ - -op do not strip paths from source file\n\ - -oq write object files with fully qualified names\n\ - -of<filename> name output file to <filename>\n\ - if -c and extension of <filename> is known, it determines the output type\n\ -\n\ - -output-ll write LLVM IR\n\ - -output-bc write LLVM bitcode\n\ - -output-s write native assembly\n\ - -output-o write native object (default if no -output switch passed)\n\ -\n\ - -c do not link\n\ - -L<linkerflag> pass <linkerflag> to linker\n\ -\n\ - -w enable warnings\n\ -\n\ - -H generate 'header' file\n\ - -Hd<hdrdir> write 'header' file to <hdrdir> directory\n\ - -Hf<filename> write 'header' file to <filename>\n\ -\n\ - -D generate documentation\n\ - -Dd<docdir> write documentation file to <docdir> directory\n\ - -Df<filename> write documentation file to <filename>\n\ -\n\ -Codegen control:\n\ - -m<arch> emit code specific to <arch> being one of:\n\ - x86 x86-64 ppc32 ppc64 arm thumb\n\ - -t<os> emit code specific to <os> being one of:\n\ - Linux, Windows, MacOSX, FreeBSD, Solaris\n\ -\n\ - -g, -gc add symbolic debug info\n\ -\n\ - -O optimize, same as -O2\n\ - -O<n> optimize at level <n> (0-5)\n\ - -inline do function inlining\n\ -\n\ - -debug enables asserts, invariants, contracts, boundscheck\n\ - and sets debug=1\n\ - -release disables asserts, invariants, contracts, boundscheck\n\ -\n\ - -enable-<feature> and\n\ - -disable-<feature> where <feature> is one of\n\ - asserts assert statements (default: on)\n\ - invariants class and struct invariants (default: on)\n\ - contracts function contracts (default: on)\n\ - boundscheck array bounds checking (default: on)\n\ - -debug=level compile in debug stmts <= level (default: 0)\n\ - -debug=ident compile in debug stmts identified by ident\n\ - -version=level compile in version code >= level\n\ - -version=ident compile in version code identified by ident\n\ -\n\ - -noasm do not allow use of inline asm\n\ - -noruntime do not allow code that generates implicit runtime calls\n\ - -noverify do not run the validation pass before writing bitcode\n\ - -unittest compile in unit tests\n\ - -d allow deprecated features\n\ -\n\ - -annotate annotate the bitcode with human readable source code\n\ - -ignore ignore unsupported pragmas\n\ -\n\ -Path options:\n\ - -I<path> where to look for imports\n\ - -J<path> where to look for string imports\n\ - -defaultlib=name set default library for non-debug build\n\ - -debuglib=name set default library for debug build\n\ - -nodefaultlib don't add a default library for linking implicitly\n\ -\n\ -Misc options:\n\ - -v verbose\n\ - -vv very verbose (does not include -v)\n\ - -quiet suppress unnecessary messages\n\ - -run srcfile args... run resulting program, passing args\n\ - --help print help\n\ -", -#if WIN32 -" @cmdfile read arguments from cmdfile\n" -#else -"" -#endif -); -} - -int main(int argc, char *argv[]) -{ - int i; - Array files; - char *p, *ext; - Module *m; - int status = EXIT_SUCCESS; - int argcstart = argc; - bool very_verbose = false; - - // Check for malformed input - if (argc < 1 || !argv) - { - Largs: - error("missing or null command line arguments"); - fatal(); - } - for (i = 0; i < argc; i++) - { - if (!argv[i]) - goto Largs; - } - -#if __DMC__ // DMC unique support for response files - if (response_expand(&argc,&argv)) // expand response files - error("can't open response file"); -#endif - - files.reserve(argc - 1); - - // Set default values -#if _WIN32 - char buf[MAX_PATH]; - GetModuleFileName(NULL, buf, MAX_PATH); - global.params.argv0 = buf; -#else - global.params.argv0 = argv[0]; -#endif - global.params.link = 1; - global.params.useAssert = 1; - global.params.useInvariants = 1; - global.params.useIn = 1; - global.params.useOut = 1; - global.params.useArrayBounds = 1; - global.params.useSwitchError = 1; - global.params.useInline = 0; // this one messes things up to a point where codegen breaks - global.params.llvmInline = 0; // use this one instead to know if inline passes should be run - global.params.obj = 1; - global.params.Dversion = 2; - global.params.quiet = 1; - - global.params.output_o = OUTPUTFLAGdefault; - - global.params.linkswitches = new Array(); - global.params.libfiles = new Array(); - global.params.objfiles = new Array(); - global.params.ddocfiles = new Array(); - - global.params.is64bit = sizeof(void*) == 8 ? 1 : 0; - - uint16_t endiantest = 0xFF00; - uint8_t endianres = ((uint8_t*)&endiantest)[0]; - if (endianres == 0x00) - global.params.isLE = true; - else if (endianres == 0xFF) - global.params.isLE = false; - else { - error("Endian test is broken"); - fatal(); - } - - global.params.llvmArch = 0; - global.params.forceBE = 0; - global.params.noruntime = 0; - global.params.novalidate = 0; - global.params.optimizeLevel = -1; - global.params.runtimeImppath = 0; - global.params.useInlineAsm = 1; - - // Predefine version identifiers -#if IN_LLVM - VersionCondition::addPredefinedGlobalIdent("LLVM"); - VersionCondition::addPredefinedGlobalIdent("LDC"); -#endif - - // D2 -#if DMDV2 - VersionCondition::addPredefinedGlobalIdent("D_Version2"); -#endif - - // setup default target os to be build os -#if _WIN32 - global.params.os = OSWindows; -#elif linux - global.params.os = OSLinux; -#elif __APPLE__ - global.params.os = OSMacOSX; -#elif __FreeBSD__ - global.params.os = OSFreeBSD; -#elif defined (__SVR4) && defined (__sun) - global.params.os = OSSolaris; -#else -#error Unsupported OS -#endif /* linux */ - - assert(global.params.os != OSinvalid); - - //VersionCondition::addPredefinedGlobalIdent("D_Bits"); - VersionCondition::addPredefinedGlobalIdent("all"); - -//#if _WIN32 - -//#if DMDV2 -// inifile(global.params.argv0, "ldc2.ini"); -//#else -// inifile(global.params.argv0, "ldc.ini"); -//#endif - -//#elif POSIX - -#if DMDV2 - inifile(global.params.argv0, "ldc2.conf"); -#else - inifile(global.params.argv0, "ldc.conf"); -#endif - -//#else -//#error -//#endif - getenv_setargv("DFLAGS", &argc, &argv); - -#if 0 - for (i = 0; i < argc; i++) - { - printf("argv[%d] = '%s'\n", i, argv[i]); - } -#endif - - for (i = 1; i < argc; i++) - { - p = argv[i]; - if (*p == '-') - { - if (strcmp(p + 1, "d") == 0) - global.params.useDeprecated = 1; - else if (strcmp(p + 1, "c") == 0) - global.params.link = 0; - else if (strcmp(p + 1, "fPIC") == 0) - global.params.pic = 1; - else if (strcmp(p + 1, "g") == 0) - global.params.symdebug = 1; - else if (strcmp(p + 1, "gc") == 0) - global.params.symdebug = 2; - else if (strcmp(p + 1, "v") == 0) - global.params.verbose = 1; - else if (strcmp(p + 1, "vv") == 0) { - Logger::enable(); - very_verbose = true; - } - else if (strcmp(p + 1, "v1") == 0) - global.params.Dversion = 1; - else if (strcmp(p + 1, "w") == 0) - global.params.warnings = 1; - else if (p[1] == 'O') - { - global.params.optimize = 1; - global.params.optimizeLevel = 2; - if (p[2] != 0) { - int optlevel = atoi(p+2); - if (optlevel < 0 || optlevel > 5) { - error("Optimization level must be between 0 and 5. Using default (%d)", - global.params.optimizeLevel); - } - else { - global.params.optimizeLevel = optlevel; - } - } - } - else if (strcmp(p + 1, "forcebe") == 0) - global.params.forceBE = 1; - else if (strcmp(p + 1, "noruntime") == 0) - global.params.noruntime = 1; - else if (strcmp(p + 1, "noverify") == 0) - global.params.novalidate = 1; - else if (strcmp(p + 1, "annotate") == 0) - global.params.llvmAnnotate = 1; - else if (strncmp(p + 1, "enable-", 7) == 0 || - strncmp(p + 1, "disable-", 8) == 0) - { - bool enable = (p[1] == 'e'); - char* feature = p + 1 + (enable ? 7 : 8); - if (strcmp(feature, "asserts") == 0) - global.params.useAssert = enable; - else if (strcmp(feature, "boundscheck") == 0) - global.params.useArrayBounds = enable; - else if (strcmp(feature, "contracts") == 0) - { - global.params.useIn = enable; - global.params.useOut = enable; - } - else if (strcmp(feature, "invariants") == 0) - global.params.useInvariants = enable; - else - error("unrecognized feature '%s'", feature); - } - else if (strcmp(p + 1, "noasm") == 0) - global.params.useInlineAsm = 0; - else if (strcmp(p + 1, "nodefaultlib") == 0) - global.params.noDefaultLib = 1; - else if (p[1] == 'o') - { - switch (p[2]) - { - case '-': - global.params.obj = 0; - break; - - case 'd': - if (!p[3]) - goto Lnoarg; - global.params.objdir = p + 3; - break; - - case 'f': - if (!p[3]) - goto Lnoarg; - global.params.objname = p + 3; - break; - - case 'p': - if (p[3]) - goto Lerror; - global.params.preservePaths = 1; - break; - - case 'q': - if (p[3]) - goto Lerror; - global.params.fqnNames = 1; - break; - - case 'u': - if (strncmp(p+1, "output-", 7) != 0) - goto Lerror; - - // remove default output - if (global.params.output_o == OUTPUTFLAGdefault) - global.params.output_o = OUTPUTFLAGno; - - if (strcmp(p+8, global.ll_ext) == 0) - global.params.output_ll = OUTPUTFLAGset; - else if (strcmp(p+8, global.bc_ext) == 0) - global.params.output_bc = OUTPUTFLAGset; - else if (strcmp(p+8, global.s_ext) == 0) - global.params.output_s = OUTPUTFLAGset; - else if (strcmp(p+8, global.obj_ext) == 0) - global.params.output_o = OUTPUTFLAGset; - else - goto Lerror; - - break; - - case 0: - error("-o no longer supported, use -of or -od"); - break; - - default: - goto Lerror; - } - } - else if (p[1] == 'D') - { global.params.doDocComments = 1; - switch (p[2]) - { - case 'd': - if (!p[3]) - goto Lnoarg; - global.params.docdir = p + 3; - break; - case 'f': - if (!p[3]) - goto Lnoarg; - global.params.docname = p + 3; - break; - - case 0: - break; - - default: - goto Lerror; - } - } -#ifdef _DH - else if (p[1] == 'H') - { global.params.doHdrGeneration = 1; - switch (p[2]) - { - case 'd': - if (!p[3]) - goto Lnoarg; - global.params.hdrdir = p + 3; - break; - - case 'f': - if (!p[3]) - goto Lnoarg; - global.params.hdrname = p + 3; - break; - - case 0: - break; - - default: - goto Lerror; - } - } -#endif - else if (strcmp(p + 1, "ignore") == 0) - global.params.ignoreUnsupportedPragmas = 1; - else if (strcmp(p + 1, "inline") == 0) { - // TODO - // the ast rewrites dmd does for inlining messes up the ast. - // someday maybe we can support it, for now llvm does an excellent job at inlining - global.params.useInline = 0; //1 - global.params.llvmInline = 1; - } - else if (strcmp(p + 1, "quiet") == 0) - global.params.quiet = 1; - else if (strcmp(p + 1, "release") == 0) - { - global.params.useInvariants = 0; - global.params.useIn = 0; - global.params.useOut = 0; - global.params.useAssert = 0; - global.params.useArrayBounds = 0; - } - else if (strcmp(p + 1, "unittest") == 0) - global.params.useUnitTests = 1; - else if (p[1] == 'I') - { - if (!global.params.imppath) - global.params.imppath = new Array(); - global.params.imppath->push(p + 2); - } - else if (p[1] == 'J') - { - if (!global.params.fileImppath) - global.params.fileImppath = new Array(); - global.params.fileImppath->push(p + 2); - } - else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l') - { - // Parse: - // -debug - // -debug=number - // -debug=identifier - if (p[6] == '=') - { - if (isdigit(p[7])) - { long level; - - errno = 0; - level = strtol(p + 7, &p, 10); - if (*p || errno || level > INT_MAX) - goto Lerror; - DebugCondition::setGlobalLevel((int)level); - } - else if (Lexer::isValidIdentifier(p + 7)) - DebugCondition::addGlobalIdent(p + 7); - else - goto Lerror; - } - else if (p[6]) - goto Lerror; - else - { - global.params.useInvariants = 1; - global.params.useIn = 1; - global.params.useOut = 1; - global.params.useAssert = 1; - global.params.useArrayBounds = 1; - global.params.debuglevel = 1; - } - } - else if (memcmp(p + 1, "version", 5) == 0) - { - // Parse: - // -version=number - // -version=identifier - if (p[8] == '=') - { - if (isdigit(p[9])) - { long level; - - errno = 0; - level = strtol(p + 9, &p, 10); - if (*p || errno || level > INT_MAX) - goto Lerror; - VersionCondition::setGlobalLevel((int)level); - } - else if (Lexer::isValidIdentifier(p + 9)) - VersionCondition::addGlobalIdent(p + 9); - else - goto Lerror; - } - else - goto Lerror; - } - else if (strcmp(p + 1, "-b") == 0) - global.params.debugb = 1; - else if (strcmp(p + 1, "-c") == 0) - global.params.debugc = 1; - else if (strcmp(p + 1, "-f") == 0) - global.params.debugf = 1; - else if (strcmp(p + 1, "-help") == 0) - { usage(); - exit(EXIT_SUCCESS); - } - else if (strcmp(p + 1, "-r") == 0) - global.params.debugr = 1; - else if (strcmp(p + 1, "-x") == 0) - global.params.debugx = 1; - else if (strcmp(p + 1, "-y") == 0) - global.params.debugy = 1; - else if (p[1] == 'L') - { - global.params.linkswitches->push(p + 2); - } - else if (memcmp(p + 1, "defaultlib=", 11) == 0) - { - if(!global.params.defaultlibnames) - global.params.defaultlibnames = new Array(); - global.params.defaultlibnames->push(p + 1 + 11); - } - else if (memcmp(p + 1, "debuglib=", 9) == 0) - { - if(!global.params.debuglibnames) - global.params.debuglibnames = new Array(); - global.params.debuglibnames->push(p + 1 + 9); - } - else if (strcmp(p + 1, "run") == 0) - { global.params.run = 1; - global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1; - if (global.params.runargs_length) - { - files.push(argv[i + 1]); - global.params.runargs = &argv[i + 2]; - i += global.params.runargs_length; - global.params.runargs_length--; - } - else - { global.params.run = 0; - goto Lnoarg; - } - } - else if (p[1] == 'm') - { - global.params.llvmArch = p+2; - } - else if (p[1] == 't') - { - if(strcmp(p + 2, "Linux") == 0) - global.params.os = OSLinux; - else if(strcmp(p + 2, "Windows") == 0) - global.params.os = OSWindows; - else if(strcmp(p + 2, "MacOSX") == 0) - global.params.os = OSMacOSX; - else if(strcmp(p + 2, "FreeBSD") == 0) - global.params.os = OSFreeBSD; - else if(strcmp(p + 2, "Solaris") == 0) - global.params.os = OSSolaris; - else - error("unrecognized target os '%s'", p + 2); - } - else - { - Lerror: - error("unrecognized switch '%s'", argv[i]); - continue; - - Lnoarg: - error("argument expected for switch '%s'", argv[i]); - continue; - } - } - else - files.push(p); - } - if (global.errors) - { - fatal(); - } - if (files.dim == 0) - { usage(); - return EXIT_FAILURE; - } - - Array* libs; - if (global.params.symdebug) - libs = global.params.debuglibnames; - else - libs = global.params.defaultlibnames; - - if (libs) - { - for (int i = 0; i < libs->dim; i++) - { - char *arg = (char *)mem.malloc(64); - strcpy(arg, "-l"); - strncat(arg, (char *)libs->data[i], 64); - global.params.linkswitches->push(arg); - } - } - else if (!global.params.noDefaultLib) - { -#if DMDV2 - char *arg; - arg = (char *)mem.malloc(64); - strcpy(arg, "-ldruntime-ldc"); - global.params.linkswitches->push(arg); -#else - char *arg; - arg = (char *)mem.malloc(64); - strcpy(arg, "-lldc-runtime"); - global.params.linkswitches->push(arg); - arg = (char *)mem.malloc(64); - strcpy(arg, "-ltango-cc-tango"); - global.params.linkswitches->push(arg); - arg = (char *)mem.malloc(64); - strcpy(arg, "-ltango-gc-basic"); - global.params.linkswitches->push(arg); - // pass the runtime again to resolve issues - // with linking order - arg = (char *)mem.malloc(64); - strcpy(arg, "-lldc-runtime"); - global.params.linkswitches->push(arg); -#endif - } - - if (global.params.run) - global.params.quiet = 1; - - if (global.params.useUnitTests) - global.params.useAssert = 1; - - // LDC output determination - - // if we don't link, autodetect target from extension - if(!global.params.link && global.params.objname) { - ext = FileName::ext(global.params.objname); - bool autofound = false; - if (!ext) { - // keep things as they are - } else if (strcmp(ext, global.ll_ext) == 0) { - global.params.output_ll = OUTPUTFLAGset; - autofound = true; - } else if (strcmp(ext, global.bc_ext) == 0) { - global.params.output_bc = OUTPUTFLAGset; - autofound = true; - } else if (strcmp(ext, global.s_ext) == 0) { - global.params.output_s = OUTPUTFLAGset; - autofound = true; - } else if (strcmp(ext, global.obj_ext) == 0) { - global.params.output_o = OUTPUTFLAGset; - autofound = true; - } else { - // append dot, so forceExt won't change existing name even if it contains dots - size_t len = strlen(global.params.objname); - size_t extlen = strlen("."); - char* s = (char *)mem.malloc(len + 1 + extlen + 1); - memcpy(s, global.params.objname, len); - s[len] = '.'; - s[len+1+extlen] = 0; - global.params.objname = s; - - } - if(autofound && global.params.output_o == OUTPUTFLAGdefault) - global.params.output_o = OUTPUTFLAGno; - } - - // only link if possible - if (!global.params.obj || !global.params.output_o) - global.params.link = 0; - - if (global.params.link) - { - global.params.exefile = global.params.objname; - if (files.dim > 1) - global.params.objname = NULL; - } - else if (global.params.run) - { - error("flags conflict with -run"); - fatal(); - } - else - { - if (global.params.objname && files.dim > 1) - { - error("multiple source files, but only one .obj name"); - fatal(); - } - } - - bool allowForceEndianness = false; - - if (global.params.llvmArch == 0) { - #if defined(__x86_64__) || defined(_M_X64) - global.params.llvmArch = "x86-64"; - #elif defined(__i386__) || defined(_M_IX86) - global.params.llvmArch = "x86"; - #elif defined(__ppc__) || defined(_M_PPC) - if (global.params.is64bit) - global.params.llvmArch = "ppc64"; - else - global.params.llvmArch = "ppc32"; - #elif defined(__arm__) - global.params.llvmArch = "arm"; - #elif defined(__thumb__) - global.params.llvmArch = "thumb"; - #else - #error - #endif - } - - if (strcmp(global.params.llvmArch,"x86")==0) { - VersionCondition::addPredefinedGlobalIdent("X86"); - global.params.isLE = true; - global.params.is64bit = false; - global.params.cpu = ARCHx86; - if (global.params.useInlineAsm) { - VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86"); - } - } - else if (strcmp(global.params.llvmArch,"x86-64")==0) { - VersionCondition::addPredefinedGlobalIdent("X86_64"); - global.params.isLE = true; - global.params.is64bit = true; - global.params.cpu = ARCHx86_64; - if (global.params.useInlineAsm) { - VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64"); - } - } - else if (strcmp(global.params.llvmArch,"ppc32")==0) { - VersionCondition::addPredefinedGlobalIdent("PPC"); - global.params.isLE = false; - global.params.is64bit = false; - global.params.cpu = ARCHppc; - } - else if (strcmp(global.params.llvmArch,"ppc64")==0) { - VersionCondition::addPredefinedGlobalIdent("PPC64"); - global.params.isLE = false; - global.params.is64bit = true; - global.params.cpu = ARCHppc_64; - } - else if (strcmp(global.params.llvmArch,"arm")==0) { - VersionCondition::addPredefinedGlobalIdent("ARM"); - global.params.isLE = true; - global.params.is64bit = false; - global.params.cpu = ARCHarm; - } - else if (strcmp(global.params.llvmArch,"thumb")==0) { - VersionCondition::addPredefinedGlobalIdent("Thumb"); - global.params.isLE = true; - global.params.is64bit = false; - global.params.cpu = ARCHthumb; - } - else { - error("invalid cpu architecture specified: %s", global.params.llvmArch); - } - - assert(global.params.cpu != ARCHinvalid); - - if (allowForceEndianness && global.params.forceBE) { - VersionCondition::addPredefinedGlobalIdent("BigEndian"); - global.params.isLE = false; - } - else if (global.params.isLE) { - VersionCondition::addPredefinedGlobalIdent("LittleEndian"); - } - else { - VersionCondition::addPredefinedGlobalIdent("BigEndian"); - } - - if (global.params.is64bit) { - VersionCondition::addPredefinedGlobalIdent("LLVM64"); - } - - - // setup version idents and tt_os for chosen target os - switch(global.params.os) - { - case OSWindows: - VersionCondition::addPredefinedGlobalIdent("Windows"); - VersionCondition::addPredefinedGlobalIdent("Win32"); - VersionCondition::addPredefinedGlobalIdent("mingw32"); - break; - - case OSLinux: - VersionCondition::addPredefinedGlobalIdent("linux"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - break; - - case OSMacOSX: - VersionCondition::addPredefinedGlobalIdent("darwin"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - break; - - case OSFreeBSD: - VersionCondition::addPredefinedGlobalIdent("freebsd"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - break; - - case OSSolaris: - VersionCondition::addPredefinedGlobalIdent("solaris"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - break; - - default: - assert(false && "Target OS not supported"); - } - - if (!global.params.targetTriple) - global.params.targetTriple = DEFAULT_TARGET_TRIPLE; - - Logger::println("Target triple: %s", global.params.targetTriple); - - // build a minimal data layout so llvm can find the target - global.params.dataLayout = global.params.isLE - ? (char*)(global.params.is64bit ? "e-p:64:64" : "e-p:32:32") - : (char*)(global.params.is64bit ? "E-p:64:64" : "E-p:32:32"); - Logger::println("Layout: %s", global.params.dataLayout); - - // Initialization - Type::init(); - Id::initialize(); - Module::init(); - initPrecedence(); - - backend_init(); - - //printf("%d source files\n",files.dim); - - // Build import search path - if (global.params.imppath) - { - for (i = 0; i < global.params.imppath->dim; i++) - { - char *path = (char *)global.params.imppath->data[i]; - Array *a = FileName::splitPath(path); - - if (a) - { - if (!global.path) - global.path = new Array(); - global.path->append(a); - } - } - } - - // Build string import search path - if (global.params.fileImppath) - { - for (i = 0; i < global.params.fileImppath->dim; i++) - { - char *path = (char *)global.params.fileImppath->data[i]; - Array *a = FileName::splitPath(path); - - if (a) - { - if (!global.filePath) - global.filePath = new Array(); - global.filePath->append(a); - } - } - } - - // Create Modules - Array modules; - modules.reserve(files.dim); - for (i = 0; i < files.dim; i++) - { Identifier *id; - char *ext; - char *name; - - p = (char *) files.data[i]; - - p = FileName::name(p); // strip path - ext = FileName::ext(p); - if (ext) - { -#if POSIX - if (strcmp(ext, global.obj_ext) == 0 || - strcmp(ext, global.bc_ext) == 0) -#else - if (stricmp(ext, global.obj_ext) == 0 || - stricmp(ext, global.bc_ext) == 0) -#endif - { - global.params.objfiles->push(files.data[i]); - continue; - } - -#if POSIX - if (strcmp(ext, "a") == 0) -#elif __MINGW32__ - if (stricmp(ext, "a") == 0) -#else - if (stricmp(ext, "lib") == 0) -#endif - { - global.params.libfiles->push(files.data[i]); - continue; - } - - if (strcmp(ext, global.ddoc_ext) == 0) - { - global.params.ddocfiles->push(files.data[i]); - continue; - } - -#if !POSIX - if (stricmp(ext, "res") == 0) - { - global.params.resfile = (char *)files.data[i]; - continue; - } - - if (stricmp(ext, "def") == 0) - { - global.params.deffile = (char *)files.data[i]; - continue; - } - - if (stricmp(ext, "exe") == 0) - { - global.params.exefile = (char *)files.data[i]; - continue; - } -#endif - - if (stricmp(ext, global.mars_ext) == 0 || - stricmp(ext, global.hdr_ext) == 0 || - stricmp(ext, "htm") == 0 || - stricmp(ext, "html") == 0 || - stricmp(ext, "xhtml") == 0) - { - ext--; // skip onto '.' - assert(*ext == '.'); - name = (char *)mem.malloc((ext - p) + 1); - memcpy(name, p, ext - p); - name[ext - p] = 0; // strip extension - - if (name[0] == 0 || - strcmp(name, "..") == 0 || - strcmp(name, ".") == 0) - { - Linvalid: - error("invalid file name '%s'", (char *)files.data[i]); - fatal(); - } - } - else - { error("unrecognized file extension %s\n", ext); - fatal(); - } - } - else - { name = p; - if (!*name) - goto Linvalid; - } - - id = new Identifier(name, 0); - m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration); - modules.push(m); - } - - // Read files, parse them - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("parse %s\n", m->toChars()); - if (!Module::rootModule) - Module::rootModule = m; - m->importedFrom = m; - m->read(0); - m->parse(); - m->buildTargetFiles(); - m->deleteObjFile(); - if (m->isDocFile) - { - m->gendocfile(); - - // Remove m from list of modules - modules.remove(i); - i--; - } - } - if (global.errors) - fatal(); -#ifdef _DH - if (global.params.doHdrGeneration) - { - /* Generate 'header' import files. - * Since 'header' import files must be independent of command - * line switches and what else is imported, they are generated - * before any semantic analysis. - */ - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("import %s\n", m->toChars()); - m->genhdrfile(); - } - } - if (global.errors) - fatal(); -#endif - - // Do semantic analysis - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("semantic %s\n", m->toChars()); - m->semantic(); - } - if (global.errors) - fatal(); - - // Do pass 2 semantic analysis - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("semantic2 %s\n", m->toChars()); - m->semantic2(); - } - if (global.errors) - fatal(); - - // Do pass 3 semantic analysis - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("semantic3 %s\n", m->toChars()); - m->semantic3(); - } - if (global.errors) - fatal(); - -#if !IN_LLVM - // Scan for functions to inline - if (global.params.useInline) - { - /* The problem with useArrayBounds and useAssert is that the - * module being linked to may not have generated them, so if - * we inline functions from those modules, the symbols for them will - * not be found at link time. - */ - if (!global.params.useArrayBounds && !global.params.useAssert) - { -#endif - // Do pass 3 semantic analysis on all imported modules, - // since otherwise functions in them cannot be inlined - for (i = 0; i < Module::amodules.dim; i++) - { - m = (Module *)Module::amodules.data[i]; - if (global.params.verbose) - printf("semantic3 %s\n", m->toChars()); - m->semantic3(); - } - if (global.errors) - fatal(); -#if !IN_LLVM - } - - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("inline scan %s\n", m->toChars()); - m->inlineScan(); - } - } -#endif - if (global.errors) - fatal(); - - // Generate output files - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("code %s\n", m->toChars()); - if (global.params.obj) - { - m->genobjfile(0); - global.params.objfiles->push(m->objfile->name->str); - } - if (global.errors) - m->deleteObjFile(); - else - { - if (global.params.doDocComments) - m->gendocfile(); - } - } - - backend_term(); - if (global.errors) - fatal(); - - if (!global.params.objfiles->dim) - { - if (global.params.link) - error("no object files to link"); - } - else - { - if (global.params.link) - //status = runLINK(); - linkObjToExecutable(global.params.argv0); - - if (global.params.run) - { - if (!status) - { - status = runExectuable(); - - /* Delete .obj files and .exe file - */ - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - m->deleteObjFile(); - } - deleteExecutable(); - } - } - } - - return status; -} - - - /*********************************** * Parse and append contents of environment variable envvar * to argc and argv[]. @@ -1308,7 +160,7 @@ Array *argv; int argc; - int wildcard; // do wildcard expansion + int wildcard; // do wildcard expansion int instring; int slash; char c; @@ -1316,90 +168,111 @@ env = getenv(envvar); if (!env) - return; + return; - env = mem.strdup(env); // create our own writable copy + env = mem.strdup(env); // create our own writable copy argc = *pargc; argv = new Array(); argv->setDim(argc); - for (int i = 0; i < argc; i++) - argv->data[i] = (void *)(*pargv)[i]; + int argc_left = 0; + for (int i = 0; i < argc; i++) { + if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) { + // HACK: set flag to indicate we saw '-run' here + global.params.run = true; + // Don't eat -run yet so the program arguments don't get changed + argc_left = argc - i; + argc = i; + *pargv = &(*pargv)[i]; + argv->setDim(i); + break; + } else { + argv->data[i] = (void *)(*pargv)[i]; + } + } + // HACK to stop required values from command line being drawn from DFLAGS + argv->push((char*)""); + argc++; - j = 1; // leave argv[0] alone + j = 1; // leave argv[0] alone while (1) { - wildcard = 1; - switch (*env) - { - case ' ': - case '\t': - env++; - break; + wildcard = 1; + switch (*env) + { + case ' ': + case '\t': + env++; + break; - case 0: - goto Ldone; + case 0: + goto Ldone; - case '"': - wildcard = 0; - default: - argv->push(env); // append - //argv->insert(j, env); // insert at position j - j++; - argc++; - p = env; - slash = 0; - instring = 0; - c = 0; + case '"': + wildcard = 0; + default: + argv->push(env); // append + //argv->insert(j, env); // insert at position j + j++; + argc++; + p = env; + slash = 0; + instring = 0; + c = 0; - while (1) - { - c = *env++; - switch (c) - { - case '"': - p -= (slash >> 1); - if (slash & 1) - { p--; - goto Laddc; - } - instring ^= 1; - slash = 0; - continue; + while (1) + { + c = *env++; + switch (c) + { + case '"': + p -= (slash >> 1); + if (slash & 1) + { p--; + goto Laddc; + } + instring ^= 1; + slash = 0; + continue; - case ' ': - case '\t': - if (instring) - goto Laddc; - *p = 0; - //if (wildcard) - //wildcardexpand(); // not implemented - break; + case ' ': + case '\t': + if (instring) + goto Laddc; + *p = 0; + //if (wildcard) + //wildcardexpand(); // not implemented + break; - case '\\': - slash++; - *p++ = c; - continue; + case '\\': + slash++; + *p++ = c; + continue; - case 0: - *p = 0; - //if (wildcard) - //wildcardexpand(); // not implemented - goto Ldone; + case 0: + *p = 0; + //if (wildcard) + //wildcardexpand(); // not implemented + goto Ldone; - default: - Laddc: - slash = 0; - *p++ = c; - continue; - } - break; - } - } + default: + Laddc: + slash = 0; + *p++ = c; + continue; + } + break; + } + } } Ldone: + assert(argc == argv->dim); + argv->reserve(argc_left); + for (int i = 0; i < argc_left; i++) + argv->data[argc++] = (void *)(*pargv)[i]; + *pargc = argc; *pargv = (char **)argv->data; }