diff dmd/mars.c @ 159:5acec6b2eef8 trunk

[svn r175] merged dmd 1.029
author ChristianK
date Thu, 01 May 2008 15:15:28 +0200
parents d11848349f97
children 9d44ec83acd1
line wrap: on
line diff
--- a/dmd/mars.c	Thu May 01 13:33:02 2008 +0200
+++ b/dmd/mars.c	Thu May 01 15:15:28 2008 +0200
@@ -1,1215 +1,1219 @@
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include "llvm/Target/TargetMachineRegistry.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <limits.h>
-#include <string>
-#include <cstdarg>
-
-#if _WIN32
-#include <windows.h>
-long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
-#endif
-
-#if __DMC__
-#include <dos.h>
-#endif
-
-#if linux
-#include <errno.h>
-#endif
-
-#include "mem.h"
-#include "root.h"
-
-#include "mars.h"
-#include "module.h"
-#include "mtype.h"
-#include "id.h"
-#include "cond.h"
-#include "expression.h"
-#include "lexer.h"
-
-#include "gen/logger.h"
-
-void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
-
-Global global;
-
-Global::Global()
-{
-    mars_ext = "d";
-    sym_ext  = "d";
-    hdr_ext  = "di";
-    doc_ext  = "html";
-    ddoc_ext = "ddoc";
-
-#if IN_LLVM
-    obj_ext  = "bc";
-    ll_ext  = "ll";
-    bc_ext  = "bc";
-    nativeobj_ext = "o";
-#elif _WIN32
-    obj_ext  = "obj";
-#elif linux
-    obj_ext  = "o";
-#else
-#error "fix this"
-#endif
-
-    copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen";
-    written = "written by Walter Bright and Tomas Lindquist Olsen";
-    llvmdc_version = "0.1";
-    version = "v1.026";
-    global.structalign = 8;
-
-    memset(&params, 0, sizeof(Param));
-}
-
-char *Loc::toChars() const
-{
-    OutBuffer buf;
-    char *p;
-
-    if (filename)
-    {
-	buf.printf("%s", filename);
-    }
-
-    if (linnum)
-	buf.printf("(%d)", linnum);
-    buf.writeByte(0);
-    return (char *)buf.extractData();
-}
-
-Loc::Loc(Module *mod, unsigned linnum)
-{
-    this->linnum = linnum;
-    this->filename = mod ? mod->srcfile->toChars() : NULL;
-}
-
-/**************************************
- * Print error message and exit.
- */
-
-void error(Loc loc, const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    verror(loc, format, ap);
-    va_end( ap );
-}
-
-void verror(Loc loc, const char *format, va_list ap)
-{
-    if (!global.gag)
-    {
-	char *p = loc.toChars();
-
-	if (*p)
-	    fprintf(stdmsg, "%s: ", p);
-	mem.free(p);
-
-	fprintf(stdmsg, "Error: ");
-	vfprintf(stdmsg, format, ap);
-	fprintf(stdmsg, "\n");
-	fflush(stdmsg);
-    }
-    global.errors++;
-}
-
-/***************************************
- * Call this after printing out fatal error messages to clean up and exit
- * the compiler.
- */
-
-void fatal()
-{
-#if 0
-    halt();
-#endif
-    exit(EXIT_FAILURE);
-}
-
-/**************************************
- * Try to stop forgetting to remove the breakpoints from
- * release builds.
- */
-void halt()
-{
-#ifdef DEBUG
-    *(char*)0=0;
-#endif
-}
-
-extern void backend_init();
-extern void backend_term();
-
-void usage()
-{
-    printf("LLVM D Compiler %s (based on DMD %s and LLVM 2.2)\n%s\n%s\n",
-    global.llvmdc_version, global.version, global.copyright, global.written);
-    printf("\
-D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
-LLVMDC Homepage: http://www.dsource.org/projects/llvmdc\n\
-Usage:\n\
-  dmd files.d ... { -switch }\n\
-\n\
-  files.d        D source files\n%s\
-  -annotate      annotate the bitcode with human readable source code\n\
-  -c             do not link\n\
-  -cov           do code coverage analysis\n\
-  -D             generate documentation\n\
-  -Dd<docdir>    write documentation file to <docdir> directory\n\
-  -Df<filename>  write documentation file to <filename>\n\
-  -d             allow deprecated features\n\
-  -debug         compile in debug code\n\
-  -debug=level   compile in debug code <= level\n\
-  -debug=ident   compile in debug code identified by ident\n\
-  -debuglib=name    set symbolic debug library to name\n\
-  -defaultlib=name  set default library to name\n\
-  -dis           disassemble module after compiling\n\
-  -g             add symbolic debug info\n\
-  -gc            add symbolic debug info, pretend to be C\n\
-  -H             generate 'header' file\n\
-  -Hd<hdrdir>    write 'header' file to <hdrdir> directory\n\
-  -Hf<filename>  write 'header' file to <filename>\n\
-  --help         print help\n\
-  -I<path>       where to look for imports\n\
-  -J<path>       where to look for string imports\n\
-  -inline        do function inlining\n\
-  -Llinkerflag   pass linkerflag to link\n\
-  -m<arch>       emit code specific to <arch>\n\
-                 x86 x86-64 ppc32 ppc64\n\
-  -nofloat       do not emit reference to floating point\n\
-  -noruntime     do not allow code that generates implicit runtime calls\n\
-  -noverify      do not run the validation pass before writing bitcode\n\
-  -O             optimize, same as -O2\n\
-  -O<n>          optimize at level <n> (0-5)\n\
-  -o-            do not write object file\n\
-  -od<objdir>    write object files to directory <objdir>\n\
-  -of<filename>	 name output file to <filename>\n\
-  -op            do not strip paths from source file\n\
-  -profile       profile runtime performance of generated code\n\
-  -quiet         suppress unnecessary messages\n\
-  -release       compile release version\n\
-  -run srcfile args...   run resulting program, passing args\n\
-  -R<path>       provide path to the directory containing the runtime library\n\
-  -unittest      compile in unit tests\n\
-  -v             verbose\n\
-  -vv            very verbose (does not include -v)\n\
-  -v1            D language version 1\n\
-  -version=level compile in version code >= level\n\
-  -version=ident compile in version code identified by ident\n\
-  -w             enable warnings\n\
-",
-#if WIN32
-"  @cmdfile       read arguments from cmdfile\n"
-#else
-""
-#endif
-);
-}
-
-int main(int argc, char *argv[])
-{
-    int i;
-    Array files;
-    char *p;
-    Module *m;
-    int status = EXIT_SUCCESS;
-    int argcstart = argc;
-    char* tt_arch = 0;
-    char* tt_os = 0;
-    char* data_layout = 0;
-    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
-    global.params.argv0 = argv[0];
-    global.params.link = 1;
-    global.params.useAssert = 0;
-    global.params.useInvariants = 0;
-    global.params.useIn = 1;
-    global.params.useOut = 1;
-    global.params.useArrayBounds = 0;
-    global.params.useSwitchError = 0;
-    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.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.defaultlibname = "phobos";
-    global.params.debuglibname = global.params.defaultlibname;
-
-    // Predefine version identifiers
-#if IN_LLVM
-    VersionCondition::addPredefinedGlobalIdent("LLVM");
-    VersionCondition::addPredefinedGlobalIdent("LLVMDC");
-    VersionCondition::addPredefinedGlobalIdent("Posix");
-#endif
-#if _WIN32
-    VersionCondition::addPredefinedGlobalIdent("Windows");
-    VersionCondition::addPredefinedGlobalIdent("Win32");
-    global.params.isWindows = 1;
-#elif linux
-    VersionCondition::addPredefinedGlobalIdent("linux");
-    global.params.isLinux = 1;
-    tt_os = "-unknown-linux-gnu";
-#else
-#error
-#endif /* linux */
-
-    //VersionCondition::addPredefinedGlobalIdent("D_Bits");
-    //VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
-    //VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
-    VersionCondition::addPredefinedGlobalIdent("all");
-
-#if _WIN32
-    inifile(argv[0], "llvmdc.ini");
-#endif
-#if linux
-    inifile(argv[0], "llvmdc.conf");
-#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, "cov") == 0)
-		global.params.cov = 1;
-	    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, "gt") == 0)
-	    {	error("use -profile instead of -gt\n");
-            global.params.trace = 1;
-	    }
-	    else if (strcmp(p + 1, "profile") == 0)
-		global.params.trace = 1;
-	    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, "dis") == 0)
-            global.params.disassemble = 1;
-        else if (strcmp(p + 1, "annotate") == 0)
-            global.params.llvmAnnotate = 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 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, "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, "nofloat") == 0)
-		global.params.nofloat = 1;
-	    else if (strcmp(p + 1, "quiet") == 0)
-		global.params.quiet = 1;
-	    else if (strcmp(p + 1, "release") == 0)
-		global.params.release = 1;
-	    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 (p[1] == 'R')
-        {
-        global.params.runtimePath = 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.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)
-	    {
-		global.params.defaultlibname = p + 1 + 11;
-	    }
-	    else if (memcmp(p + 1, "debuglib=", 9) == 0)
-	    {
-		global.params.debuglibname = 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
-	    {
-	     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;
-    }
-
-    if (global.params.release)
-    {	global.params.useInvariants = 0;
-	global.params.useIn = 0;
-	global.params.useOut = 0;
-	global.params.useAssert = 0;
-	global.params.useArrayBounds = 0;
-	global.params.useSwitchError = 0;
-    }
-
-    if (global.params.run)
-	global.params.quiet = 1;
-
-    if (global.params.useUnitTests)
-	global.params.useAssert = 1;
-
-    if (!global.params.obj)
-	global.params.link = 0;
-
-    if (global.params.link)
-    {
-	global.params.exefile = global.params.objname;
-	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();
-	}
-    }
-    if (global.params.cov)
-	VersionCondition::addPredefinedGlobalIdent("D_Coverage");
-
-    bool allowForceEndianness = false;
-
-    if (global.params.llvmArch == 0) {
-        std::string err_str;
-        const llvm::TargetMachineRegistry::entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str);
-        if (e == 0) {
-            error("Failed to find a default target machine: %s", err_str.c_str());
-            fatal();
-        }
-        else {
-            global.params.llvmArch = const_cast<char*>(e->Name);
-            if (global.params.verbose || very_verbose)
-            printf("Default target found: %s\n", global.params.llvmArch);
-            if (very_verbose) {
-                int X = sizeof(va_list);
-                printf("valist.sizeof = %d\n", X);
-            }
-        }
-    }
-
-    if (strcmp(global.params.llvmArch,"x86")==0) {
-        VersionCondition::addPredefinedGlobalIdent("X86");
-        //VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
-        global.params.isLE = true;
-        global.params.is64bit = false;
-        tt_arch = "i686";
-        data_layout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:8";
-    }
-    else if (strcmp(global.params.llvmArch,"x86-64")==0) {
-        VersionCondition::addPredefinedGlobalIdent("X86_64");
-        //VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
-        global.params.isLE = true;
-        global.params.is64bit = true;
-        tt_arch = "x86_64";
-        data_layout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:8";
-    }
-    else if (strcmp(global.params.llvmArch,"ppc32")==0) {
-        VersionCondition::addPredefinedGlobalIdent("PPC");
-        global.params.isLE = false;
-        global.params.is64bit = false;
-        tt_arch = "powerpc";
-        data_layout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:8";
-    }
-    else if (strcmp(global.params.llvmArch,"ppc64")==0) {
-        VersionCondition::addPredefinedGlobalIdent("PPC64");
-        global.params.isLE = false;
-        global.params.is64bit = true;
-        tt_arch = "powerpc64";
-        data_layout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:8";
-    }
-    else {
-        assert(0 && "Invalid arch");
-    }
-
-    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");
-    }
-
-    assert(tt_arch != 0);
-    assert(tt_os != 0);
-    assert(data_layout != 0);
-    global.params.tt_arch = tt_arch;
-    global.params.tt_os = tt_os;
-    global.params.data_layout = data_layout;
-
-    // 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];
-
-#if _WIN32
-	// Convert / to \ so linker will work
-	for (int i = 0; p[i]; i++)
-	{
-	    if (p[i] == '/')
-		p[i] = '\\';
-	}
-#endif
-
-	p = FileName::name(p);		// strip path
-	ext = FileName::ext(p);
-	if (ext)
-	{
-#if IN_LLVM
-        if (strcmp(ext, global.nativeobj_ext) == 0 ||
-            strcmp(ext, global.obj_ext) == 0)
-#elif TARGET_LINUX
-	    if (strcmp(ext, global.obj_ext) == 0)
-#else
-	    if (stricmp(ext, global.obj_ext) == 0)
-#endif
-	    {
-		global.params.objfiles->push(files.data[i]);
-		continue;
-	    }
-
-#if TARGET_LINUX
-	    if (strcmp(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 !TARGET_LINUX
-	    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, "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);
-
-	global.params.objfiles->push(m->objfile->name->str);
-    }
-
-#if _WIN32
-  __try
-  {
-#endif
-    // 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->deleteObjFile();
-	m->read(0);
-	m->parse();
-	if (m->isDocFile)
-	{
-	    m->gendocfile();
-
-	    // Remove m from list of modules
-	    modules.remove(i);
-	    i--;
-
-	    // Remove m's object file from list of object files
-	    for (int j = 0; j < global.params.objfiles->dim; j++)
-	    {
-		if (m->objfile->name->str == global.params.objfiles->data[j])
-		{
-		    global.params.objfiles->remove(j);
-		    break;
-		}
-	    }
-
-	    if (global.params.objfiles->dim == 0)
-		global.params.link = 0;
-	}
-    }
-    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();
-	}
-    }
-    if (global.errors)
-	fatal();
-#endif
-
-    // 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();
-	if (global.errors)
-	    m->deleteObjFile();
-	else
-	{
-	    if (global.params.doDocComments)
-		m->gendocfile();
-	}
-    }
-#if _WIN32
-  }
-  __except (__ehfilter(GetExceptionInformation()))
-  {
-    printf("Stack overflow\n");
-    fatal();
-  }
-#endif
-    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();
-
-	if (global.params.run)
-	{
-	    if (!status)
-	    {
-		status = runProgram();
-
-		/* Delete .obj files and .exe file
-		 */
-		for (i = 0; i < modules.dim; i++)
-		{
-		    m = (Module *)modules.data[i];
-		    m->deleteObjFile();
-		}
-		deleteExeFile();
-	    }
-	}
-    }
-
-    return status;
-}
-
-
-
-/***********************************
- * Parse and append contents of environment variable envvar
- * to argc and argv[].
- * The string is separated into arguments, processing \ and ".
- */
-
-void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
-{
-    char *env;
-    char *p;
-    Array *argv;
-    int argc;
-
-    int wildcard;		// do wildcard expansion
-    int instring;
-    int slash;
-    char c;
-    int j;
-
-    env = getenv(envvar);
-    if (!env)
-	return;
-
-    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];
-
-    j = 1;			// leave argv[0] alone
-    while (1)
-    {
-	wildcard = 1;
-	switch (*env)
-	{
-	    case ' ':
-	    case '\t':
-		env++;
-		break;
-
-	    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;
-
-		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 '\\':
-			    slash++;
-			    *p++ = c;
-			    continue;
-
-			case 0:
-			    *p = 0;
-			    //if (wildcard)
-				//wildcardexpand();	// not implemented
-			    goto Ldone;
-
-			default:
-			Laddc:
-			    slash = 0;
-			    *p++ = c;
-			    continue;
-		    }
-		    break;
-		}
-	}
-    }
-
-Ldone:
-    *pargc = argc;
-    *pargv = (char **)argv->data;
-}
-
-#if _WIN32
-
-long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep)
-{
-    //printf("%x\n", ep->ExceptionRecord->ExceptionCode);
-    if (ep->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
-    {
-#ifndef DEBUG
-	return EXCEPTION_EXECUTE_HANDLER;
-#endif
-    }
-    return EXCEPTION_CONTINUE_SEARCH;
-}
-
-#endif
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include "llvm/Target/TargetMachineRegistry.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+#include <limits.h>
+#include <string>
+#include <cstdarg>
+
+#if _WIN32
+#include <windows.h>
+long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
+#endif
+
+#if __DMC__
+#include <dos.h>
+#endif
+
+#if linux
+#include <errno.h>
+#endif
+
+#include "mem.h"
+#include "root.h"
+
+#include "mars.h"
+#include "module.h"
+#include "mtype.h"
+#include "id.h"
+#include "cond.h"
+#include "expression.h"
+#include "lexer.h"
+
+#include "gen/logger.h"
+
+void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
+
+Global global;
+
+Global::Global()
+{
+    mars_ext = "d";
+    sym_ext  = "d";
+    hdr_ext  = "di";
+    doc_ext  = "html";
+    ddoc_ext = "ddoc";
+
+#if IN_LLVM
+    obj_ext  = "bc";
+    ll_ext  = "ll";
+    bc_ext  = "bc";
+    nativeobj_ext = "o";
+#elif _WIN32
+    obj_ext  = "obj";
+#elif linux
+    obj_ext  = "o";
+#else
+#error "fix this"
+#endif
+
+    copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen";
+    written = "written by Walter Bright and Tomas Lindquist Olsen";
+    version = "v1.029";
+    llvmdc_version = "0.1";
+    global.structalign = 8;
+
+    memset(&params, 0, sizeof(Param));
+}
+
+char *Loc::toChars() const
+{
+    OutBuffer buf;
+    char *p;
+
+    if (filename)
+    {
+	buf.printf("%s", filename);
+    }
+
+    if (linnum)
+	buf.printf("(%d)", linnum);
+    buf.writeByte(0);
+    return (char *)buf.extractData();
+}
+
+Loc::Loc(Module *mod, unsigned linnum)
+{
+    this->linnum = linnum;
+    this->filename = mod ? mod->srcfile->toChars() : NULL;
+}
+
+/**************************************
+ * Print error message and exit.
+ */
+
+void error(Loc loc, const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    verror(loc, format, ap);
+    va_end( ap );
+}
+
+void verror(Loc loc, const char *format, va_list ap)
+{
+    if (!global.gag)
+    {
+	char *p = loc.toChars();
+
+	if (*p)
+	    fprintf(stdmsg, "%s: ", p);
+	mem.free(p);
+
+	fprintf(stdmsg, "Error: ");
+	vfprintf(stdmsg, format, ap);
+	fprintf(stdmsg, "\n");
+	fflush(stdmsg);
+    }
+    global.errors++;
+}
+
+/***************************************
+ * Call this after printing out fatal error messages to clean up and exit
+ * the compiler.
+ */
+
+void fatal()
+{
+#if 0
+    halt();
+#endif
+    exit(EXIT_FAILURE);
+}
+
+/**************************************
+ * Try to stop forgetting to remove the breakpoints from
+ * release builds.
+ */
+void halt()
+{
+#ifdef DEBUG
+    *(char*)0=0;
+#endif
+}
+
+extern void backend_init();
+extern void backend_term();
+
+void usage()
+{
+    printf("LLVM D Compiler %s (based on DMD %s and LLVM 2.2)\n%s\n%s\n",
+    global.llvmdc_version, global.version, global.copyright, global.written);
+    printf("\
+D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
+LLVMDC Homepage: http://www.dsource.org/projects/llvmdc\n\
+Usage:\n\
+  dmd files.d ... { -switch }\n\
+\n\
+  files.d        D source files\n%s\
+  -annotate      annotate the bitcode with human readable source code\n\
+  -c             do not link\n\
+  -cov           do code coverage analysis\n\
+  -D             generate documentation\n\
+  -Dd<docdir>    write documentation file to <docdir> directory\n\
+  -Df<filename>  write documentation file to <filename>\n\
+  -d             allow deprecated features\n\
+  -debug         compile in debug code\n\
+  -debug=level   compile in debug code <= level\n\
+  -debug=ident   compile in debug code identified by ident\n\
+  -debuglib=name    set symbolic debug library to name\n\
+  -defaultlib=name  set default library to name\n\
+  -dis           disassemble module after compiling\n\
+  -g             add symbolic debug info\n\
+  -gc            add symbolic debug info, pretend to be C\n\
+  -H             generate 'header' file\n\
+  -Hd<hdrdir>    write 'header' file to <hdrdir> directory\n\
+  -Hf<filename>  write 'header' file to <filename>\n\
+  --help         print help\n\
+  -I<path>       where to look for imports\n\
+  -J<path>       where to look for string imports\n\
+  -ignore        ignore unsupported pragmas\n\
+  -inline        do function inlining\n\
+  -Llinkerflag   pass linkerflag to link\n\
+  -m<arch>       emit code specific to <arch>\n\
+                 x86 x86-64 ppc32 ppc64\n\
+  -nofloat       do not emit reference to floating point\n\
+  -noruntime     do not allow code that generates implicit runtime calls\n\
+  -noverify      do not run the validation pass before writing bitcode\n\
+  -O             optimize, same as -O2\n\
+  -O<n>          optimize at level <n> (0-5)\n\
+  -o-            do not write object file\n\
+  -od<objdir>    write object files to directory <objdir>\n\
+  -of<filename>	 name output file to <filename>\n\
+  -op            do not strip paths from source file\n\
+  -profile	 profile runtime performance of generated code\n\
+  -quiet         suppress unnecessary messages\n\
+  -release	 compile release version\n\
+  -run srcfile args...   run resulting program, passing args\n\
+  -R<path>       provide path to the directory containing the runtime library\n\
+  -unittest      compile in unit tests\n\
+  -v             verbose\n\
+  -vv            very verbose (does not include -v)\n\
+  -v1            D language version 1\n\
+  -version=level compile in version code >= level\n\
+  -version=ident compile in version code identified by ident\n\
+  -w             enable warnings\n\
+",
+#if WIN32
+"  @cmdfile       read arguments from cmdfile\n"
+#else
+""
+#endif
+);
+}
+
+int main(int argc, char *argv[])
+{
+    int i;
+    Array files;
+    char *p;
+    Module *m;
+    int status = EXIT_SUCCESS;
+    int argcstart = argc;
+    char* tt_arch = 0;
+    char* tt_os = 0;
+    char* data_layout = 0;
+    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
+    global.params.argv0 = argv[0];
+    global.params.link = 1;
+    global.params.useAssert = 0;
+    global.params.useInvariants = 0;
+    global.params.useIn = 1;
+    global.params.useOut = 1;
+    global.params.useArrayBounds = 0;
+    global.params.useSwitchError = 0;
+    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.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.defaultlibname = "phobos";
+    global.params.debuglibname = global.params.defaultlibname;
+
+    // Predefine version identifiers
+#if IN_LLVM
+    VersionCondition::addPredefinedGlobalIdent("LLVM");
+    VersionCondition::addPredefinedGlobalIdent("LLVMDC");
+    VersionCondition::addPredefinedGlobalIdent("Posix");
+#endif
+#if _WIN32
+    VersionCondition::addPredefinedGlobalIdent("Windows");
+    VersionCondition::addPredefinedGlobalIdent("Win32");
+    global.params.isWindows = 1;
+#elif linux
+    VersionCondition::addPredefinedGlobalIdent("linux");
+    global.params.isLinux = 1;
+    tt_os = "-unknown-linux-gnu";
+#else
+#error
+#endif /* linux */
+
+    //VersionCondition::addPredefinedGlobalIdent("D_Bits");
+    //VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
+    //VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
+    VersionCondition::addPredefinedGlobalIdent("all");
+
+#if _WIN32
+    inifile(argv[0], "llvmdc.ini");
+#endif
+#if linux
+    inifile(argv[0], "llvmdc.conf");
+#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, "cov") == 0)
+		global.params.cov = 1;
+	    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, "gt") == 0)
+	    {	error("use -profile instead of -gt\n");
+		global.params.trace = 1;
+	    }
+	    else if (strcmp(p + 1, "profile") == 0)
+		global.params.trace = 1;
+	    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, "dis") == 0)
+            global.params.disassemble = 1;
+        else if (strcmp(p + 1, "annotate") == 0)
+            global.params.llvmAnnotate = 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 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, "nofloat") == 0)
+		global.params.nofloat = 1;
+	    else if (strcmp(p + 1, "quiet") == 0)
+		global.params.quiet = 1;
+	    else if (strcmp(p + 1, "release") == 0)
+		global.params.release = 1;
+	    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 (p[1] == 'R')
+        {
+        global.params.runtimePath = 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.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)
+	    {
+		global.params.defaultlibname = p + 1 + 11;
+	    }
+	    else if (memcmp(p + 1, "debuglib=", 9) == 0)
+	    {
+		global.params.debuglibname = 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
+	    {
+	     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;
+    }
+
+    if (global.params.release)
+    {	global.params.useInvariants = 0;
+	global.params.useIn = 0;
+	global.params.useOut = 0;
+	global.params.useAssert = 0;
+	global.params.useArrayBounds = 0;
+	global.params.useSwitchError = 0;
+    }
+
+    if (global.params.run)
+	global.params.quiet = 1;
+
+    if (global.params.useUnitTests)
+	global.params.useAssert = 1;
+
+    if (!global.params.obj)
+	global.params.link = 0;
+
+    if (global.params.link)
+    {
+	global.params.exefile = global.params.objname;
+	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();
+	}
+    }
+    if (global.params.cov)
+	VersionCondition::addPredefinedGlobalIdent("D_Coverage");
+
+    bool allowForceEndianness = false;
+
+    if (global.params.llvmArch == 0) {
+        std::string err_str;
+        const llvm::TargetMachineRegistry::entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str);
+        if (e == 0) {
+            error("Failed to find a default target machine: %s", err_str.c_str());
+            fatal();
+        }
+        else {
+            global.params.llvmArch = const_cast<char*>(e->Name);
+            if (global.params.verbose || very_verbose)
+            printf("Default target found: %s\n", global.params.llvmArch);
+            if (very_verbose) {
+                int X = sizeof(va_list);
+                printf("valist.sizeof = %d\n", X);
+            }
+        }
+    }
+
+    if (strcmp(global.params.llvmArch,"x86")==0) {
+        VersionCondition::addPredefinedGlobalIdent("X86");
+        //VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
+        global.params.isLE = true;
+        global.params.is64bit = false;
+        tt_arch = "i686";
+        data_layout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:8";
+    }
+    else if (strcmp(global.params.llvmArch,"x86-64")==0) {
+        VersionCondition::addPredefinedGlobalIdent("X86_64");
+        //VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
+        global.params.isLE = true;
+        global.params.is64bit = true;
+        tt_arch = "x86_64";
+        data_layout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:8";
+    }
+    else if (strcmp(global.params.llvmArch,"ppc32")==0) {
+        VersionCondition::addPredefinedGlobalIdent("PPC");
+        global.params.isLE = false;
+        global.params.is64bit = false;
+        tt_arch = "powerpc";
+        data_layout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:8";
+    }
+    else if (strcmp(global.params.llvmArch,"ppc64")==0) {
+        VersionCondition::addPredefinedGlobalIdent("PPC64");
+        global.params.isLE = false;
+        global.params.is64bit = true;
+        tt_arch = "powerpc64";
+        data_layout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:8";
+    }
+    else {
+        assert(0 && "Invalid arch");
+    }
+
+    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");
+    }
+
+    assert(tt_arch != 0);
+    assert(tt_os != 0);
+    assert(data_layout != 0);
+    global.params.tt_arch = tt_arch;
+    global.params.tt_os = tt_os;
+    global.params.data_layout = data_layout;
+
+    // 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];
+
+#if _WIN32
+	// Convert / to \ so linker will work
+	for (int i = 0; p[i]; i++)
+	{
+	    if (p[i] == '/')
+		p[i] = '\\';
+	}
+#endif
+
+	p = FileName::name(p);		// strip path
+	ext = FileName::ext(p);
+	if (ext)
+	{
+#if IN_LLVM
+        if (strcmp(ext, global.nativeobj_ext) == 0 ||
+            strcmp(ext, global.obj_ext) == 0)
+#elif TARGET_LINUX
+	    if (strcmp(ext, global.obj_ext) == 0)
+#else
+	    if (stricmp(ext, global.obj_ext) == 0)
+#endif
+	    {
+		global.params.objfiles->push(files.data[i]);
+		continue;
+	    }
+
+#if TARGET_LINUX
+	    if (strcmp(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 !TARGET_LINUX
+	    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, "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);
+
+	global.params.objfiles->push(m->objfile->name->str);
+    }
+
+#if _WIN32
+  __try
+  {
+#endif
+    // 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->deleteObjFile();
+	m->read(0);
+	m->parse();
+	if (m->isDocFile)
+	{
+	    m->gendocfile();
+
+	    // Remove m from list of modules
+	    modules.remove(i);
+	    i--;
+
+	    // Remove m's object file from list of object files
+	    for (int j = 0; j < global.params.objfiles->dim; j++)
+	    {
+		if (m->objfile->name->str == global.params.objfiles->data[j])
+		{
+		    global.params.objfiles->remove(j);
+		    break;
+		}
+	    }
+
+	    if (global.params.objfiles->dim == 0)
+		global.params.link = 0;
+	}
+    }
+    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();
+	}
+    }
+    if (global.errors)
+	fatal();
+#endif
+
+    // 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();
+	if (global.errors)
+	    m->deleteObjFile();
+	else
+	{
+	    if (global.params.doDocComments)
+		m->gendocfile();
+	}
+    }
+#if _WIN32
+  }
+  __except (__ehfilter(GetExceptionInformation()))
+  {
+    printf("Stack overflow\n");
+    fatal();
+  }
+#endif
+    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();
+
+	if (global.params.run)
+	{
+	    if (!status)
+	    {
+		status = runProgram();
+
+		/* Delete .obj files and .exe file
+		 */
+		for (i = 0; i < modules.dim; i++)
+		{
+		    m = (Module *)modules.data[i];
+		    m->deleteObjFile();
+		}
+		deleteExeFile();
+	    }
+	}
+    }
+
+    return status;
+}
+
+
+
+/***********************************
+ * Parse and append contents of environment variable envvar
+ * to argc and argv[].
+ * The string is separated into arguments, processing \ and ".
+ */
+
+void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
+{
+    char *env;
+    char *p;
+    Array *argv;
+    int argc;
+
+    int wildcard;		// do wildcard expansion
+    int instring;
+    int slash;
+    char c;
+    int j;
+
+    env = getenv(envvar);
+    if (!env)
+	return;
+
+    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];
+
+    j = 1;			// leave argv[0] alone
+    while (1)
+    {
+	wildcard = 1;
+	switch (*env)
+	{
+	    case ' ':
+	    case '\t':
+		env++;
+		break;
+
+	    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;
+
+		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 '\\':
+			    slash++;
+			    *p++ = c;
+			    continue;
+
+			case 0:
+			    *p = 0;
+			    //if (wildcard)
+				//wildcardexpand();	// not implemented
+			    goto Ldone;
+
+			default:
+			Laddc:
+			    slash = 0;
+			    *p++ = c;
+			    continue;
+		    }
+		    break;
+		}
+	}
+    }
+
+Ldone:
+    *pargc = argc;
+    *pargv = (char **)argv->data;
+}
+
+#if _WIN32
+
+long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep)
+{
+    //printf("%x\n", ep->ExceptionRecord->ExceptionCode);
+    if (ep->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
+    {
+#ifndef DEBUG
+	return EXCEPTION_EXECUTE_HANDLER;
+#endif
+    }
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+#endif