# HG changeset patch # User Frits van Bommel # Date 1235579691 -3600 # Node ID a8cb25d478c4644e1b4deb900ec05743b11d889f # Parent bce024c60adced077e4ddd3db4f836693e98f91b Use LLVM-style command line (instead of DMD-style) Note: For a backward compatible interface, use the new bin/ldmd script. It supports all old options while passing on anything it doesn't recognize. Some changes caused by this: * -debug and -version are now -d-debug and -d-version due to a conflict with standard LLVM options. * All "flag" options now allow an optional =true/=1/=false/=0 suffix. * Some "hidden debug switches" starting with "--" were renamed because LLVM doesn't care about the number of dashes, so they were conflicting with other options (such as -c). The new versions start with "-hidden-debug-" instead of "--" * --help works, but has a non-zero exit code. This breaks some Tango scripts which use it to test for compiler existence. See tango.patch. Some changes not (directly) caused by this; * (-enable/-disable)-FOO options are now available for pre- and postconditions. * -march is used instead of -m (like other LLVM programs), but -m is an alias for it. * -defaultlib, -debuglib, -d-debug and -d-version allow comma-separated values. The effect should be identical to specifying the same option multiple times. I decided against allowing these for some other options because paths might contain commas on some systems. * -fPIC is removed in favor of the standard LLVM option -relocation-model=pic Bug: * If -run is specified as the last argument in DFLAGS, no error is generated. (Not very serious IMHO) diff -r bce024c60adc -r a8cb25d478c4 bin/ldmd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/ldmd Wed Feb 25 17:34:51 2009 +0100 @@ -0,0 +1,41 @@ +#! /usr/bin/env bash + +# Default to 'ldc' next to this file +LDC=`basename "$0"`/ldc +if [ ! -x "$LDC" ]; then + # If that doesn't work, assume this script was called via $PATH + # and do the same for ldc + if which ldc &> /dev/null; then + LDC=ldc + else + echo 'ldc not found, check your installation' >/dev/stderr + exit 1 + fi +fi + +declare -a ARGS +SeenFile=0 +IDX=0 +for arg; do + case "$arg" in + -debug|-debug=*|-version=*) + arg="-d$arg" + ;; + -fPIC) + arg="-relocation-model=pic" + ;; + --a|--b|--c|--f|--r|--w|--x|--y) + # "Hidden debug switches" + # Are these ever used? + arg="-hidden-debug${arg:1}" + ;; + -*) + ;; + *) + SeenFile=1 + ;; + esac + ARGS[IDX++]="$arg" +done + +exec "$LDC" "${ARGS[@]}" diff -r bce024c60adc -r a8cb25d478c4 dmd/attrib.c --- a/dmd/attrib.c Thu Feb 19 13:51:44 2009 +0100 +++ b/dmd/attrib.c Wed Feb 25 17:34:51 2009 +0100 @@ -33,6 +33,15 @@ #include "../gen/enums.h" + +#include "llvm/Support/CommandLine.h" + +static llvm::cl::opt ignoreUnsupportedPragmas("ignore", + llvm::cl::desc("Ignore unsupported pragmas"), + llvm::cl::ZeroOrMore); + + + extern void obj_includelib(const char *name); void obj_startaddress(Symbol *s); @@ -962,7 +971,7 @@ #endif // LDC - else if (global.params.ignoreUnsupportedPragmas) + else if (ignoreUnsupportedPragmas) { if (global.params.verbose) { diff -r bce024c60adc -r a8cb25d478c4 dmd/mars.c --- a/dmd/mars.c Thu Feb 19 13:51:44 2009 +0100 +++ b/dmd/mars.c Wed Feb 25 17:34:51 2009 +0100 @@ -40,6 +40,42 @@ #include "gen/linker.h" #include "revisions.h" +#include "gen/cl_options.h" +#include "gen/cl_helpers.h" +using namespace opts; + + +static cl::opt forceBE("forcebe", + cl::desc("Force big-endian"), + cl::Hidden, + cl::ZeroOrMore); + +static cl::opt noDefaultLib("nodefaultlib", + cl::desc("Don't add a default library for linking implicitly"), + cl::ZeroOrMore); + +static ArrayAdapter impPathsStore("I", global.params.imppath); +static cl::list importPaths("I", + cl::desc("Where to look for imports"), + cl::value_desc("path"), + cl::location(impPathsStore), + cl::Prefix); + +static ArrayAdapter defaultLibStore("defaultlib", global.params.defaultlibnames); +static cl::list defaultlibs("defaultlib", + cl::desc("Set default libraries for non-debug build"), + cl::value_desc("lib,..."), + cl::location(defaultLibStore), + cl::CommaSeparated); + +static ArrayAdapter debugLibStore("debuglib", global.params.debuglibnames); +static cl::list debuglibs("debuglib", + cl::desc("Set default libraries for debug build"), + cl::value_desc("lib,..."), + cl::location(debugLibStore), + cl::CommaSeparated); + + void getenv_setargv(const char *envvar, int *pargc, char** *pargv); Global global; @@ -68,13 +104,17 @@ 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) { @@ -150,98 +190,49 @@ extern void backend_init(); extern void backend_term(); -void usage() -{ +void printVersion() { 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/1.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 write object files to directory \n\ - -op do not strip paths from source file\n\ - -oq write object files with fully qualified names\n\ - -of name output file to \n\ - if -c and extension of 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 pass to linker\n\ -\n\ - -w enable warnings\n\ -\n\ - -H generate 'header' file\n\ - -Hd write 'header' file to directory\n\ - -Hf write 'header' file to \n\ -\n\ - -D generate documentation\n\ - -Dd write documentation file to directory\n\ - -Df write documentation file to \n\ -\n\ -Codegen control:\n\ - -m emit code specific to being one of:\n\ - x86 x86-64 ppc32 ppc64 arm thumb\n\ - -t emit code specific to 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 optimize at level (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- and\n\ - -disable- where 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 where to look for imports\n\ - -J 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 -); + printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n" + "LDC Homepage: http://www.dsource.org/projects/ldc\n"); +} + +// Helper function to handle -d-debug=* and -d-version=* +static void processVersions(std::vector& list, char* type, + void (*setLevel)(unsigned), void (*addIdent)(char*)) { + typedef std::vector::iterator It; + + for(It I = list.begin(), E = list.end(); I != E; ++I) { + const char* value = I->c_str(); + if (isdigit(value[0])) { + errno = 0; + char* end; + long level = strtol(value, &end, 10); + if (*end || errno || level > INT_MAX) { + error("Invalid %s level: %s", type, I->c_str()); + } else { + setLevel((unsigned)level); + } + } else { + char* cstr = mem.strdup(value); + if (Lexer::isValidIdentifier(cstr)) { + addIdent(cstr); + continue; + } else { + error("Invalid %s identifier or level: '%s'", type, I->c_str()); + } + } + } +} + +// Helper function to handle -of, -od, etc. +static void initFromString(char*& dest, const cl::opt& src) { + dest = 0; + if (src.getNumOccurrences() != 0) { + if (src.empty()) + error("Expected argument to '-%s'", src.ArgStr); + dest = mem.strdup(src.c_str()); + } } int main(int argc, char *argv[]) @@ -251,28 +242,6 @@ 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 @@ -282,20 +251,7 @@ #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(); @@ -315,14 +271,6 @@ 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"); @@ -365,362 +313,81 @@ } #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; + cl::SetVersionPrinter(&printVersion); + cl::ParseCommandLineOptions(argc, argv, "LLVM-based D Compiler\n"); + + global.params.optimize = (global.params.optimizeLevel >= 0); - case 'd': - if (!p[3]) - goto Lnoarg; - global.params.objdir = p + 3; - break; + // Negated options + global.params.link = !compileOnly; + global.params.obj = !dontWriteObj; + global.params.useInlineAsm = !noAsm; - 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; + // String options: std::string --> char* + initFromString(global.params.objname, objectFile); + initFromString(global.params.objdir, objectDir); + + initFromString(global.params.docdir, ddocDir); + initFromString(global.params.docname, ddocFile); + global.params.doDocComments |= + global.params.docdir || global.params.docname; + +#ifdef _DH + initFromString(global.params.hdrdir, hdrDir); + initFromString(global.params.hdrname, hdrFile); + global.params.doHdrGeneration |= + global.params.hdrdir || global.params.hdrname; +#endif - 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; + processVersions(debugArgs, "debug", + DebugCondition::setGlobalLevel, + DebugCondition::addGlobalIdent); + processVersions(versions, "version", + VersionCondition::setGlobalLevel, + VersionCondition::addGlobalIdent); - 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; + global.params.output_o = + opts::output_o == cl::BOU_UNSET + ? OUTPUTFLAGdefault + : opts::output_o == cl::BOU_TRUE + ? OUTPUTFLAGset + : OUTPUTFLAGno; + global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno; + global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno; + global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno; - 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; + if (global.params.run || !runargs.empty()) { + // FIXME: how to properly detect the presence of a PositionalEatsArgs + // option without parameters? We want to emit an error in that case... + // You'd think getNumOccurrences would do it, but it just returns the + // number of parameters) + // NOTE: Hacked around it by detecting -run in getenv_setargv(), where + // we're looking for it anyway, and pre-setting the flag... + global.params.run = true; + if (!runargs.empty()) { + files.push(mem.strdup(runargs[0].c_str())); + } else { + global.params.run = false; + error("Expected at least one argument to '-run'\n"); } - 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; + } + + if (mArch) + global.params.llvmArch = mArch->Name; - Lnoarg: - error("argument expected for switch '%s'", argv[i]); - continue; - } - } - else - files.push(p); - } + files.reserve(fileList.size()); + typedef std::vector::iterator It; + for(It I = fileList.begin(), E = fileList.end(); I != E; ++I) + if (!I->empty()) + files.push(mem.strdup(I->c_str())); + if (global.errors) { fatal(); } if (files.dim == 0) - { usage(); + { + cl::PrintHelpMessage(); return EXIT_FAILURE; } @@ -740,7 +407,7 @@ global.params.linkswitches->push(arg); } } - else if (!global.params.noDefaultLib) + else if (!noDefaultLib) { char *arg; arg = (char *)mem.malloc(64); @@ -760,7 +427,7 @@ } if (global.params.run) - global.params.quiet = 1; + quiet = 1; if (global.params.useUnitTests) global.params.useAssert = 1; @@ -893,7 +560,7 @@ assert(global.params.cpu != ARCHinvalid); - if (allowForceEndianness && global.params.forceBE) { + if (allowForceEndianness && forceBE) { VersionCondition::addPredefinedGlobalIdent("BigEndian"); global.params.isLE = false; } @@ -1306,8 +973,24 @@ 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 while (1) @@ -1382,6 +1065,11 @@ } 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; } diff -r bce024c60adc -r a8cb25d478c4 dmd/mars.h --- a/dmd/mars.h Thu Feb 19 13:51:44 2009 +0100 +++ b/dmd/mars.h Wed Feb 25 17:34:51 2009 +0100 @@ -17,6 +17,7 @@ #include #include +#include #define __STDC_FORMAT_MACROS 1 #include #include @@ -72,48 +73,40 @@ // Put command line switches in here struct Param { - char obj; // write object file - char link; // perform link - char quiet; // suppress non-error messages - char verbose; // verbose compile + bool obj; // write object file + bool link; // perform link + bool verbose; // verbose compile char symdebug; // insert debug symbolic information - char optimize; // run optimizer + bool optimize; // run optimizer char optimizeLevel; // optimization level ARCH cpu; // target CPU OS os; // target OS - char is64bit; // generate 64 bit code - char isLE; // generate little endian code - char scheduler; // which scheduler to use - char useDeprecated; // allow use of deprecated features - char useAssert; // generate runtime code for assert()'s - char useInvariants; // generate class invariant checks - char useIn; // generate precondition checks - char useOut; // generate postcondition checks - char useArrayBounds; // generate array bounds checks - char useSwitchError; // check for switches without a default - char useUnitTests; // generate unittest code - char useInline; // inline expand functions - char preservePaths; // !=0 means don't strip path from source file - char warnings; // enable warnings - char pic; // generate position-independent-code for shared libs - char noruntime; // code is not allowed to make implicit calls to the runtime - char novalidate;// no bitcode validation + bool is64bit; // generate 64 bit code + bool isLE; // generate little endian code + bool useDeprecated; // allow use of deprecated features + bool useAssert; // generate runtime code for assert()'s + bool useInvariants; // generate class invariant checks + bool useIn; // generate precondition checks + bool useOut; // generate postcondition checks + bool useArrayBounds; // generate array bounds checks + bool useSwitchError; // check for switches without a default + bool useUnitTests; // generate unittest code + bool useInline; // inline expand functions + bool warnings; // enable warnings char Dversion; // D version number - char ignoreUnsupportedPragmas; // rather than error on them char *argv0; // program name Array *imppath; // array of char*'s of where to look for import modules Array *fileImppath; // array of char*'s of where to look for file import modules - char *runtimeImppath; // char* of where to look for the core runtime char *objdir; // .obj file output directory char *objname; // .obj file output name - char doDocComments; // process embedded documentation comments + bool doDocComments; // process embedded documentation comments char *docdir; // write documentation file to docdir directory char *docname; // write documentation file to docname Array *ddocfiles; // macro include files for Ddoc - char doHdrGeneration; // process embedded documentation comments + bool doHdrGeneration; // process embedded documentation comments char *hdrdir; // write 'header' file to docdir directory char *hdrname; // write 'header' file to docname @@ -131,18 +124,16 @@ char *xmlname; // filename for XML output // Hidden debug switches - char debuga; - char debugb; - char debugc; - char debugf; - char debugr; - char debugw; - char debugx; - char debugy; + bool debuga; + bool debugb; + bool debugc; + bool debugf; + bool debugr; + bool debugw; + bool debugx; + bool debugy; - char run; // run resulting executable - size_t runargs_length; - char** runargs; // arguments for executable + bool run; // run resulting executable // Linker stuff Array *objfiles; @@ -153,17 +144,14 @@ char *exefile; // LDC stuff - char *llvmArch; - char forceBE; - char output_ll; - char output_bc; - char output_s; - char output_o; - char llvmInline; - char llvmAnnotate; - char useInlineAsm; - char fqnNames; // use fully qualified object names - char noDefaultLib; + const char *llvmArch; + OUTPUTFLAG output_ll; + OUTPUTFLAG output_bc; + OUTPUTFLAG output_s; + OUTPUTFLAG output_o; + bool llvmInline; + bool llvmAnnotate; + bool useInlineAsm; // target stuff char *targetTriple; diff -r bce024c60adc -r a8cb25d478c4 dmd/module.c --- a/dmd/module.c Thu Feb 19 13:51:44 2009 +0100 +++ b/dmd/module.c Wed Feb 25 17:34:51 2009 +0100 @@ -44,6 +44,19 @@ #include "d-dmd-gcc.h" #endif + +#include "llvm/Support/CommandLine.h" + +static llvm::cl::opt preservePaths("op", + llvm::cl::desc("Do not strip paths from source file"), + llvm::cl::ZeroOrMore); + +static llvm::cl::opt fqnNames("oq", + llvm::cl::desc("Write object files with fully qualified names"), + llvm::cl::ZeroOrMore); + + + ClassDeclaration *Module::moduleinfo; Module *Module::rootModule; @@ -139,12 +152,12 @@ argobj = forcename; else { - if (global.params.preservePaths) + if (preservePaths) argobj = (char*)this->arg; else argobj = FileName::name((char*)this->arg); - if (global.params.fqnNames) + if (fqnNames) { if(md) argobj = FileName::replaceName(argobj, md->toChars()); diff -r bce024c60adc -r a8cb25d478c4 gen/cl_helpers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/cl_helpers.cpp Wed Feb 25 17:34:51 2009 +0100 @@ -0,0 +1,81 @@ +#include "gen/cl_helpers.h" + +#include "dmd/root.h" +#include "dmd/mem.h" + +#include // isupper, tolower +#include +#include +#include + +namespace opts { + +// Helper function +static char toLower(char c) { + if (isupper(c)) + return tolower(c); + return c; +} + +bool FlagParser::parse(cl::Option &O, const char *ArgName, const std::string &Arg, bool &Val) { + // Make a std::string out of it to make comparisons easier + // (and avoid repeated conversion) + std::string argname = ArgName; + + typedef std::vector >::iterator It; + for (It I = switches.begin(), E = switches.end(); I != E; ++I) { + std::string name = I->first; + if (name == argname + || (name.length() < argname.length() + && argname.substr(0, name.length()) == name + && argname[name.length()] == '=')) { + + if (!cl::parser::parse(O, ArgName, Arg, Val)) { + Val = (Val == I->second); + return false; + } + // Invalid option value + break; + } + } + return true; +} + +void FlagParser::getExtraOptionNames(std::vector &Names) { + typedef std::vector >::iterator It; + for (It I = switches.begin() + 1, E = switches.end(); I != E; ++I) { + Names.push_back(I->first.c_str()); + } +} + + +MultiSetter::MultiSetter(bool invert, bool* p, ...) { + this->invert = invert; + if (p) { + locations.push_back(p); + va_list va; + va_start(va, p); + while (p = va_arg(va, bool*)) { + locations.push_back(p); + } + } +} + +void MultiSetter::operator=(bool val) { + typedef std::vector::iterator It; + for (It I = locations.begin(), E = locations.end(); I != E; ++I) { + **I = (val != invert); + } +} + + +void ArrayAdapter::push_back(const char* cstr) { + if (!cstr || !*cstr) + error("Expected argument to '-%s'", name); + + if (!*arrp) + *arrp = new Array; + (*arrp)->push(mem.strdup(cstr)); +} + +} // namespace opts diff -r bce024c60adc -r a8cb25d478c4 gen/cl_helpers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/cl_helpers.h Wed Feb 25 17:34:51 2009 +0100 @@ -0,0 +1,68 @@ +#ifndef LDC_CL_HELPERS_H +#define LDC_CL_HELPERS_H + +#include + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" + +struct Array; + +namespace opts { + namespace cl = llvm::cl; + + /// Helper class for fancier options + class FlagParser : public cl::parser { + std::vector > switches; + public: + template + void initialize(Opt &O) { + assert(!(O.getMiscFlags() & cl::AllowInverse) + && "FlagParser doesn't support redundant AllowInverse flag"); + + std::string Name = O.ArgStr; + switches.push_back(make_pair("enable-" + Name, true)); + switches.push_back(make_pair("disable-" + Name, false)); + // Replace with -enable- + O.ArgStr = switches[0].first.c_str(); + } + + bool parse(cl::Option &O, const char *ArgName, const std::string &ArgValue, bool &Val); + + void getExtraOptionNames(std::vector &Names); + }; + + /// Helper class for options that set multiple flags + class MultiSetter { + std::vector locations; + bool invert; + MultiSetter(bool); //not implemented, disable auto-conversion + public: + MultiSetter(bool invert, bool* p, ...) END_WITH_NULL; + + void operator=(bool val); + }; + + /// Helper class to fill Array with char* when given strings + /// (Errors on empty strings) + class ArrayAdapter { + const char* name; + Array** arrp; + public: + ArrayAdapter(const char* name_, Array*& arr) { + name = name_; + arrp = &arr; + assert(name); + assert(arrp); + } + + void push_back(const char* cstr); + + void push_back(const std::string& str) { + push_back(str.c_str()); + } + }; + +} + +#endif diff -r bce024c60adc -r a8cb25d478c4 gen/cl_options.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/cl_options.cpp Wed Feb 25 17:34:51 2009 +0100 @@ -0,0 +1,337 @@ +#include "gen/cl_options.h" +#include "gen/cl_helpers.h" + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" + +#include "gen/logger.h" + +#include "llvm/Support/CommandLine.h" + +namespace opts { + +// Positional options first, in order: +cl::list fileList( + cl::Positional, cl::desc("files")); + +cl::list runargs("run", + cl::desc("program args..."), + cl::Positional, + cl::PositionalEatsArgs); + + + +// TODO: Replace this with a proper PassNameParser-based solution +static cl::opt doInline("inline", + cl::desc("Do function inlining"), + cl::location(global.params.llvmInline), + cl::ZeroOrMore, + cl::init(false)); + + + +static cl::opt useDeprecated("d", + cl::desc("Allow deprecated language features"), + cl::ZeroOrMore, + cl::location(global.params.useDeprecated)); + +static cl::opt useDv1( + cl::desc("Force language version:"), + cl::ZeroOrMore, + cl::values( + clEnumValN(1, "v1", "D language version 1.00"), + clEnumValEnd), + cl::location(global.params.Dversion), + cl::init(2), + cl::Hidden); + +cl::opt compileOnly("c", + cl::desc("Do not link"), + cl::ZeroOrMore); + +static cl::opt verbose("v", + cl::desc("Verbose"), + cl::ZeroOrMore, + cl::location(global.params.verbose)); + +static cl::opt warnings("w", + cl::desc("Enable warnings"), + cl::ZeroOrMore, + cl::location(global.params.warnings)); + + +static cl::opt optimizeLevel( + cl::desc("Setting the optimization level:"), + cl::ZeroOrMore, + cl::values( + clEnumValN(2, "O", "Equivalent to -O2"), + clEnumValN(0, "O0", "Trivial optimizations only"), + clEnumValN(1, "O1", "Simple optimizations"), + clEnumValN(2, "O2", "Good optimizations"), + clEnumValN(3, "O3", "Aggressive optimizations"), + clEnumValN(4, "O4", "Link-time optimization"), // not implemented? + clEnumValN(5, "O5", "Link-time optimization"), // not implemented? + clEnumValEnd), + cl::location(global.params.optimizeLevel), + cl::init(-1)); + +static cl::opt debugInfo( + cl::desc("Generating debug information:"), + cl::ZeroOrMore, + cl::values( + clEnumValN(1, "g", "Generate debug information"), + clEnumValN(2, "gc", "Same as -g, but pretend to be C"), + clEnumValEnd), + cl::location(global.params.symdebug), + cl::init(0)); + + +static cl::opt annotate("annotate", + cl::desc("Annotate the bitcode with human readable source code"), + cl::location(global.params.llvmAnnotate)); + +cl::opt noAsm("noasm", + cl::desc("Disallow use of inline assembler")); + +// Output file options +cl::opt dontWriteObj("o-", + cl::desc("Do not write object file")); + +cl::opt objectFile("of", + cl::value_desc("filename"), + cl::Prefix, + cl::desc("Use as output file name")); + +cl::opt objectDir("od", + cl::value_desc("objdir"), + cl::Prefix, + cl::desc("Write object files to directory ")); + + +// Output format options +cl::opt output_bc("output-bc", + cl::desc("Write LLVM bitcode")); + +cl::opt output_ll("output-ll", + cl::desc("Write LLVM IR")); + +cl::opt output_s("output-s", + cl::desc("Write native assembly")); + +cl::opt output_o("output-o", + cl::desc("Write native object")); + + +// DDoc options +static cl::opt doDdoc("D", + cl::desc("Generate documentation"), + cl::location(global.params.doDocComments)); + +cl::opt ddocDir("Dd", + cl::desc("Write documentation file to directory"), + cl::value_desc("docdir"), + cl::Prefix); + +cl::opt ddocFile("Df", + cl::desc("Write documentation file to "), + cl::value_desc("filename"), + cl::Prefix); + + +// Header generation options +#ifdef _DH +static cl::opt doHdrGen("H", + cl::desc("Generate 'header' file"), + cl::location(global.params.doHdrGeneration)); + +cl::opt hdrDir("Hd", + cl::desc("Write 'header' file to directory"), + cl::value_desc("hdrdir"), + cl::Prefix); + +cl::opt hdrFile("Hf", + cl::desc("Write 'header' file to "), + cl::value_desc("filename"), + cl::Prefix); +#endif + + + +static cl::opt unittest("unittest", + cl::desc("Compile in unit tests"), + cl::location(global.params.useUnitTests)); + + +static ArrayAdapter strImpPathStore("J", global.params.fileImppath); +static cl::list stringImportPaths("J", + cl::desc("Where to look for string imports"), + cl::value_desc("path"), + cl::location(strImpPathStore), + cl::Prefix); + + + +// -d-debug is a bit messy, it has 3 modes: +// -d-debug=ident, -d-debug=level and -d-debug (without argument) +// That last of these must be acted upon immediately to ensure proper +// interaction with other options, so it needs some special handling: +std::vector debugArgs; + +struct D_DebugStorage { + void push_back(const std::string& str) { + if (str.empty()) { + // Bare "-d-debug" has a special meaning. + global.params.useAssert = true; + global.params.useArrayBounds = true; + global.params.useInvariants = true; + global.params.useIn = true; + global.params.useOut = true; + debugArgs.push_back("1"); + } else { + debugArgs.push_back(str); + } + } +}; + +static D_DebugStorage dds; + +// -debug is already declared in LLVM (at least, in debug builds), +// so we need to be a bit more verbose. +static cl::list debugVersionsOption("d-debug", + cl::desc("Compile in debug code >= or identified by ."), + cl::value_desc("level/idents"), + cl::location(dds), + cl::CommaSeparated, + cl::ValueOptional); + + + +// -version is also declared in LLVM, so again we need to be a bit more verbose. +cl::list versions("d-version", + cl::desc("Compile in version code >= or identified by "), + cl::value_desc("level/idents"), + cl::CommaSeparated); + + +static ArrayAdapter linkSwitchStore("L", global.params.linkswitches); +static cl::list linkerSwitches("L", + cl::desc("Pass to the linker"), + cl::value_desc("linkerflag"), + cl::location(linkSwitchStore), + cl::Prefix); + + +cl::opt > mArch("march", + cl::desc("Architecture to generate code for:")); + +static cl::alias m("m", + cl::desc("Alias for '-march' for backwards compatibility"), + cl::Prefix, + cl::aliasopt(mArch)); + + +static cl::opt os("t", + cl::desc("Emit code for the specified OS:"), + cl::values( +#define ENUMVAL_N(Name, Desc) clEnumValN(OS##Name, #Name, Desc) +#define ENUMVAL(Name) ENUMVAL_N(Name, #Name) + ENUMVAL(Linux), + ENUMVAL(Windows), + ENUMVAL_N(MacOSX, "Mac OS X"), + ENUMVAL(FreeBSD), + ENUMVAL(Solaris), +#undef ENUMVAL +#undef ENUMVAL_N + clEnumValEnd), + cl::Prefix, + cl::location(global.params.os)); + + +// "Hidden debug switches" +// Are these ever used? +static cl::opt debuga("hidden-debug--a", + cl::desc("Hidden debug option A"), + cl::ReallyHidden, + cl::location(global.params.debuga)); +static cl::opt debugb("hidden-debug-b", + cl::desc("Hidden debug option B"), + cl::ReallyHidden, + cl::location(global.params.debugb)); +static cl::opt debugc("hidden-debug-c", + cl::desc("Hidden debug option C"), + cl::ReallyHidden, + cl::location(global.params.debugc)); +static cl::opt debugf("hidden-debug-f", + cl::desc("Hidden debug option F"), + cl::ReallyHidden, + cl::location(global.params.debugf)); +static cl::opt debugr("hidden-debug-r", + cl::desc("Hidden debug option R"), + cl::ReallyHidden, + cl::location(global.params.debugr)); +static cl::opt debugw("hidden-debug-w", + cl::desc("Hidden debug option W"), + cl::ReallyHidden, + cl::location(global.params.debugw)); +static cl::opt debugx("hidden-debug-x", + cl::desc("Hidden debug option X"), + cl::ReallyHidden, + cl::location(global.params.debugx)); +static cl::opt debugy("hidden-debug-y", + cl::desc("Hidden debug option Y"), + cl::ReallyHidden, + cl::location(global.params.debugy)); + + +static cl::opt asserts("asserts", + cl::desc("(*) Enable assertions"), + cl::value_desc("bool"), + cl::location(global.params.useAssert), + cl::init(true)); + +static cl::opt boundsChecks("boundscheck", + cl::desc("(*) Enable array bounds checks"), + cl::value_desc("bool"), + cl::location(global.params.useArrayBounds), + cl::init(true)); + +static cl::opt invariants("invariants", + cl::desc("(*) Enable invariants"), + cl::location(global.params.useInvariants), + cl::init(true)); + +static cl::opt preconditions("preconditions", + cl::desc("(*) Enable function preconditions"), + cl::location(global.params.useIn), + cl::init(true)); + +static cl::opt postconditions("postconditions", + cl::desc("(*) Enable function postconditions"), + cl::location(global.params.useOut), + cl::init(true)); + + +static MultiSetter ContractsSetter(false, + &global.params.useIn, &global.params.useOut, NULL); +static cl::opt contracts("contracts", + cl::desc("(*) Enable function pre- and post-conditions"), + cl::location(ContractsSetter)); + +static MultiSetter ReleaseSetter(true, &global.params.useAssert, + &global.params.useArrayBounds, &global.params.useInvariants, + &global.params.useOut, &global.params.useIn, NULL); +static cl::opt > release("release", + cl::desc("Disables asserts, invariants, contracts and boundscheck"), + cl::location(ReleaseSetter), + cl::ValueDisallowed); + + +static cl::extrahelp footer("\n" +"-d-debug can also be specified without options, in which case it enables all\n" +"debug checks (i.e. (asserts, boundchecks, contracts and invariants) as well\n" +"as acting as -d-debug=1\n\n" +"Options marked with (*) also have a -disable-FOO variant with inverted\n" +"meaning.\n"); + +} // namespace opts diff -r bce024c60adc -r a8cb25d478c4 gen/cl_options.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/cl_options.h Wed Feb 25 17:34:51 2009 +0100 @@ -0,0 +1,46 @@ +#ifndef LDC_CL_OPTIONS_H +#define LDC_CL_OPTIONS_H + +#include "mars.h" + +#include +#include + +#include "llvm/Support/RegistryParser.h" +#include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/Support/CommandLine.h" + +namespace opts { + namespace cl = llvm::cl; + + /* Mostly generated with the following command: + egrep -e '^(cl::|#if|#e)' gen/cl_options.cpp \ + | sed -re 's/^(cl::.*)\(.*$/ extern \1;/' + */ + extern cl::list fileList; + extern cl::list runargs; + extern cl::opt compileOnly; + extern cl::opt noAsm; + extern cl::opt dontWriteObj; + extern cl::opt objectFile; + extern cl::opt objectDir; + extern cl::opt output_bc; + extern cl::opt output_ll; + extern cl::opt output_s; + extern cl::opt output_o; + extern cl::opt ddocDir; + extern cl::opt ddocFile; +#ifdef _DH + extern cl::opt hdrDir; + extern cl::opt hdrFile; +#endif + extern cl::list versions; + + extern cl::opt > mArch; + + // Arguments to -d-debug + extern std::vector debugArgs; + // Arguments to -run +} +#endif diff -r bce024c60adc -r a8cb25d478c4 gen/linker.cpp --- a/gen/linker.cpp Thu Feb 19 13:51:44 2009 +0100 +++ b/gen/linker.cpp Wed Feb 25 17:34:51 2009 +0100 @@ -1,3 +1,4 @@ +#include "gen/linker.h" #include "gen/llvm.h" #include "llvm/Linker.h" #include "llvm/System/Program.h" @@ -11,6 +12,16 @@ #define NO_COUT_LOGGER #include "gen/logger.h" +#include "gen/cl_options.h" + +////////////////////////////////////////////////////////////////////////////// + +// Is this useful? +llvm::cl::opt quiet("quiet", + llvm::cl::desc("Suppress output of link command (unless -v is also passed)"), + llvm::cl::Hidden, + llvm::cl::ZeroOrMore, + llvm::cl::init(true)); ////////////////////////////////////////////////////////////////////////////// @@ -173,7 +184,7 @@ } // print link command? - if (!global.params.quiet || global.params.verbose) + if (!quiet || global.params.verbose) { // Print it for (int i = 0; i < args.size(); i++) @@ -311,7 +322,7 @@ args.push_back("-m64"); // print link command? - if (!global.params.quiet || global.params.verbose) + if (!quiet || global.params.verbose) { // Print it for (int i = 0; i < args.size(); i++) @@ -363,10 +374,12 @@ // build arguments std::vector args; - for (size_t i = 0; i < global.params.runargs_length; i++) + // args[0] should be the name of the executable + args.push_back(gExePath.toString().c_str()); + // Skip first argument to -run; it's a D source file. + for (size_t i = 1, length = opts::runargs.size(); i < length; i++) { - char *a = global.params.runargs[i]; - args.push_back(a); + args.push_back(opts::runargs[i].c_str()); } // terminate args list args.push_back(NULL); diff -r bce024c60adc -r a8cb25d478c4 gen/linker.h --- a/gen/linker.h Thu Feb 19 13:51:44 2009 +0100 +++ b/gen/linker.h Wed Feb 25 17:34:51 2009 +0100 @@ -1,8 +1,11 @@ #ifndef LDC_GEN_LINKER_H #define LDC_GEN_LINKER_H +#include "llvm/Support/CommandLine.h" #include +extern llvm::cl::opt quiet; + namespace llvm { class Module; diff -r bce024c60adc -r a8cb25d478c4 gen/logger.cpp --- a/gen/logger.cpp Thu Feb 19 13:51:44 2009 +0100 +++ b/gen/logger.cpp Wed Feb 25 17:34:51 2009 +0100 @@ -8,6 +8,7 @@ #include "mars.h" +#include "llvm/Support/CommandLine.h" #include "gen/logger.h" namespace Logger @@ -15,7 +16,10 @@ static std::string indent_str; static std::ofstream null_out("/dev/null"); - static bool _enabled = false; + llvm::cl::opt _enabled("vv", + llvm::cl::desc("Very verbose"), + llvm::cl::ZeroOrMore); + void indent() { if (_enabled) { diff -r bce024c60adc -r a8cb25d478c4 gen/runtime.cpp --- a/gen/runtime.cpp Thu Feb 19 13:51:44 2009 +0100 +++ b/gen/runtime.cpp Wed Feb 25 17:34:51 2009 +0100 @@ -2,6 +2,7 @@ #include "llvm/Module.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/CommandLine.h" #include "root.h" #include "mars.h" @@ -15,6 +16,14 @@ #include "gen/tollvm.h" #include "gen/irstate.h" +////////////////////////////////////////////////////////////////////////////////////////////////// + +static llvm::cl::opt noruntime("noruntime", + llvm::cl::desc("Do not allow code that generates implicit runtime calls"), + llvm::cl::ZeroOrMore); + +////////////////////////////////////////////////////////////////////////////////////////////////// + static llvm::Module* M = NULL; static bool runtime_failed = false; @@ -44,7 +53,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name) { - if (global.params.noruntime) { + if (noruntime) { error("No implicit runtime calls allowed with -noruntime option enabled"); fatal(); } @@ -80,7 +89,7 @@ return gv; } - if (global.params.noruntime) { + if (noruntime) { error("No implicit runtime calls allowed with -noruntime option enabled"); fatal(); } diff -r bce024c60adc -r a8cb25d478c4 gen/toobj.cpp --- a/gen/toobj.cpp Thu Feb 19 13:51:44 2009 +0100 +++ b/gen/toobj.cpp Wed Feb 25 17:34:51 2009 +0100 @@ -24,6 +24,7 @@ #include "llvm/System/Program.h" #include "llvm/System/Path.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/CommandLine.h" #include "mars.h" #include "module.h" @@ -55,6 +56,12 @@ ////////////////////////////////////////////////////////////////////////////////////////// +static llvm::cl::opt noVerify("noverify", + llvm::cl::desc("Do not run the validation pass before writing bitcode"), + llvm::cl::ZeroOrMore); + +////////////////////////////////////////////////////////////////////////////////////////// + // in gen/optimize.cpp void ldc_optimize_module(llvm::Module* m, char lvl, bool doinline); @@ -124,10 +131,6 @@ // for (unsigned i = 0; i != MAttrs.size(); ++i) // Features.AddFeature(MAttrs[i]); - // only generate PIC code when -fPIC switch is used - if (global.params.pic) - llvm::TargetMachine::setRelocationModel(llvm::Reloc::PIC_); - // allocate the target machine std::auto_ptr target(MArch->CtorFn(*ir.module, Features.getString())); assert(target.get() && "Could not allocate target machine!"); @@ -182,7 +185,7 @@ } // verify the llvm - if (!global.params.novalidate) { + if (!noVerify) { std::string verifyErr; Logger::println("Verifying module..."); LOG_SCOPE; @@ -200,7 +203,7 @@ ldc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline); // verify the llvm - if (!global.params.novalidate && (global.params.optimizeLevel >= 0 || global.params.llvmInline)) { + if (!noVerify && (global.params.optimizeLevel >= 0 || global.params.llvmInline)) { std::string verifyErr; Logger::println("Verifying module... again..."); LOG_SCOPE; diff -r bce024c60adc -r a8cb25d478c4 ldc-posix-tango --- a/ldc-posix-tango Thu Feb 19 13:51:44 2009 +0100 +++ b/ldc-posix-tango Wed Feb 25 17:34:51 2009 +0100 @@ -38,7 +38,7 @@ [compile] oneatatime=yes -cmd=ldc -c $i +cmd=ldmd -c $i flag=$i incdir=-I$i diff -r bce024c60adc -r a8cb25d478c4 ldc.conf.in --- a/ldc.conf.in Thu Feb 19 13:51:44 2009 +0100 +++ b/ldc.conf.in Wed Feb 25 17:34:51 2009 +0100 @@ -1,2 +1,2 @@ [Environment] -DFLAGS=-I@RUNTIME_DIR@ -I@RUNTIME_DIR@/lib/common -L-L%@P%/../lib -version=Tango -defaultlib=@RUNTIME_AIO@ -debuglib=@RUNTIME_AIO@ +DFLAGS=-I@RUNTIME_DIR@ -I@RUNTIME_DIR@/lib/common -L-L%@P%/../lib -d-version=Tango -defaultlib=@RUNTIME_AIO@ -debuglib=@RUNTIME_AIO@ diff -r bce024c60adc -r a8cb25d478c4 tango.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango.patch Wed Feb 25 17:34:51 2009 +0100 @@ -0,0 +1,56 @@ +Index: lib/unittest.sh +=================================================================== +--- lib/unittest.sh (revision 4330) ++++ lib/unittest.sh (working copy) +@@ -15,14 +15,14 @@ + usage() { + echo 'Usage: ./unittest.sh [otions ...] + Options: +- --help: This message ++ --help: This message + --run-all: Reports result instead of breaking. Do not use this if you want to +- run unittest runner through a debugger. +- dmd: Builds unittests for dmd +- gdc: Builds unittests for gdc +- ldc: Builds unittests for ldc ++ run unittest runner through a debugger. ++ dmd: Builds unittests for dmd ++ gdc: Builds unittests for gdc ++ ldc: Builds unittests for ldc + +- : Builds unittests for all known compilers.' ++ : Builds unittests for all known compilers.' + exit 0 + } + +@@ -37,7 +37,7 @@ + + rebuild --help >& /dev/null || die "rebuild required, aborting" 1 + +- if ! $DC --help >& /dev/null ++ if ! which $DC >& /dev/null + then + echo "$DC not found on your \$PATH!" + else +Index: lib/build-tango.sh +=================================================================== +--- lib/build-tango.sh (revision 4330) ++++ lib/build-tango.sh (working copy) +@@ -131,7 +131,7 @@ + DC=$1 + LIB=$2 + +- if ! $DC --help >& /dev/null ++ if ! which "$DC" >& /dev/null + then + echo "$DC not found on your \$PATH!" + return +@@ -203,7 +203,7 @@ + build gdmd libgtango.a libgphobos.a + ;; + ldc) +- build ldc libtango-user-ldc.a build-tango.sh ++ build ldmd libtango-user-ldc.a build-tango.sh + ;; + mac) + POSIXFLAG="-version=Posix"