comparison dmd/mars.c @ 986:a8cb25d478c4

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)
author Frits van Bommel <fvbommel wxs.nl>
date Wed, 25 Feb 2009 17:34:51 +0100
parents 0b38b64f62c7
children 2667e3a145be
comparison
equal deleted inserted replaced
985:bce024c60adc 986:a8cb25d478c4
38 38
39 #include "gen/logger.h" 39 #include "gen/logger.h"
40 #include "gen/linker.h" 40 #include "gen/linker.h"
41 #include "revisions.h" 41 #include "revisions.h"
42 42
43 #include "gen/cl_options.h"
44 #include "gen/cl_helpers.h"
45 using namespace opts;
46
47
48 static cl::opt<bool> forceBE("forcebe",
49 cl::desc("Force big-endian"),
50 cl::Hidden,
51 cl::ZeroOrMore);
52
53 static cl::opt<bool> noDefaultLib("nodefaultlib",
54 cl::desc("Don't add a default library for linking implicitly"),
55 cl::ZeroOrMore);
56
57 static ArrayAdapter impPathsStore("I", global.params.imppath);
58 static cl::list<std::string, ArrayAdapter> importPaths("I",
59 cl::desc("Where to look for imports"),
60 cl::value_desc("path"),
61 cl::location(impPathsStore),
62 cl::Prefix);
63
64 static ArrayAdapter defaultLibStore("defaultlib", global.params.defaultlibnames);
65 static cl::list<std::string, ArrayAdapter> defaultlibs("defaultlib",
66 cl::desc("Set default libraries for non-debug build"),
67 cl::value_desc("lib,..."),
68 cl::location(defaultLibStore),
69 cl::CommaSeparated);
70
71 static ArrayAdapter debugLibStore("debuglib", global.params.debuglibnames);
72 static cl::list<std::string, ArrayAdapter> debuglibs("debuglib",
73 cl::desc("Set default libraries for debug build"),
74 cl::value_desc("lib,..."),
75 cl::location(debugLibStore),
76 cl::CommaSeparated);
77
78
43 void getenv_setargv(const char *envvar, int *pargc, char** *pargv); 79 void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
44 80
45 Global global; 81 Global global;
46 82
47 Global::Global() 83 Global::Global()
66 version = "v1.039"; 102 version = "v1.039";
67 ldc_version = LDC_REV; 103 ldc_version = LDC_REV;
68 llvm_version = LLVM_REV; 104 llvm_version = LLVM_REV;
69 global.structalign = 8; 105 global.structalign = 8;
70 106
71 memset(&params, 0, sizeof(Param)); 107 // This should only be used as a global, so the other fields are
108 // automatically initialized to zero when the program is loaded.
109 // In particular, DO NOT zero-initialize .params here (like DMD
110 // does) because command-line options initialize some of those
111 // fields to non-zero defaults, and do so from constructors that
112 // may run before this one.
72 } 113 }
73 114
74 char *Loc::toChars() const 115 char *Loc::toChars() const
75 { 116 {
76 OutBuffer buf; 117 OutBuffer buf;
77 char *p;
78 118
79 if (filename) 119 if (filename)
80 { 120 {
81 buf.printf("%s", filename); 121 buf.printf("%s", filename);
82 } 122 }
148 } 188 }
149 189
150 extern void backend_init(); 190 extern void backend_init();
151 extern void backend_term(); 191 extern void backend_term();
152 192
153 void usage() 193 void printVersion() {
154 {
155 printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n", 194 printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n",
156 global.ldc_version, global.version, global.llvm_version, global.copyright, global.written); 195 global.ldc_version, global.version, global.llvm_version, global.copyright, global.written);
157 printf("\ 196 printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n"
158 D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ 197 "LDC Homepage: http://www.dsource.org/projects/ldc\n");
159 LDC Homepage: http://www.dsource.org/projects/ldc\n\ 198 }
160 Usage:\n\ 199
161 ldc files.d ... { -switch }\n\ 200 // Helper function to handle -d-debug=* and -d-version=*
162 \n\ 201 static void processVersions(std::vector<std::string>& list, char* type,
163 files.d D source files\n%s\ 202 void (*setLevel)(unsigned), void (*addIdent)(char*)) {
164 -o- do not write object file\n\ 203 typedef std::vector<std::string>::iterator It;
165 -od<objdir> write object files to directory <objdir>\n\ 204
166 -op do not strip paths from source file\n\ 205 for(It I = list.begin(), E = list.end(); I != E; ++I) {
167 -oq write object files with fully qualified names\n\ 206 const char* value = I->c_str();
168 -of<filename> name output file to <filename>\n\ 207 if (isdigit(value[0])) {
169 if -c and extension of <filename> is known, it determines the output type\n\ 208 errno = 0;
170 \n\ 209 char* end;
171 -output-ll write LLVM IR\n\ 210 long level = strtol(value, &end, 10);
172 -output-bc write LLVM bitcode\n\ 211 if (*end || errno || level > INT_MAX) {
173 -output-s write native assembly\n\ 212 error("Invalid %s level: %s", type, I->c_str());
174 -output-o write native object (default if no -output switch passed)\n\ 213 } else {
175 \n\ 214 setLevel((unsigned)level);
176 -c do not link\n\ 215 }
177 -L<linkerflag> pass <linkerflag> to linker\n\ 216 } else {
178 \n\ 217 char* cstr = mem.strdup(value);
179 -w enable warnings\n\ 218 if (Lexer::isValidIdentifier(cstr)) {
180 \n\ 219 addIdent(cstr);
181 -H generate 'header' file\n\ 220 continue;
182 -Hd<hdrdir> write 'header' file to <hdrdir> directory\n\ 221 } else {
183 -Hf<filename> write 'header' file to <filename>\n\ 222 error("Invalid %s identifier or level: '%s'", type, I->c_str());
184 \n\ 223 }
185 -D generate documentation\n\ 224 }
186 -Dd<docdir> write documentation file to <docdir> directory\n\ 225 }
187 -Df<filename> write documentation file to <filename>\n\ 226 }
188 \n\ 227
189 Codegen control:\n\ 228 // Helper function to handle -of, -od, etc.
190 -m<arch> emit code specific to <arch> being one of:\n\ 229 static void initFromString(char*& dest, const cl::opt<std::string>& src) {
191 x86 x86-64 ppc32 ppc64 arm thumb\n\ 230 dest = 0;
192 -t<os> emit code specific to <os> being one of:\n\ 231 if (src.getNumOccurrences() != 0) {
193 Linux, Windows, MacOSX, FreeBSD, Solaris\n\ 232 if (src.empty())
194 \n\ 233 error("Expected argument to '-%s'", src.ArgStr);
195 -g, -gc add symbolic debug info\n\ 234 dest = mem.strdup(src.c_str());
196 \n\ 235 }
197 -O optimize, same as -O2\n\
198 -O<n> optimize at level <n> (0-5)\n\
199 -inline do function inlining\n\
200 \n\
201 -debug enables asserts, invariants, contracts, boundscheck\n\
202 and sets debug=1\n\
203 -release disables asserts, invariants, contracts, boundscheck\n\
204 \n\
205 -enable-<feature> and\n\
206 -disable-<feature> where <feature> is one of\n\
207 asserts assert statements (default: on)\n\
208 invariants class and struct invariants (default: on)\n\
209 contracts function contracts (default: on)\n\
210 boundscheck array bounds checking (default: on)\n\
211 -debug=level compile in debug stmts <= level (default: 0)\n\
212 -debug=ident compile in debug stmts identified by ident\n\
213 -version=level compile in version code >= level\n\
214 -version=ident compile in version code identified by ident\n\
215 \n\
216 -noasm do not allow use of inline asm\n\
217 -noruntime do not allow code that generates implicit runtime calls\n\
218 -noverify do not run the validation pass before writing bitcode\n\
219 -unittest compile in unit tests\n\
220 -d allow deprecated features\n\
221 \n\
222 -annotate annotate the bitcode with human readable source code\n\
223 -ignore ignore unsupported pragmas\n\
224 \n\
225 Path options:\n\
226 -I<path> where to look for imports\n\
227 -J<path> where to look for string imports\n\
228 -defaultlib=name set default library for non-debug build\n\
229 -debuglib=name set default library for debug build\n\
230 -nodefaultlib don't add a default library for linking implicitly\n\
231 \n\
232 Misc options:\n\
233 -v verbose\n\
234 -vv very verbose (does not include -v)\n\
235 -quiet suppress unnecessary messages\n\
236 -run srcfile args... run resulting program, passing args\n\
237 --help print help\n\
238 ",
239 #if WIN32
240 " @cmdfile read arguments from cmdfile\n"
241 #else
242 ""
243 #endif
244 );
245 } 236 }
246 237
247 int main(int argc, char *argv[]) 238 int main(int argc, char *argv[])
248 { 239 {
249 int i; 240 int i;
250 Array files; 241 Array files;
251 char *p, *ext; 242 char *p, *ext;
252 Module *m; 243 Module *m;
253 int status = EXIT_SUCCESS; 244 int status = EXIT_SUCCESS;
254 int argcstart = argc;
255 bool very_verbose = false;
256
257 // Check for malformed input
258 if (argc < 1 || !argv)
259 {
260 Largs:
261 error("missing or null command line arguments");
262 fatal();
263 }
264 for (i = 0; i < argc; i++)
265 {
266 if (!argv[i])
267 goto Largs;
268 }
269
270 #if __DMC__ // DMC unique support for response files
271 if (response_expand(&argc,&argv)) // expand response files
272 error("can't open response file");
273 #endif
274
275 files.reserve(argc - 1);
276 245
277 // Set default values 246 // Set default values
278 #if _WIN32 247 #if _WIN32
279 char buf[MAX_PATH]; 248 char buf[MAX_PATH];
280 GetModuleFileName(NULL, buf, MAX_PATH); 249 GetModuleFileName(NULL, buf, MAX_PATH);
281 global.params.argv0 = buf; 250 global.params.argv0 = buf;
282 #else 251 #else
283 global.params.argv0 = argv[0]; 252 global.params.argv0 = argv[0];
284 #endif 253 #endif
285 global.params.link = 1;
286 global.params.useAssert = 1;
287 global.params.useInvariants = 1;
288 global.params.useIn = 1;
289 global.params.useOut = 1;
290 global.params.useArrayBounds = 1;
291 global.params.useSwitchError = 1; 254 global.params.useSwitchError = 1;
292 global.params.useInline = 0; // this one messes things up to a point where codegen breaks
293 global.params.llvmInline = 0; // use this one instead to know if inline passes should be run
294 global.params.obj = 1;
295 global.params.Dversion = 2;
296 global.params.quiet = 1;
297
298 global.params.output_o = OUTPUTFLAGdefault;
299 255
300 global.params.linkswitches = new Array(); 256 global.params.linkswitches = new Array();
301 global.params.libfiles = new Array(); 257 global.params.libfiles = new Array();
302 global.params.objfiles = new Array(); 258 global.params.objfiles = new Array();
303 global.params.ddocfiles = new Array(); 259 global.params.ddocfiles = new Array();
312 global.params.isLE = false; 268 global.params.isLE = false;
313 else { 269 else {
314 error("Endian test is broken"); 270 error("Endian test is broken");
315 fatal(); 271 fatal();
316 } 272 }
317
318 global.params.llvmArch = 0;
319 global.params.forceBE = 0;
320 global.params.noruntime = 0;
321 global.params.novalidate = 0;
322 global.params.optimizeLevel = -1;
323 global.params.runtimeImppath = 0;
324 global.params.useInlineAsm = 1;
325 273
326 // Predefine version identifiers 274 // Predefine version identifiers
327 #if IN_LLVM 275 #if IN_LLVM
328 VersionCondition::addPredefinedGlobalIdent("LLVM"); 276 VersionCondition::addPredefinedGlobalIdent("LLVM");
329 VersionCondition::addPredefinedGlobalIdent("LDC"); 277 VersionCondition::addPredefinedGlobalIdent("LDC");
363 { 311 {
364 printf("argv[%d] = '%s'\n", i, argv[i]); 312 printf("argv[%d] = '%s'\n", i, argv[i]);
365 } 313 }
366 #endif 314 #endif
367 315
368 for (i = 1; i < argc; i++) 316 cl::SetVersionPrinter(&printVersion);
369 { 317 cl::ParseCommandLineOptions(argc, argv, "LLVM-based D Compiler\n");
370 p = argv[i]; 318
371 if (*p == '-') 319 global.params.optimize = (global.params.optimizeLevel >= 0);
372 { 320
373 if (strcmp(p + 1, "d") == 0) 321 // Negated options
374 global.params.useDeprecated = 1; 322 global.params.link = !compileOnly;
375 else if (strcmp(p + 1, "c") == 0) 323 global.params.obj = !dontWriteObj;
376 global.params.link = 0; 324 global.params.useInlineAsm = !noAsm;
377 else if (strcmp(p + 1, "fPIC") == 0) 325
378 global.params.pic = 1; 326 // String options: std::string --> char*
379 else if (strcmp(p + 1, "g") == 0) 327 initFromString(global.params.objname, objectFile);
380 global.params.symdebug = 1; 328 initFromString(global.params.objdir, objectDir);
381 else if (strcmp(p + 1, "gc") == 0) 329
382 global.params.symdebug = 2; 330 initFromString(global.params.docdir, ddocDir);
383 else if (strcmp(p + 1, "v") == 0) 331 initFromString(global.params.docname, ddocFile);
384 global.params.verbose = 1; 332 global.params.doDocComments |=
385 else if (strcmp(p + 1, "vv") == 0) { 333 global.params.docdir || global.params.docname;
386 Logger::enable(); 334
387 very_verbose = true; 335 #ifdef _DH
388 } 336 initFromString(global.params.hdrdir, hdrDir);
389 else if (strcmp(p + 1, "v1") == 0) 337 initFromString(global.params.hdrname, hdrFile);
390 global.params.Dversion = 1; 338 global.params.doHdrGeneration |=
391 else if (strcmp(p + 1, "w") == 0) 339 global.params.hdrdir || global.params.hdrname;
392 global.params.warnings = 1; 340 #endif
393 else if (p[1] == 'O') 341
394 { 342 processVersions(debugArgs, "debug",
395 global.params.optimize = 1; 343 DebugCondition::setGlobalLevel,
396 global.params.optimizeLevel = 2; 344 DebugCondition::addGlobalIdent);
397 if (p[2] != 0) { 345 processVersions(versions, "version",
398 int optlevel = atoi(p+2); 346 VersionCondition::setGlobalLevel,
399 if (optlevel < 0 || optlevel > 5) { 347 VersionCondition::addGlobalIdent);
400 error("Optimization level must be between 0 and 5. Using default (%d)", 348
401 global.params.optimizeLevel); 349 global.params.output_o =
402 } 350 opts::output_o == cl::BOU_UNSET
403 else { 351 ? OUTPUTFLAGdefault
404 global.params.optimizeLevel = optlevel; 352 : opts::output_o == cl::BOU_TRUE
405 } 353 ? OUTPUTFLAGset
406 } 354 : OUTPUTFLAGno;
355 global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno;
356 global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno;
357 global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno;
358
359 if (global.params.run || !runargs.empty()) {
360 // FIXME: how to properly detect the presence of a PositionalEatsArgs
361 // option without parameters? We want to emit an error in that case...
362 // You'd think getNumOccurrences would do it, but it just returns the
363 // number of parameters)
364 // NOTE: Hacked around it by detecting -run in getenv_setargv(), where
365 // we're looking for it anyway, and pre-setting the flag...
366 global.params.run = true;
367 if (!runargs.empty()) {
368 files.push(mem.strdup(runargs[0].c_str()));
369 } else {
370 global.params.run = false;
371 error("Expected at least one argument to '-run'\n");
407 } 372 }
408 else if (strcmp(p + 1, "forcebe") == 0) 373 }
409 global.params.forceBE = 1; 374
410 else if (strcmp(p + 1, "noruntime") == 0) 375 if (mArch)
411 global.params.noruntime = 1; 376 global.params.llvmArch = mArch->Name;
412 else if (strcmp(p + 1, "noverify") == 0) 377
413 global.params.novalidate = 1; 378 files.reserve(fileList.size());
414 else if (strcmp(p + 1, "annotate") == 0) 379 typedef std::vector<std::string>::iterator It;
415 global.params.llvmAnnotate = 1; 380 for(It I = fileList.begin(), E = fileList.end(); I != E; ++I)
416 else if (strncmp(p + 1, "enable-", 7) == 0 || 381 if (!I->empty())
417 strncmp(p + 1, "disable-", 8) == 0) 382 files.push(mem.strdup(I->c_str()));
418 { 383
419 bool enable = (p[1] == 'e');
420 char* feature = p + 1 + (enable ? 7 : 8);
421 if (strcmp(feature, "asserts") == 0)
422 global.params.useAssert = enable;
423 else if (strcmp(feature, "boundscheck") == 0)
424 global.params.useArrayBounds = enable;
425 else if (strcmp(feature, "contracts") == 0)
426 {
427 global.params.useIn = enable;
428 global.params.useOut = enable;
429 }
430 else if (strcmp(feature, "invariants") == 0)
431 global.params.useInvariants = enable;
432 else
433 error("unrecognized feature '%s'", feature);
434 }
435 else if (strcmp(p + 1, "noasm") == 0)
436 global.params.useInlineAsm = 0;
437 else if (strcmp(p + 1, "nodefaultlib") == 0)
438 global.params.noDefaultLib = 1;
439 else if (p[1] == 'o')
440 {
441 switch (p[2])
442 {
443 case '-':
444 global.params.obj = 0;
445 break;
446
447 case 'd':
448 if (!p[3])
449 goto Lnoarg;
450 global.params.objdir = p + 3;
451 break;
452
453 case 'f':
454 if (!p[3])
455 goto Lnoarg;
456 global.params.objname = p + 3;
457 break;
458
459 case 'p':
460 if (p[3])
461 goto Lerror;
462 global.params.preservePaths = 1;
463 break;
464
465 case 'q':
466 if (p[3])
467 goto Lerror;
468 global.params.fqnNames = 1;
469 break;
470
471 case 'u':
472 if (strncmp(p+1, "output-", 7) != 0)
473 goto Lerror;
474
475 // remove default output
476 if (global.params.output_o == OUTPUTFLAGdefault)
477 global.params.output_o = OUTPUTFLAGno;
478
479 if (strcmp(p+8, global.ll_ext) == 0)
480 global.params.output_ll = OUTPUTFLAGset;
481 else if (strcmp(p+8, global.bc_ext) == 0)
482 global.params.output_bc = OUTPUTFLAGset;
483 else if (strcmp(p+8, global.s_ext) == 0)
484 global.params.output_s = OUTPUTFLAGset;
485 else if (strcmp(p+8, global.obj_ext) == 0)
486 global.params.output_o = OUTPUTFLAGset;
487 else
488 goto Lerror;
489
490 break;
491
492 case 0:
493 error("-o no longer supported, use -of or -od");
494 break;
495
496 default:
497 goto Lerror;
498 }
499 }
500 else if (p[1] == 'D')
501 { global.params.doDocComments = 1;
502 switch (p[2])
503 {
504 case 'd':
505 if (!p[3])
506 goto Lnoarg;
507 global.params.docdir = p + 3;
508 break;
509 case 'f':
510 if (!p[3])
511 goto Lnoarg;
512 global.params.docname = p + 3;
513 break;
514
515 case 0:
516 break;
517
518 default:
519 goto Lerror;
520 }
521 }
522 #ifdef _DH
523 else if (p[1] == 'H')
524 { global.params.doHdrGeneration = 1;
525 switch (p[2])
526 {
527 case 'd':
528 if (!p[3])
529 goto Lnoarg;
530 global.params.hdrdir = p + 3;
531 break;
532
533 case 'f':
534 if (!p[3])
535 goto Lnoarg;
536 global.params.hdrname = p + 3;
537 break;
538
539 case 0:
540 break;
541
542 default:
543 goto Lerror;
544 }
545 }
546 #endif
547 else if (strcmp(p + 1, "ignore") == 0)
548 global.params.ignoreUnsupportedPragmas = 1;
549 else if (strcmp(p + 1, "inline") == 0) {
550 // TODO
551 // the ast rewrites dmd does for inlining messes up the ast.
552 // someday maybe we can support it, for now llvm does an excellent job at inlining
553 global.params.useInline = 0; //1
554 global.params.llvmInline = 1;
555 }
556 else if (strcmp(p + 1, "quiet") == 0)
557 global.params.quiet = 1;
558 else if (strcmp(p + 1, "release") == 0)
559 {
560 global.params.useInvariants = 0;
561 global.params.useIn = 0;
562 global.params.useOut = 0;
563 global.params.useAssert = 0;
564 global.params.useArrayBounds = 0;
565 }
566 else if (strcmp(p + 1, "unittest") == 0)
567 global.params.useUnitTests = 1;
568 else if (p[1] == 'I')
569 {
570 if (!global.params.imppath)
571 global.params.imppath = new Array();
572 global.params.imppath->push(p + 2);
573 }
574 else if (p[1] == 'J')
575 {
576 if (!global.params.fileImppath)
577 global.params.fileImppath = new Array();
578 global.params.fileImppath->push(p + 2);
579 }
580 else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
581 {
582 // Parse:
583 // -debug
584 // -debug=number
585 // -debug=identifier
586 if (p[6] == '=')
587 {
588 if (isdigit(p[7]))
589 { long level;
590
591 errno = 0;
592 level = strtol(p + 7, &p, 10);
593 if (*p || errno || level > INT_MAX)
594 goto Lerror;
595 DebugCondition::setGlobalLevel((int)level);
596 }
597 else if (Lexer::isValidIdentifier(p + 7))
598 DebugCondition::addGlobalIdent(p + 7);
599 else
600 goto Lerror;
601 }
602 else if (p[6])
603 goto Lerror;
604 else
605 {
606 global.params.useInvariants = 1;
607 global.params.useIn = 1;
608 global.params.useOut = 1;
609 global.params.useAssert = 1;
610 global.params.useArrayBounds = 1;
611 global.params.debuglevel = 1;
612 }
613 }
614 else if (memcmp(p + 1, "version", 5) == 0)
615 {
616 // Parse:
617 // -version=number
618 // -version=identifier
619 if (p[8] == '=')
620 {
621 if (isdigit(p[9]))
622 { long level;
623
624 errno = 0;
625 level = strtol(p + 9, &p, 10);
626 if (*p || errno || level > INT_MAX)
627 goto Lerror;
628 VersionCondition::setGlobalLevel((int)level);
629 }
630 else if (Lexer::isValidIdentifier(p + 9))
631 VersionCondition::addGlobalIdent(p + 9);
632 else
633 goto Lerror;
634 }
635 else
636 goto Lerror;
637 }
638 else if (strcmp(p + 1, "-b") == 0)
639 global.params.debugb = 1;
640 else if (strcmp(p + 1, "-c") == 0)
641 global.params.debugc = 1;
642 else if (strcmp(p + 1, "-f") == 0)
643 global.params.debugf = 1;
644 else if (strcmp(p + 1, "-help") == 0)
645 { usage();
646 exit(EXIT_SUCCESS);
647 }
648 else if (strcmp(p + 1, "-r") == 0)
649 global.params.debugr = 1;
650 else if (strcmp(p + 1, "-x") == 0)
651 global.params.debugx = 1;
652 else if (strcmp(p + 1, "-y") == 0)
653 global.params.debugy = 1;
654 else if (p[1] == 'L')
655 {
656 global.params.linkswitches->push(p + 2);
657 }
658 else if (memcmp(p + 1, "defaultlib=", 11) == 0)
659 {
660 if(!global.params.defaultlibnames)
661 global.params.defaultlibnames = new Array();
662 global.params.defaultlibnames->push(p + 1 + 11);
663 }
664 else if (memcmp(p + 1, "debuglib=", 9) == 0)
665 {
666 if(!global.params.debuglibnames)
667 global.params.debuglibnames = new Array();
668 global.params.debuglibnames->push(p + 1 + 9);
669 }
670 else if (strcmp(p + 1, "run") == 0)
671 { global.params.run = 1;
672 global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
673 if (global.params.runargs_length)
674 {
675 files.push(argv[i + 1]);
676 global.params.runargs = &argv[i + 2];
677 i += global.params.runargs_length;
678 global.params.runargs_length--;
679 }
680 else
681 { global.params.run = 0;
682 goto Lnoarg;
683 }
684 }
685 else if (p[1] == 'm')
686 {
687 global.params.llvmArch = p+2;
688 }
689 else if (p[1] == 't')
690 {
691 if(strcmp(p + 2, "Linux") == 0)
692 global.params.os = OSLinux;
693 else if(strcmp(p + 2, "Windows") == 0)
694 global.params.os = OSWindows;
695 else if(strcmp(p + 2, "MacOSX") == 0)
696 global.params.os = OSMacOSX;
697 else if(strcmp(p + 2, "FreeBSD") == 0)
698 global.params.os = OSFreeBSD;
699 else if(strcmp(p + 2, "Solaris") == 0)
700 global.params.os = OSSolaris;
701 else
702 error("unrecognized target os '%s'", p + 2);
703 }
704 else
705 {
706 Lerror:
707 error("unrecognized switch '%s'", argv[i]);
708 continue;
709
710 Lnoarg:
711 error("argument expected for switch '%s'", argv[i]);
712 continue;
713 }
714 }
715 else
716 files.push(p);
717 }
718 if (global.errors) 384 if (global.errors)
719 { 385 {
720 fatal(); 386 fatal();
721 } 387 }
722 if (files.dim == 0) 388 if (files.dim == 0)
723 { usage(); 389 {
390 cl::PrintHelpMessage();
724 return EXIT_FAILURE; 391 return EXIT_FAILURE;
725 } 392 }
726 393
727 Array* libs; 394 Array* libs;
728 if (global.params.symdebug) 395 if (global.params.symdebug)
738 strcpy(arg, "-l"); 405 strcpy(arg, "-l");
739 strncat(arg, (char *)libs->data[i], 64); 406 strncat(arg, (char *)libs->data[i], 64);
740 global.params.linkswitches->push(arg); 407 global.params.linkswitches->push(arg);
741 } 408 }
742 } 409 }
743 else if (!global.params.noDefaultLib) 410 else if (!noDefaultLib)
744 { 411 {
745 char *arg; 412 char *arg;
746 arg = (char *)mem.malloc(64); 413 arg = (char *)mem.malloc(64);
747 strcpy(arg, "-lldc-runtime"); 414 strcpy(arg, "-lldc-runtime");
748 global.params.linkswitches->push(arg); 415 global.params.linkswitches->push(arg);
758 strcpy(arg, "-lldc-runtime"); 425 strcpy(arg, "-lldc-runtime");
759 global.params.linkswitches->push(arg); 426 global.params.linkswitches->push(arg);
760 } 427 }
761 428
762 if (global.params.run) 429 if (global.params.run)
763 global.params.quiet = 1; 430 quiet = 1;
764 431
765 if (global.params.useUnitTests) 432 if (global.params.useUnitTests)
766 global.params.useAssert = 1; 433 global.params.useAssert = 1;
767 434
768 // LDC output determination 435 // LDC output determination
891 error("invalid cpu architecture specified: %s", global.params.llvmArch); 558 error("invalid cpu architecture specified: %s", global.params.llvmArch);
892 } 559 }
893 560
894 assert(global.params.cpu != ARCHinvalid); 561 assert(global.params.cpu != ARCHinvalid);
895 562
896 if (allowForceEndianness && global.params.forceBE) { 563 if (allowForceEndianness && forceBE) {
897 VersionCondition::addPredefinedGlobalIdent("BigEndian"); 564 VersionCondition::addPredefinedGlobalIdent("BigEndian");
898 global.params.isLE = false; 565 global.params.isLE = false;
899 } 566 }
900 else if (global.params.isLE) { 567 else if (global.params.isLE) {
901 VersionCondition::addPredefinedGlobalIdent("LittleEndian"); 568 VersionCondition::addPredefinedGlobalIdent("LittleEndian");
1304 971
1305 argc = *pargc; 972 argc = *pargc;
1306 argv = new Array(); 973 argv = new Array();
1307 argv->setDim(argc); 974 argv->setDim(argc);
1308 975
1309 for (int i = 0; i < argc; i++) 976 int argc_left = 0;
1310 argv->data[i] = (void *)(*pargv)[i]; 977 for (int i = 0; i < argc; i++) {
978 if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
979 // HACK: set flag to indicate we saw '-run' here
980 global.params.run = true;
981 // Don't eat -run yet so the program arguments don't get changed
982 argc_left = argc - i;
983 argc = i;
984 *pargv = &(*pargv)[i];
985 argv->setDim(i);
986 break;
987 } else {
988 argv->data[i] = (void *)(*pargv)[i];
989 }
990 }
991 // HACK to stop required values from command line being drawn from DFLAGS
992 argv->push((char*)"");
993 argc++;
1311 994
1312 j = 1; // leave argv[0] alone 995 j = 1; // leave argv[0] alone
1313 while (1) 996 while (1)
1314 { 997 {
1315 wildcard = 1; 998 wildcard = 1;
1380 } 1063 }
1381 } 1064 }
1382 } 1065 }
1383 1066
1384 Ldone: 1067 Ldone:
1068 assert(argc == argv->dim);
1069 argv->reserve(argc_left);
1070 for (int i = 0; i < argc_left; i++)
1071 argv->data[argc++] = (void *)(*pargv)[i];
1072
1385 *pargc = argc; 1073 *pargc = argc;
1386 *pargv = (char **)argv->data; 1074 *pargv = (char **)argv->data;
1387 } 1075 }