Mercurial > projects > ldc
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(¶ms, 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 } |