mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 00:20:40 +03:00
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)
This commit is contained in:
parent
6a02292c10
commit
b3d87205ad
17 changed files with 908 additions and 549 deletions
41
bin/ldmd
Executable file
41
bin/ldmd
Executable file
|
@ -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[@]}"
|
11
dmd/attrib.c
11
dmd/attrib.c
|
@ -33,6 +33,15 @@
|
||||||
|
|
||||||
#include "../gen/enums.h"
|
#include "../gen/enums.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> ignoreUnsupportedPragmas("ignore",
|
||||||
|
llvm::cl::desc("Ignore unsupported pragmas"),
|
||||||
|
llvm::cl::ZeroOrMore);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern void obj_includelib(const char *name);
|
extern void obj_includelib(const char *name);
|
||||||
void obj_startaddress(Symbol *s);
|
void obj_startaddress(Symbol *s);
|
||||||
|
|
||||||
|
@ -962,7 +971,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
|
|
||||||
#endif // LDC
|
#endif // LDC
|
||||||
|
|
||||||
else if (global.params.ignoreUnsupportedPragmas)
|
else if (ignoreUnsupportedPragmas)
|
||||||
{
|
{
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
{
|
{
|
||||||
|
|
652
dmd/mars.c
652
dmd/mars.c
|
@ -40,6 +40,42 @@
|
||||||
#include "gen/linker.h"
|
#include "gen/linker.h"
|
||||||
#include "revisions.h"
|
#include "revisions.h"
|
||||||
|
|
||||||
|
#include "gen/cl_options.h"
|
||||||
|
#include "gen/cl_helpers.h"
|
||||||
|
using namespace opts;
|
||||||
|
|
||||||
|
|
||||||
|
static cl::opt<bool> forceBE("forcebe",
|
||||||
|
cl::desc("Force big-endian"),
|
||||||
|
cl::Hidden,
|
||||||
|
cl::ZeroOrMore);
|
||||||
|
|
||||||
|
static cl::opt<bool> 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<std::string, ArrayAdapter> 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<std::string, ArrayAdapter> 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<std::string, ArrayAdapter> 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);
|
void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
|
||||||
|
|
||||||
Global global;
|
Global global;
|
||||||
|
@ -68,13 +104,17 @@ Global::Global()
|
||||||
llvm_version = LLVM_REV;
|
llvm_version = LLVM_REV;
|
||||||
global.structalign = 8;
|
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
|
char *Loc::toChars() const
|
||||||
{
|
{
|
||||||
OutBuffer buf;
|
OutBuffer buf;
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (filename)
|
if (filename)
|
||||||
{
|
{
|
||||||
|
@ -150,98 +190,49 @@ void halt()
|
||||||
extern void backend_init();
|
extern void backend_init();
|
||||||
extern void backend_term();
|
extern void backend_term();
|
||||||
|
|
||||||
void usage()
|
void printVersion() {
|
||||||
{
|
|
||||||
printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n",
|
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);
|
global.ldc_version, global.version, global.llvm_version, global.copyright, global.written);
|
||||||
printf("\
|
printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n"
|
||||||
D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
|
"LDC Homepage: http://www.dsource.org/projects/ldc\n");
|
||||||
LDC Homepage: http://www.dsource.org/projects/ldc\n\
|
}
|
||||||
Usage:\n\
|
|
||||||
ldc files.d ... { -switch }\n\
|
// Helper function to handle -d-debug=* and -d-version=*
|
||||||
\n\
|
static void processVersions(std::vector<std::string>& list, char* type,
|
||||||
files.d D source files\n%s\
|
void (*setLevel)(unsigned), void (*addIdent)(char*)) {
|
||||||
-o- do not write object file\n\
|
typedef std::vector<std::string>::iterator It;
|
||||||
-od<objdir> write object files to directory <objdir>\n\
|
|
||||||
-op do not strip paths from source file\n\
|
for(It I = list.begin(), E = list.end(); I != E; ++I) {
|
||||||
-oq write object files with fully qualified names\n\
|
const char* value = I->c_str();
|
||||||
-of<filename> name output file to <filename>\n\
|
if (isdigit(value[0])) {
|
||||||
if -c and extension of <filename> is known, it determines the output type\n\
|
errno = 0;
|
||||||
\n\
|
char* end;
|
||||||
-output-ll write LLVM IR\n\
|
long level = strtol(value, &end, 10);
|
||||||
-output-bc write LLVM bitcode\n\
|
if (*end || errno || level > INT_MAX) {
|
||||||
-output-s write native assembly\n\
|
error("Invalid %s level: %s", type, I->c_str());
|
||||||
-output-o write native object (default if no -output switch passed)\n\
|
} else {
|
||||||
\n\
|
setLevel((unsigned)level);
|
||||||
-c do not link\n\
|
}
|
||||||
-L<linkerflag> pass <linkerflag> to linker\n\
|
} else {
|
||||||
\n\
|
char* cstr = mem.strdup(value);
|
||||||
-w enable warnings\n\
|
if (Lexer::isValidIdentifier(cstr)) {
|
||||||
\n\
|
addIdent(cstr);
|
||||||
-H generate 'header' file\n\
|
continue;
|
||||||
-Hd<hdrdir> write 'header' file to <hdrdir> directory\n\
|
} else {
|
||||||
-Hf<filename> write 'header' file to <filename>\n\
|
error("Invalid %s identifier or level: '%s'", type, I->c_str());
|
||||||
\n\
|
}
|
||||||
-D generate documentation\n\
|
}
|
||||||
-Dd<docdir> write documentation file to <docdir> directory\n\
|
}
|
||||||
-Df<filename> write documentation file to <filename>\n\
|
}
|
||||||
\n\
|
|
||||||
Codegen control:\n\
|
// Helper function to handle -of, -od, etc.
|
||||||
-m<arch> emit code specific to <arch> being one of:\n\
|
static void initFromString(char*& dest, const cl::opt<std::string>& src) {
|
||||||
x86 x86-64 ppc32 ppc64 arm thumb\n\
|
dest = 0;
|
||||||
-t<os> emit code specific to <os> being one of:\n\
|
if (src.getNumOccurrences() != 0) {
|
||||||
Linux, Windows, MacOSX, FreeBSD, Solaris\n\
|
if (src.empty())
|
||||||
\n\
|
error("Expected argument to '-%s'", src.ArgStr);
|
||||||
-g, -gc add symbolic debug info\n\
|
dest = mem.strdup(src.c_str());
|
||||||
\n\
|
}
|
||||||
-O optimize, same as -O2\n\
|
|
||||||
-O<n> optimize at level <n> (0-5)\n\
|
|
||||||
-inline do function inlining\n\
|
|
||||||
\n\
|
|
||||||
-debug enables asserts, invariants, contracts, boundscheck\n\
|
|
||||||
and sets debug=1\n\
|
|
||||||
-release disables asserts, invariants, contracts, boundscheck\n\
|
|
||||||
\n\
|
|
||||||
-enable-<feature> and\n\
|
|
||||||
-disable-<feature> where <feature> is one of\n\
|
|
||||||
asserts assert statements (default: on)\n\
|
|
||||||
invariants class and struct invariants (default: on)\n\
|
|
||||||
contracts function contracts (default: on)\n\
|
|
||||||
boundscheck array bounds checking (default: on)\n\
|
|
||||||
-debug=level compile in debug stmts <= level (default: 0)\n\
|
|
||||||
-debug=ident compile in debug stmts identified by ident\n\
|
|
||||||
-version=level compile in version code >= level\n\
|
|
||||||
-version=ident compile in version code identified by ident\n\
|
|
||||||
\n\
|
|
||||||
-noasm do not allow use of inline asm\n\
|
|
||||||
-noruntime do not allow code that generates implicit runtime calls\n\
|
|
||||||
-noverify do not run the validation pass before writing bitcode\n\
|
|
||||||
-unittest compile in unit tests\n\
|
|
||||||
-d allow deprecated features\n\
|
|
||||||
\n\
|
|
||||||
-annotate annotate the bitcode with human readable source code\n\
|
|
||||||
-ignore ignore unsupported pragmas\n\
|
|
||||||
\n\
|
|
||||||
Path options:\n\
|
|
||||||
-I<path> where to look for imports\n\
|
|
||||||
-J<path> where to look for string imports\n\
|
|
||||||
-defaultlib=name set default library for non-debug build\n\
|
|
||||||
-debuglib=name set default library for debug build\n\
|
|
||||||
-nodefaultlib don't add a default library for linking implicitly\n\
|
|
||||||
\n\
|
|
||||||
Misc options:\n\
|
|
||||||
-v verbose\n\
|
|
||||||
-vv very verbose (does not include -v)\n\
|
|
||||||
-quiet suppress unnecessary messages\n\
|
|
||||||
-run srcfile args... run resulting program, passing args\n\
|
|
||||||
--help print help\n\
|
|
||||||
",
|
|
||||||
#if WIN32
|
|
||||||
" @cmdfile read arguments from cmdfile\n"
|
|
||||||
#else
|
|
||||||
""
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -251,28 +242,6 @@ int main(int argc, char *argv[])
|
||||||
char *p, *ext;
|
char *p, *ext;
|
||||||
Module *m;
|
Module *m;
|
||||||
int status = EXIT_SUCCESS;
|
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
|
// Set default values
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
@ -282,20 +251,7 @@ int main(int argc, char *argv[])
|
||||||
#else
|
#else
|
||||||
global.params.argv0 = argv[0];
|
global.params.argv0 = argv[0];
|
||||||
#endif
|
#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.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.linkswitches = new Array();
|
||||||
global.params.libfiles = new Array();
|
global.params.libfiles = new Array();
|
||||||
|
@ -315,14 +271,6 @@ int main(int argc, char *argv[])
|
||||||
fatal();
|
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
|
// Predefine version identifiers
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
VersionCondition::addPredefinedGlobalIdent("LLVM");
|
VersionCondition::addPredefinedGlobalIdent("LLVM");
|
||||||
|
@ -365,362 +313,81 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 1; i < argc; i++)
|
cl::SetVersionPrinter(&printVersion);
|
||||||
{
|
cl::ParseCommandLineOptions(argc, argv, "LLVM-based D Compiler\n");
|
||||||
p = argv[i];
|
|
||||||
if (*p == '-')
|
|
||||||
{
|
|
||||||
if (strcmp(p + 1, "d") == 0)
|
|
||||||
global.params.useDeprecated = 1;
|
|
||||||
else if (strcmp(p + 1, "c") == 0)
|
|
||||||
global.params.link = 0;
|
|
||||||
else if (strcmp(p + 1, "fPIC") == 0)
|
|
||||||
global.params.pic = 1;
|
|
||||||
else if (strcmp(p + 1, "g") == 0)
|
|
||||||
global.params.symdebug = 1;
|
|
||||||
else if (strcmp(p + 1, "gc") == 0)
|
|
||||||
global.params.symdebug = 2;
|
|
||||||
else if (strcmp(p + 1, "v") == 0)
|
|
||||||
global.params.verbose = 1;
|
|
||||||
else if (strcmp(p + 1, "vv") == 0) {
|
|
||||||
Logger::enable();
|
|
||||||
very_verbose = true;
|
|
||||||
}
|
|
||||||
else if (strcmp(p + 1, "v1") == 0)
|
|
||||||
global.params.Dversion = 1;
|
|
||||||
else if (strcmp(p + 1, "w") == 0)
|
|
||||||
global.params.warnings = 1;
|
|
||||||
else if (p[1] == 'O')
|
|
||||||
{
|
|
||||||
global.params.optimize = 1;
|
|
||||||
global.params.optimizeLevel = 2;
|
|
||||||
if (p[2] != 0) {
|
|
||||||
int optlevel = atoi(p+2);
|
|
||||||
if (optlevel < 0 || optlevel > 5) {
|
|
||||||
error("Optimization level must be between 0 and 5. Using default (%d)",
|
|
||||||
global.params.optimizeLevel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
global.params.optimizeLevel = optlevel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(p + 1, "forcebe") == 0)
|
|
||||||
global.params.forceBE = 1;
|
|
||||||
else if (strcmp(p + 1, "noruntime") == 0)
|
|
||||||
global.params.noruntime = 1;
|
|
||||||
else if (strcmp(p + 1, "noverify") == 0)
|
|
||||||
global.params.novalidate = 1;
|
|
||||||
else if (strcmp(p + 1, "annotate") == 0)
|
|
||||||
global.params.llvmAnnotate = 1;
|
|
||||||
else if (strncmp(p + 1, "enable-", 7) == 0 ||
|
|
||||||
strncmp(p + 1, "disable-", 8) == 0)
|
|
||||||
{
|
|
||||||
bool enable = (p[1] == 'e');
|
|
||||||
char* feature = p + 1 + (enable ? 7 : 8);
|
|
||||||
if (strcmp(feature, "asserts") == 0)
|
|
||||||
global.params.useAssert = enable;
|
|
||||||
else if (strcmp(feature, "boundscheck") == 0)
|
|
||||||
global.params.useArrayBounds = enable;
|
|
||||||
else if (strcmp(feature, "contracts") == 0)
|
|
||||||
{
|
|
||||||
global.params.useIn = enable;
|
|
||||||
global.params.useOut = enable;
|
|
||||||
}
|
|
||||||
else if (strcmp(feature, "invariants") == 0)
|
|
||||||
global.params.useInvariants = enable;
|
|
||||||
else
|
|
||||||
error("unrecognized feature '%s'", feature);
|
|
||||||
}
|
|
||||||
else if (strcmp(p + 1, "noasm") == 0)
|
|
||||||
global.params.useInlineAsm = 0;
|
|
||||||
else if (strcmp(p + 1, "nodefaultlib") == 0)
|
|
||||||
global.params.noDefaultLib = 1;
|
|
||||||
else if (p[1] == 'o')
|
|
||||||
{
|
|
||||||
switch (p[2])
|
|
||||||
{
|
|
||||||
case '-':
|
|
||||||
global.params.obj = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
global.params.optimize = (global.params.optimizeLevel >= 0);
|
||||||
if (!p[3])
|
|
||||||
goto Lnoarg;
|
|
||||||
global.params.objdir = p + 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
// Negated options
|
||||||
if (!p[3])
|
global.params.link = !compileOnly;
|
||||||
goto Lnoarg;
|
global.params.obj = !dontWriteObj;
|
||||||
global.params.objname = p + 3;
|
global.params.useInlineAsm = !noAsm;
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
// String options: std::string --> char*
|
||||||
if (p[3])
|
initFromString(global.params.objname, objectFile);
|
||||||
goto Lerror;
|
initFromString(global.params.objdir, objectDir);
|
||||||
global.params.preservePaths = 1;
|
|
||||||
break;
|
initFromString(global.params.docdir, ddocDir);
|
||||||
|
initFromString(global.params.docname, ddocFile);
|
||||||
case 'q':
|
global.params.doDocComments |=
|
||||||
if (p[3])
|
global.params.docdir || global.params.docname;
|
||||||
goto Lerror;
|
|
||||||
global.params.fqnNames = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'u':
|
|
||||||
if (strncmp(p+1, "output-", 7) != 0)
|
|
||||||
goto Lerror;
|
|
||||||
|
|
||||||
// remove default output
|
|
||||||
if (global.params.output_o == OUTPUTFLAGdefault)
|
|
||||||
global.params.output_o = OUTPUTFLAGno;
|
|
||||||
|
|
||||||
if (strcmp(p+8, global.ll_ext) == 0)
|
|
||||||
global.params.output_ll = OUTPUTFLAGset;
|
|
||||||
else if (strcmp(p+8, global.bc_ext) == 0)
|
|
||||||
global.params.output_bc = OUTPUTFLAGset;
|
|
||||||
else if (strcmp(p+8, global.s_ext) == 0)
|
|
||||||
global.params.output_s = OUTPUTFLAGset;
|
|
||||||
else if (strcmp(p+8, global.obj_ext) == 0)
|
|
||||||
global.params.output_o = OUTPUTFLAGset;
|
|
||||||
else
|
|
||||||
goto Lerror;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
error("-o no longer supported, use -of or -od");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
goto Lerror;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (p[1] == 'D')
|
|
||||||
{ global.params.doDocComments = 1;
|
|
||||||
switch (p[2])
|
|
||||||
{
|
|
||||||
case 'd':
|
|
||||||
if (!p[3])
|
|
||||||
goto Lnoarg;
|
|
||||||
global.params.docdir = p + 3;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if (!p[3])
|
|
||||||
goto Lnoarg;
|
|
||||||
global.params.docname = p + 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
goto Lerror;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef _DH
|
#ifdef _DH
|
||||||
else if (p[1] == 'H')
|
initFromString(global.params.hdrdir, hdrDir);
|
||||||
{ global.params.doHdrGeneration = 1;
|
initFromString(global.params.hdrname, hdrFile);
|
||||||
switch (p[2])
|
global.params.doHdrGeneration |=
|
||||||
{
|
global.params.hdrdir || global.params.hdrname;
|
||||||
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
|
#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;
|
processVersions(debugArgs, "debug",
|
||||||
level = strtol(p + 7, &p, 10);
|
DebugCondition::setGlobalLevel,
|
||||||
if (*p || errno || level > INT_MAX)
|
DebugCondition::addGlobalIdent);
|
||||||
goto Lerror;
|
processVersions(versions, "version",
|
||||||
DebugCondition::setGlobalLevel((int)level);
|
VersionCondition::setGlobalLevel,
|
||||||
}
|
VersionCondition::addGlobalIdent);
|
||||||
else if (Lexer::isValidIdentifier(p + 7))
|
|
||||||
DebugCondition::addGlobalIdent(p + 7);
|
|
||||||
else
|
|
||||||
goto Lerror;
|
|
||||||
}
|
|
||||||
else if (p[6])
|
|
||||||
goto Lerror;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
global.params.useInvariants = 1;
|
|
||||||
global.params.useIn = 1;
|
|
||||||
global.params.useOut = 1;
|
|
||||||
global.params.useAssert = 1;
|
|
||||||
global.params.useArrayBounds = 1;
|
|
||||||
global.params.debuglevel = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (memcmp(p + 1, "version", 5) == 0)
|
|
||||||
{
|
|
||||||
// Parse:
|
|
||||||
// -version=number
|
|
||||||
// -version=identifier
|
|
||||||
if (p[8] == '=')
|
|
||||||
{
|
|
||||||
if (isdigit(p[9]))
|
|
||||||
{ long level;
|
|
||||||
|
|
||||||
errno = 0;
|
global.params.output_o =
|
||||||
level = strtol(p + 9, &p, 10);
|
opts::output_o == cl::BOU_UNSET
|
||||||
if (*p || errno || level > INT_MAX)
|
? OUTPUTFLAGdefault
|
||||||
goto Lerror;
|
: opts::output_o == cl::BOU_TRUE
|
||||||
VersionCondition::setGlobalLevel((int)level);
|
? OUTPUTFLAGset
|
||||||
}
|
: OUTPUTFLAGno;
|
||||||
else if (Lexer::isValidIdentifier(p + 9))
|
global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||||
VersionCondition::addGlobalIdent(p + 9);
|
global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||||
else
|
global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||||
goto Lerror;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto Lerror;
|
|
||||||
}
|
|
||||||
else if (strcmp(p + 1, "-b") == 0)
|
|
||||||
global.params.debugb = 1;
|
|
||||||
else if (strcmp(p + 1, "-c") == 0)
|
|
||||||
global.params.debugc = 1;
|
|
||||||
else if (strcmp(p + 1, "-f") == 0)
|
|
||||||
global.params.debugf = 1;
|
|
||||||
else if (strcmp(p + 1, "-help") == 0)
|
|
||||||
{ usage();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
else if (strcmp(p + 1, "-r") == 0)
|
|
||||||
global.params.debugr = 1;
|
|
||||||
else if (strcmp(p + 1, "-x") == 0)
|
|
||||||
global.params.debugx = 1;
|
|
||||||
else if (strcmp(p + 1, "-y") == 0)
|
|
||||||
global.params.debugy = 1;
|
|
||||||
else if (p[1] == 'L')
|
|
||||||
{
|
|
||||||
global.params.linkswitches->push(p + 2);
|
|
||||||
}
|
|
||||||
else if (memcmp(p + 1, "defaultlib=", 11) == 0)
|
|
||||||
{
|
|
||||||
if(!global.params.defaultlibnames)
|
|
||||||
global.params.defaultlibnames = new Array();
|
|
||||||
global.params.defaultlibnames->push(p + 1 + 11);
|
|
||||||
}
|
|
||||||
else if (memcmp(p + 1, "debuglib=", 9) == 0)
|
|
||||||
{
|
|
||||||
if(!global.params.debuglibnames)
|
|
||||||
global.params.debuglibnames = new Array();
|
|
||||||
global.params.debuglibnames->push(p + 1 + 9);
|
|
||||||
}
|
|
||||||
else if (strcmp(p + 1, "run") == 0)
|
|
||||||
{ global.params.run = 1;
|
|
||||||
global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
|
|
||||||
if (global.params.runargs_length)
|
|
||||||
{
|
|
||||||
files.push(argv[i + 1]);
|
|
||||||
global.params.runargs = &argv[i + 2];
|
|
||||||
i += global.params.runargs_length;
|
|
||||||
global.params.runargs_length--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ global.params.run = 0;
|
|
||||||
goto Lnoarg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (p[1] == 'm')
|
|
||||||
{
|
|
||||||
global.params.llvmArch = p+2;
|
|
||||||
}
|
|
||||||
else if (p[1] == 't')
|
|
||||||
{
|
|
||||||
if(strcmp(p + 2, "Linux") == 0)
|
|
||||||
global.params.os = OSLinux;
|
|
||||||
else if(strcmp(p + 2, "Windows") == 0)
|
|
||||||
global.params.os = OSWindows;
|
|
||||||
else if(strcmp(p + 2, "MacOSX") == 0)
|
|
||||||
global.params.os = OSMacOSX;
|
|
||||||
else if(strcmp(p + 2, "FreeBSD") == 0)
|
|
||||||
global.params.os = OSFreeBSD;
|
|
||||||
else if(strcmp(p + 2, "Solaris") == 0)
|
|
||||||
global.params.os = OSSolaris;
|
|
||||||
else
|
|
||||||
error("unrecognized target os '%s'", p + 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Lerror:
|
|
||||||
error("unrecognized switch '%s'", argv[i]);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Lnoarg:
|
if (global.params.run || !runargs.empty()) {
|
||||||
error("argument expected for switch '%s'", argv[i]);
|
// FIXME: how to properly detect the presence of a PositionalEatsArgs
|
||||||
continue;
|
// 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)
|
||||||
else
|
// NOTE: Hacked around it by detecting -run in getenv_setargv(), where
|
||||||
files.push(p);
|
// 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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mArch)
|
||||||
|
global.params.llvmArch = mArch->Name;
|
||||||
|
|
||||||
|
files.reserve(fileList.size());
|
||||||
|
typedef std::vector<std::string>::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)
|
if (global.errors)
|
||||||
{
|
{
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
if (files.dim == 0)
|
if (files.dim == 0)
|
||||||
{ usage();
|
{
|
||||||
|
cl::PrintHelpMessage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,7 +407,7 @@ int main(int argc, char *argv[])
|
||||||
global.params.linkswitches->push(arg);
|
global.params.linkswitches->push(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!global.params.noDefaultLib)
|
else if (!noDefaultLib)
|
||||||
{
|
{
|
||||||
char *arg;
|
char *arg;
|
||||||
arg = (char *)mem.malloc(64);
|
arg = (char *)mem.malloc(64);
|
||||||
|
@ -760,7 +427,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.params.run)
|
if (global.params.run)
|
||||||
global.params.quiet = 1;
|
quiet = 1;
|
||||||
|
|
||||||
if (global.params.useUnitTests)
|
if (global.params.useUnitTests)
|
||||||
global.params.useAssert = 1;
|
global.params.useAssert = 1;
|
||||||
|
@ -893,7 +560,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
assert(global.params.cpu != ARCHinvalid);
|
assert(global.params.cpu != ARCHinvalid);
|
||||||
|
|
||||||
if (allowForceEndianness && global.params.forceBE) {
|
if (allowForceEndianness && forceBE) {
|
||||||
VersionCondition::addPredefinedGlobalIdent("BigEndian");
|
VersionCondition::addPredefinedGlobalIdent("BigEndian");
|
||||||
global.params.isLE = false;
|
global.params.isLE = false;
|
||||||
}
|
}
|
||||||
|
@ -1306,8 +973,24 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
|
||||||
argv = new Array();
|
argv = new Array();
|
||||||
argv->setDim(argc);
|
argv->setDim(argc);
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++)
|
int argc_left = 0;
|
||||||
argv->data[i] = (void *)(*pargv)[i];
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
|
||||||
|
// HACK: set flag to indicate we saw '-run' here
|
||||||
|
global.params.run = true;
|
||||||
|
// Don't eat -run yet so the program arguments don't get changed
|
||||||
|
argc_left = argc - i;
|
||||||
|
argc = i;
|
||||||
|
*pargv = &(*pargv)[i];
|
||||||
|
argv->setDim(i);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
argv->data[i] = (void *)(*pargv)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// HACK to stop required values from command line being drawn from DFLAGS
|
||||||
|
argv->push((char*)"");
|
||||||
|
argc++;
|
||||||
|
|
||||||
j = 1; // leave argv[0] alone
|
j = 1; // leave argv[0] alone
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -1382,6 +1065,11 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ldone:
|
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;
|
*pargc = argc;
|
||||||
*pargv = (char **)argv->data;
|
*pargv = (char **)argv->data;
|
||||||
}
|
}
|
||||||
|
|
84
dmd/mars.h
84
dmd/mars.h
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
#define __STDC_FORMAT_MACROS 1
|
#define __STDC_FORMAT_MACROS 1
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -72,48 +73,40 @@ enum OS
|
||||||
// Put command line switches in here
|
// Put command line switches in here
|
||||||
struct Param
|
struct Param
|
||||||
{
|
{
|
||||||
char obj; // write object file
|
bool obj; // write object file
|
||||||
char link; // perform link
|
bool link; // perform link
|
||||||
char quiet; // suppress non-error messages
|
bool verbose; // verbose compile
|
||||||
char verbose; // verbose compile
|
|
||||||
char symdebug; // insert debug symbolic information
|
char symdebug; // insert debug symbolic information
|
||||||
char optimize; // run optimizer
|
bool optimize; // run optimizer
|
||||||
char optimizeLevel; // optimization level
|
char optimizeLevel; // optimization level
|
||||||
ARCH cpu; // target CPU
|
ARCH cpu; // target CPU
|
||||||
OS os; // target OS
|
OS os; // target OS
|
||||||
char is64bit; // generate 64 bit code
|
bool is64bit; // generate 64 bit code
|
||||||
char isLE; // generate little endian code
|
bool isLE; // generate little endian code
|
||||||
char scheduler; // which scheduler to use
|
bool useDeprecated; // allow use of deprecated features
|
||||||
char useDeprecated; // allow use of deprecated features
|
bool useAssert; // generate runtime code for assert()'s
|
||||||
char useAssert; // generate runtime code for assert()'s
|
bool useInvariants; // generate class invariant checks
|
||||||
char useInvariants; // generate class invariant checks
|
bool useIn; // generate precondition checks
|
||||||
char useIn; // generate precondition checks
|
bool useOut; // generate postcondition checks
|
||||||
char useOut; // generate postcondition checks
|
bool useArrayBounds; // generate array bounds checks
|
||||||
char useArrayBounds; // generate array bounds checks
|
bool useSwitchError; // check for switches without a default
|
||||||
char useSwitchError; // check for switches without a default
|
bool useUnitTests; // generate unittest code
|
||||||
char useUnitTests; // generate unittest code
|
bool useInline; // inline expand functions
|
||||||
char useInline; // inline expand functions
|
bool warnings; // enable warnings
|
||||||
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
|
|
||||||
char Dversion; // D version number
|
char Dversion; // D version number
|
||||||
char ignoreUnsupportedPragmas; // rather than error on them
|
|
||||||
|
|
||||||
char *argv0; // program name
|
char *argv0; // program name
|
||||||
Array *imppath; // array of char*'s of where to look for import modules
|
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
|
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 *objdir; // .obj file output directory
|
||||||
char *objname; // .obj file output name
|
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 *docdir; // write documentation file to docdir directory
|
||||||
char *docname; // write documentation file to docname
|
char *docname; // write documentation file to docname
|
||||||
Array *ddocfiles; // macro include files for Ddoc
|
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 *hdrdir; // write 'header' file to docdir directory
|
||||||
char *hdrname; // write 'header' file to docname
|
char *hdrname; // write 'header' file to docname
|
||||||
|
|
||||||
|
@ -131,18 +124,16 @@ struct Param
|
||||||
char *xmlname; // filename for XML output
|
char *xmlname; // filename for XML output
|
||||||
|
|
||||||
// Hidden debug switches
|
// Hidden debug switches
|
||||||
char debuga;
|
bool debuga;
|
||||||
char debugb;
|
bool debugb;
|
||||||
char debugc;
|
bool debugc;
|
||||||
char debugf;
|
bool debugf;
|
||||||
char debugr;
|
bool debugr;
|
||||||
char debugw;
|
bool debugw;
|
||||||
char debugx;
|
bool debugx;
|
||||||
char debugy;
|
bool debugy;
|
||||||
|
|
||||||
char run; // run resulting executable
|
bool run; // run resulting executable
|
||||||
size_t runargs_length;
|
|
||||||
char** runargs; // arguments for executable
|
|
||||||
|
|
||||||
// Linker stuff
|
// Linker stuff
|
||||||
Array *objfiles;
|
Array *objfiles;
|
||||||
|
@ -153,17 +144,14 @@ struct Param
|
||||||
char *exefile;
|
char *exefile;
|
||||||
|
|
||||||
// LDC stuff
|
// LDC stuff
|
||||||
char *llvmArch;
|
const char *llvmArch;
|
||||||
char forceBE;
|
OUTPUTFLAG output_ll;
|
||||||
char output_ll;
|
OUTPUTFLAG output_bc;
|
||||||
char output_bc;
|
OUTPUTFLAG output_s;
|
||||||
char output_s;
|
OUTPUTFLAG output_o;
|
||||||
char output_o;
|
bool llvmInline;
|
||||||
char llvmInline;
|
bool llvmAnnotate;
|
||||||
char llvmAnnotate;
|
bool useInlineAsm;
|
||||||
char useInlineAsm;
|
|
||||||
char fqnNames; // use fully qualified object names
|
|
||||||
char noDefaultLib;
|
|
||||||
|
|
||||||
// target stuff
|
// target stuff
|
||||||
char *targetTriple;
|
char *targetTriple;
|
||||||
|
|
17
dmd/module.c
17
dmd/module.c
|
@ -44,6 +44,19 @@
|
||||||
#include "d-dmd-gcc.h"
|
#include "d-dmd-gcc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> preservePaths("op",
|
||||||
|
llvm::cl::desc("Do not strip paths from source file"),
|
||||||
|
llvm::cl::ZeroOrMore);
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> fqnNames("oq",
|
||||||
|
llvm::cl::desc("Write object files with fully qualified names"),
|
||||||
|
llvm::cl::ZeroOrMore);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClassDeclaration *Module::moduleinfo;
|
ClassDeclaration *Module::moduleinfo;
|
||||||
|
|
||||||
Module *Module::rootModule;
|
Module *Module::rootModule;
|
||||||
|
@ -139,12 +152,12 @@ File* Module::buildFilePath(char* forcename, char* path, char* ext)
|
||||||
argobj = forcename;
|
argobj = forcename;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (global.params.preservePaths)
|
if (preservePaths)
|
||||||
argobj = (char*)this->arg;
|
argobj = (char*)this->arg;
|
||||||
else
|
else
|
||||||
argobj = FileName::name((char*)this->arg);
|
argobj = FileName::name((char*)this->arg);
|
||||||
|
|
||||||
if (global.params.fqnNames)
|
if (fqnNames)
|
||||||
{
|
{
|
||||||
if(md)
|
if(md)
|
||||||
argobj = FileName::replaceName(argobj, md->toChars());
|
argobj = FileName::replaceName(argobj, md->toChars());
|
||||||
|
|
81
gen/cl_helpers.cpp
Normal file
81
gen/cl_helpers.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#include "gen/cl_helpers.h"
|
||||||
|
|
||||||
|
#include "dmd/root.h"
|
||||||
|
#include "dmd/mem.h"
|
||||||
|
|
||||||
|
#include <cctype> // isupper, tolower
|
||||||
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
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<std::pair<std::string, bool> >::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<bool>::parse(O, ArgName, Arg, Val)) {
|
||||||
|
Val = (Val == I->second);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Invalid option value
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlagParser::getExtraOptionNames(std::vector<const char*> &Names) {
|
||||||
|
typedef std::vector<std::pair<std::string, bool> >::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<bool*>::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
|
68
gen/cl_helpers.h
Normal file
68
gen/cl_helpers.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef LDC_CL_HELPERS_H
|
||||||
|
#define LDC_CL_HELPERS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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<bool> {
|
||||||
|
std::vector<std::pair<std::string, bool> > switches;
|
||||||
|
public:
|
||||||
|
template <class Opt>
|
||||||
|
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 <foo> with -enable-<foo>
|
||||||
|
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<const char*> &Names);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Helper class for options that set multiple flags
|
||||||
|
class MultiSetter {
|
||||||
|
std::vector<bool*> 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
|
337
gen/cl_options.cpp
Normal file
337
gen/cl_options.cpp
Normal file
|
@ -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<std::string> fileList(
|
||||||
|
cl::Positional, cl::desc("files"));
|
||||||
|
|
||||||
|
cl::list<std::string> runargs("run",
|
||||||
|
cl::desc("program args..."),
|
||||||
|
cl::Positional,
|
||||||
|
cl::PositionalEatsArgs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Replace this with a proper PassNameParser-based solution
|
||||||
|
static cl::opt<bool, true> doInline("inline",
|
||||||
|
cl::desc("Do function inlining"),
|
||||||
|
cl::location(global.params.llvmInline),
|
||||||
|
cl::ZeroOrMore,
|
||||||
|
cl::init(false));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static cl::opt<bool, true> useDeprecated("d",
|
||||||
|
cl::desc("Allow deprecated language features"),
|
||||||
|
cl::ZeroOrMore,
|
||||||
|
cl::location(global.params.useDeprecated));
|
||||||
|
|
||||||
|
static cl::opt<char, true> 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<bool> compileOnly("c",
|
||||||
|
cl::desc("Do not link"),
|
||||||
|
cl::ZeroOrMore);
|
||||||
|
|
||||||
|
static cl::opt<bool, true> verbose("v",
|
||||||
|
cl::desc("Verbose"),
|
||||||
|
cl::ZeroOrMore,
|
||||||
|
cl::location(global.params.verbose));
|
||||||
|
|
||||||
|
static cl::opt<bool, true> warnings("w",
|
||||||
|
cl::desc("Enable warnings"),
|
||||||
|
cl::ZeroOrMore,
|
||||||
|
cl::location(global.params.warnings));
|
||||||
|
|
||||||
|
|
||||||
|
static cl::opt<char, true> 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<char, true> 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<bool, true> annotate("annotate",
|
||||||
|
cl::desc("Annotate the bitcode with human readable source code"),
|
||||||
|
cl::location(global.params.llvmAnnotate));
|
||||||
|
|
||||||
|
cl::opt<bool> noAsm("noasm",
|
||||||
|
cl::desc("Disallow use of inline assembler"));
|
||||||
|
|
||||||
|
// Output file options
|
||||||
|
cl::opt<bool> dontWriteObj("o-",
|
||||||
|
cl::desc("Do not write object file"));
|
||||||
|
|
||||||
|
cl::opt<std::string> objectFile("of",
|
||||||
|
cl::value_desc("filename"),
|
||||||
|
cl::Prefix,
|
||||||
|
cl::desc("Use <filename> as output file name"));
|
||||||
|
|
||||||
|
cl::opt<std::string> objectDir("od",
|
||||||
|
cl::value_desc("objdir"),
|
||||||
|
cl::Prefix,
|
||||||
|
cl::desc("Write object files to directory <objdir>"));
|
||||||
|
|
||||||
|
|
||||||
|
// Output format options
|
||||||
|
cl::opt<bool> output_bc("output-bc",
|
||||||
|
cl::desc("Write LLVM bitcode"));
|
||||||
|
|
||||||
|
cl::opt<bool> output_ll("output-ll",
|
||||||
|
cl::desc("Write LLVM IR"));
|
||||||
|
|
||||||
|
cl::opt<bool> output_s("output-s",
|
||||||
|
cl::desc("Write native assembly"));
|
||||||
|
|
||||||
|
cl::opt<cl::boolOrDefault> output_o("output-o",
|
||||||
|
cl::desc("Write native object"));
|
||||||
|
|
||||||
|
|
||||||
|
// DDoc options
|
||||||
|
static cl::opt<bool, true> doDdoc("D",
|
||||||
|
cl::desc("Generate documentation"),
|
||||||
|
cl::location(global.params.doDocComments));
|
||||||
|
|
||||||
|
cl::opt<std::string> ddocDir("Dd",
|
||||||
|
cl::desc("Write documentation file to <docdir> directory"),
|
||||||
|
cl::value_desc("docdir"),
|
||||||
|
cl::Prefix);
|
||||||
|
|
||||||
|
cl::opt<std::string> ddocFile("Df",
|
||||||
|
cl::desc("Write documentation file to <filename>"),
|
||||||
|
cl::value_desc("filename"),
|
||||||
|
cl::Prefix);
|
||||||
|
|
||||||
|
|
||||||
|
// Header generation options
|
||||||
|
#ifdef _DH
|
||||||
|
static cl::opt<bool, true> doHdrGen("H",
|
||||||
|
cl::desc("Generate 'header' file"),
|
||||||
|
cl::location(global.params.doHdrGeneration));
|
||||||
|
|
||||||
|
cl::opt<std::string> hdrDir("Hd",
|
||||||
|
cl::desc("Write 'header' file to <hdrdir> directory"),
|
||||||
|
cl::value_desc("hdrdir"),
|
||||||
|
cl::Prefix);
|
||||||
|
|
||||||
|
cl::opt<std::string> hdrFile("Hf",
|
||||||
|
cl::desc("Write 'header' file to <filename>"),
|
||||||
|
cl::value_desc("filename"),
|
||||||
|
cl::Prefix);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static cl::opt<bool, true> unittest("unittest",
|
||||||
|
cl::desc("Compile in unit tests"),
|
||||||
|
cl::location(global.params.useUnitTests));
|
||||||
|
|
||||||
|
|
||||||
|
static ArrayAdapter strImpPathStore("J", global.params.fileImppath);
|
||||||
|
static cl::list<std::string, ArrayAdapter> 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<std::string> 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<std::string, D_DebugStorage> debugVersionsOption("d-debug",
|
||||||
|
cl::desc("Compile in debug code >= <level> or identified by <idents>."),
|
||||||
|
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<std::string> versions("d-version",
|
||||||
|
cl::desc("Compile in version code >= <level> or identified by <idents>"),
|
||||||
|
cl::value_desc("level/idents"),
|
||||||
|
cl::CommaSeparated);
|
||||||
|
|
||||||
|
|
||||||
|
static ArrayAdapter linkSwitchStore("L", global.params.linkswitches);
|
||||||
|
static cl::list<std::string, ArrayAdapter> linkerSwitches("L",
|
||||||
|
cl::desc("Pass <linkerflag> to the linker"),
|
||||||
|
cl::value_desc("linkerflag"),
|
||||||
|
cl::location(linkSwitchStore),
|
||||||
|
cl::Prefix);
|
||||||
|
|
||||||
|
|
||||||
|
cl::opt<const llvm::TargetMachineRegistry::entry*, false,
|
||||||
|
llvm::RegistryParser<llvm::TargetMachine> > 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, true> 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<bool, true> debuga("hidden-debug--a",
|
||||||
|
cl::desc("Hidden debug option A"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debuga));
|
||||||
|
static cl::opt<bool, true> debugb("hidden-debug-b",
|
||||||
|
cl::desc("Hidden debug option B"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debugb));
|
||||||
|
static cl::opt<bool, true> debugc("hidden-debug-c",
|
||||||
|
cl::desc("Hidden debug option C"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debugc));
|
||||||
|
static cl::opt<bool, true> debugf("hidden-debug-f",
|
||||||
|
cl::desc("Hidden debug option F"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debugf));
|
||||||
|
static cl::opt<bool, true> debugr("hidden-debug-r",
|
||||||
|
cl::desc("Hidden debug option R"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debugr));
|
||||||
|
static cl::opt<bool, true> debugw("hidden-debug-w",
|
||||||
|
cl::desc("Hidden debug option W"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debugw));
|
||||||
|
static cl::opt<bool, true> debugx("hidden-debug-x",
|
||||||
|
cl::desc("Hidden debug option X"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debugx));
|
||||||
|
static cl::opt<bool, true> debugy("hidden-debug-y",
|
||||||
|
cl::desc("Hidden debug option Y"),
|
||||||
|
cl::ReallyHidden,
|
||||||
|
cl::location(global.params.debugy));
|
||||||
|
|
||||||
|
|
||||||
|
static cl::opt<bool, true, FlagParser> asserts("asserts",
|
||||||
|
cl::desc("(*) Enable assertions"),
|
||||||
|
cl::value_desc("bool"),
|
||||||
|
cl::location(global.params.useAssert),
|
||||||
|
cl::init(true));
|
||||||
|
|
||||||
|
static cl::opt<bool, true, FlagParser> boundsChecks("boundscheck",
|
||||||
|
cl::desc("(*) Enable array bounds checks"),
|
||||||
|
cl::value_desc("bool"),
|
||||||
|
cl::location(global.params.useArrayBounds),
|
||||||
|
cl::init(true));
|
||||||
|
|
||||||
|
static cl::opt<bool, true, FlagParser> invariants("invariants",
|
||||||
|
cl::desc("(*) Enable invariants"),
|
||||||
|
cl::location(global.params.useInvariants),
|
||||||
|
cl::init(true));
|
||||||
|
|
||||||
|
static cl::opt<bool, true, FlagParser> preconditions("preconditions",
|
||||||
|
cl::desc("(*) Enable function preconditions"),
|
||||||
|
cl::location(global.params.useIn),
|
||||||
|
cl::init(true));
|
||||||
|
|
||||||
|
static cl::opt<bool, true, FlagParser> 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<MultiSetter, true, FlagParser> 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<MultiSetter, true, cl::parser<bool> > 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
|
46
gen/cl_options.h
Normal file
46
gen/cl_options.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef LDC_CL_OPTIONS_H
|
||||||
|
#define LDC_CL_OPTIONS_H
|
||||||
|
|
||||||
|
#include "mars.h"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#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<std::string> fileList;
|
||||||
|
extern cl::list<std::string> runargs;
|
||||||
|
extern cl::opt<bool> compileOnly;
|
||||||
|
extern cl::opt<bool> noAsm;
|
||||||
|
extern cl::opt<bool> dontWriteObj;
|
||||||
|
extern cl::opt<std::string> objectFile;
|
||||||
|
extern cl::opt<std::string> objectDir;
|
||||||
|
extern cl::opt<bool> output_bc;
|
||||||
|
extern cl::opt<bool> output_ll;
|
||||||
|
extern cl::opt<bool> output_s;
|
||||||
|
extern cl::opt<cl::boolOrDefault> output_o;
|
||||||
|
extern cl::opt<std::string> ddocDir;
|
||||||
|
extern cl::opt<std::string> ddocFile;
|
||||||
|
#ifdef _DH
|
||||||
|
extern cl::opt<std::string> hdrDir;
|
||||||
|
extern cl::opt<std::string> hdrFile;
|
||||||
|
#endif
|
||||||
|
extern cl::list<std::string> versions;
|
||||||
|
|
||||||
|
extern cl::opt<const llvm::TargetMachineRegistry::entry*, false,
|
||||||
|
llvm::RegistryParser<llvm::TargetMachine> > mArch;
|
||||||
|
|
||||||
|
// Arguments to -d-debug
|
||||||
|
extern std::vector<std::string> debugArgs;
|
||||||
|
// Arguments to -run
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "gen/linker.h"
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
#include "llvm/Linker.h"
|
#include "llvm/Linker.h"
|
||||||
#include "llvm/System/Program.h"
|
#include "llvm/System/Program.h"
|
||||||
|
@ -11,6 +12,16 @@
|
||||||
|
|
||||||
#define NO_COUT_LOGGER
|
#define NO_COUT_LOGGER
|
||||||
#include "gen/logger.h"
|
#include "gen/logger.h"
|
||||||
|
#include "gen/cl_options.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Is this useful?
|
||||||
|
llvm::cl::opt<bool> 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 @@ int linkExecutable(const char* argv0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// print link command?
|
// print link command?
|
||||||
if (!global.params.quiet || global.params.verbose)
|
if (!quiet || global.params.verbose)
|
||||||
{
|
{
|
||||||
// Print it
|
// Print it
|
||||||
for (int i = 0; i < args.size(); i++)
|
for (int i = 0; i < args.size(); i++)
|
||||||
|
@ -311,7 +322,7 @@ int linkObjToExecutable(const char* argv0)
|
||||||
args.push_back("-m64");
|
args.push_back("-m64");
|
||||||
|
|
||||||
// print link command?
|
// print link command?
|
||||||
if (!global.params.quiet || global.params.verbose)
|
if (!quiet || global.params.verbose)
|
||||||
{
|
{
|
||||||
// Print it
|
// Print it
|
||||||
for (int i = 0; i < args.size(); i++)
|
for (int i = 0; i < args.size(); i++)
|
||||||
|
@ -363,10 +374,12 @@ int runExectuable()
|
||||||
|
|
||||||
// build arguments
|
// build arguments
|
||||||
std::vector<const char*> args;
|
std::vector<const char*> 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(opts::runargs[i].c_str());
|
||||||
args.push_back(a);
|
|
||||||
}
|
}
|
||||||
// terminate args list
|
// terminate args list
|
||||||
args.push_back(NULL);
|
args.push_back(NULL);
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#ifndef LDC_GEN_LINKER_H
|
#ifndef LDC_GEN_LINKER_H
|
||||||
#define LDC_GEN_LINKER_H
|
#define LDC_GEN_LINKER_H
|
||||||
|
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
extern llvm::cl::opt<bool> quiet;
|
||||||
|
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
class Module;
|
class Module;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
|
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "gen/logger.h"
|
#include "gen/logger.h"
|
||||||
|
|
||||||
namespace Logger
|
namespace Logger
|
||||||
|
@ -15,7 +16,10 @@ namespace Logger
|
||||||
static std::string indent_str;
|
static std::string indent_str;
|
||||||
static std::ofstream null_out("/dev/null");
|
static std::ofstream null_out("/dev/null");
|
||||||
|
|
||||||
static bool _enabled = false;
|
llvm::cl::opt<bool> _enabled("vv",
|
||||||
|
llvm::cl::desc("Very verbose"),
|
||||||
|
llvm::cl::ZeroOrMore);
|
||||||
|
|
||||||
void indent()
|
void indent()
|
||||||
{
|
{
|
||||||
if (_enabled) {
|
if (_enabled) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Bitcode/ReaderWriter.h"
|
#include "llvm/Bitcode/ReaderWriter.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
|
@ -15,6 +16,14 @@
|
||||||
#include "gen/tollvm.h"
|
#include "gen/tollvm.h"
|
||||||
#include "gen/irstate.h"
|
#include "gen/irstate.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> noruntime("noruntime",
|
||||||
|
llvm::cl::desc("Do not allow code that generates implicit runtime calls"),
|
||||||
|
llvm::cl::ZeroOrMore);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static llvm::Module* M = NULL;
|
static llvm::Module* M = NULL;
|
||||||
static bool runtime_failed = false;
|
static bool runtime_failed = false;
|
||||||
|
|
||||||
|
@ -44,7 +53,7 @@ void LLVM_D_FreeRuntime()
|
||||||
|
|
||||||
llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name)
|
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");
|
error("No implicit runtime calls allowed with -noruntime option enabled");
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
|
@ -80,7 +89,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char*
|
||||||
return gv;
|
return gv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.params.noruntime) {
|
if (noruntime) {
|
||||||
error("No implicit runtime calls allowed with -noruntime option enabled");
|
error("No implicit runtime calls allowed with -noruntime option enabled");
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "llvm/System/Program.h"
|
#include "llvm/System/Program.h"
|
||||||
#include "llvm/System/Path.h"
|
#include "llvm/System/Path.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
@ -55,6 +56,12 @@
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> noVerify("noverify",
|
||||||
|
llvm::cl::desc("Do not run the validation pass before writing bitcode"),
|
||||||
|
llvm::cl::ZeroOrMore);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// in gen/optimize.cpp
|
// in gen/optimize.cpp
|
||||||
void ldc_optimize_module(llvm::Module* m, char lvl, bool doinline);
|
void ldc_optimize_module(llvm::Module* m, char lvl, bool doinline);
|
||||||
|
|
||||||
|
@ -124,10 +131,6 @@ void Module::genobjfile(int multiobj)
|
||||||
// for (unsigned i = 0; i != MAttrs.size(); ++i)
|
// for (unsigned i = 0; i != MAttrs.size(); ++i)
|
||||||
// Features.AddFeature(MAttrs[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
|
// allocate the target machine
|
||||||
std::auto_ptr<llvm::TargetMachine> target(MArch->CtorFn(*ir.module, Features.getString()));
|
std::auto_ptr<llvm::TargetMachine> target(MArch->CtorFn(*ir.module, Features.getString()));
|
||||||
assert(target.get() && "Could not allocate target machine!");
|
assert(target.get() && "Could not allocate target machine!");
|
||||||
|
@ -182,7 +185,7 @@ void Module::genobjfile(int multiobj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify the llvm
|
// verify the llvm
|
||||||
if (!global.params.novalidate) {
|
if (!noVerify) {
|
||||||
std::string verifyErr;
|
std::string verifyErr;
|
||||||
Logger::println("Verifying module...");
|
Logger::println("Verifying module...");
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
@ -200,7 +203,7 @@ void Module::genobjfile(int multiobj)
|
||||||
ldc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
|
ldc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
|
||||||
|
|
||||||
// verify the llvm
|
// 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;
|
std::string verifyErr;
|
||||||
Logger::println("Verifying module... again...");
|
Logger::println("Verifying module... again...");
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
|
@ -38,7 +38,7 @@ testversion=PIC
|
||||||
|
|
||||||
[compile]
|
[compile]
|
||||||
oneatatime=yes
|
oneatatime=yes
|
||||||
cmd=ldc -c $i
|
cmd=ldmd -c $i
|
||||||
|
|
||||||
flag=$i
|
flag=$i
|
||||||
incdir=-I$i
|
incdir=-I$i
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
[Environment]
|
[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@
|
||||||
|
|
56
tango.patch
Normal file
56
tango.patch
Normal file
|
@ -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
|
||||||
|
|
||||||
|
- <none>: Builds unittests for all known compilers.'
|
||||||
|
+ <none>: 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"
|
Loading…
Add table
Add a link
Reference in a new issue