Mercurial > projects > ldc
annotate dmd/mars.c @ 54:28e99b04a132 trunk
[svn r58] Fixed cond expression resulting in a non-basic type.
Fixed identity expression for dynamic arrays.
Revamped the system to keep track of lvalues and rvalues and their relations.
Typedef declaration now generate the custom typeinfo.
Other bugfixes.
author | lindquist |
---|---|
date | Wed, 24 Oct 2007 01:37:34 +0200 |
parents | 0c77619e803b |
children | 0ccfae271c45 |
rev | line source |
---|---|
1 | 1 // Compiler implementation of the D programming language |
2 // Copyright (c) 1999-2007 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 #include "llvm/Target/TargetMachineRegistry.h" | |
11 | |
12 #include <stdio.h> | |
13 #include <stdlib.h> | |
14 #include <ctype.h> | |
15 #include <assert.h> | |
16 #include <limits.h> | |
17 #include <string> | |
18 | |
19 #if _WIN32 | |
20 #include <windows.h> | |
21 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); | |
22 #endif | |
23 | |
24 #if __DMC__ | |
25 #include <dos.h> | |
26 #endif | |
27 | |
28 #if linux | |
29 #include <errno.h> | |
30 #endif | |
31 | |
32 #include "mem.h" | |
33 #include "root.h" | |
34 | |
35 #include "mars.h" | |
36 #include "module.h" | |
37 #include "mtype.h" | |
38 #include "id.h" | |
39 #include "cond.h" | |
40 #include "expression.h" | |
52 | 41 #include "lexer.h" |
42 | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
43 #include "gen/logger.h" |
1 | 44 |
45 void getenv_setargv(const char *envvar, int *pargc, char** *pargv); | |
46 | |
47 Global global; | |
48 | |
49 Global::Global() | |
50 { | |
51 mars_ext = "d"; | |
52 sym_ext = "d"; | |
53 hdr_ext = "di"; | |
54 doc_ext = "html"; | |
55 ddoc_ext = "ddoc"; | |
56 | |
57 #if IN_LLVM | |
58 obj_ext = "bc"; | |
59 ll_ext = "ll"; | |
60 bc_ext = "bc"; | |
61 nativeobj_ext = "o"; | |
62 #elif _WIN32 | |
63 obj_ext = "obj"; | |
64 #elif linux | |
65 obj_ext = "o"; | |
66 #else | |
67 #error "fix this" | |
68 #endif | |
69 | |
70 copyright = "Copyright (c) 1999-2007 by Digital Mars and Tomas Lindquist Olsen"; | |
71 written = "written by Walter Bright and Tomas Lindquist Olsen"; | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
31
diff
changeset
|
72 llvmdc_version = "0.1"; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
31
diff
changeset
|
73 version = "v1.022"; |
1 | 74 global.structalign = 8; |
75 | |
76 memset(¶ms, 0, sizeof(Param)); | |
77 } | |
78 | |
79 char *Loc::toChars() | |
80 { | |
81 OutBuffer buf; | |
82 char *p; | |
83 | |
84 if (filename) | |
85 { | |
86 buf.printf("%s", filename); | |
87 } | |
88 | |
89 if (linnum) | |
90 buf.printf("(%d)", linnum); | |
91 buf.writeByte(0); | |
92 return (char *)buf.extractData(); | |
93 } | |
94 | |
95 Loc::Loc(Module *mod, unsigned linnum) | |
96 { | |
97 this->linnum = linnum; | |
98 this->filename = mod ? mod->srcfile->toChars() : NULL; | |
99 } | |
100 | |
101 /************************************** | |
102 * Print error message and exit. | |
103 */ | |
104 | |
105 void error(Loc loc, const char *format, ...) | |
106 { | |
107 va_list ap; | |
108 va_start(ap, format); | |
109 verror(loc, format, ap); | |
110 va_end( ap ); | |
111 } | |
112 | |
113 void verror(Loc loc, const char *format, va_list ap) | |
114 { | |
115 if (!global.gag) | |
116 { | |
117 char *p = loc.toChars(); | |
118 | |
119 if (*p) | |
120 fprintf(stdmsg, "%s: ", p); | |
121 mem.free(p); | |
122 | |
123 fprintf(stdmsg, "Error: "); | |
124 vfprintf(stdmsg, format, ap); | |
125 fprintf(stdmsg, "\n"); | |
126 fflush(stdmsg); | |
127 } | |
128 global.errors++; | |
129 } | |
130 | |
131 /*************************************** | |
132 * Call this after printing out fatal error messages to clean up and exit | |
133 * the compiler. | |
134 */ | |
135 | |
136 void fatal() | |
137 { | |
138 #if 0 | |
139 halt(); | |
140 #endif | |
141 exit(EXIT_FAILURE); | |
142 } | |
143 | |
144 /************************************** | |
145 * Try to stop forgetting to remove the breakpoints from | |
146 * release builds. | |
147 */ | |
148 void halt() | |
149 { | |
150 #ifdef DEBUG | |
151 *(char*)0=0; | |
152 #endif | |
153 } | |
154 | |
155 extern void backend_init(); | |
156 extern void backend_term(); | |
157 | |
158 void usage() | |
159 { | |
160 printf("LLVM D Compiler %s (based on DMD %s)\n%s\n%s\n", | |
161 global.llvmdc_version, global.version, global.copyright, global.written); | |
162 printf("\ | |
9 | 163 D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ |
164 LLVMDC Homepage: http://www.dsource.org/projects/llvmdc\n\ | |
1 | 165 Usage:\n\ |
166 dmd files.d ... { -switch }\n\ | |
167 \n\ | |
168 files.d D source files\n%s\ | |
169 -c do not link\n\ | |
170 -cov do code coverage analysis\n\ | |
171 -D generate documentation\n\ | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
172 -Dd<docdir> write documentation file to <docdir> directory\n\ |
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
173 -Df<filename> write documentation file to <filename>\n\ |
1 | 174 -d allow deprecated features\n\ |
175 -debug compile in debug code\n\ | |
176 -debug=level compile in debug code <= level\n\ | |
177 -debug=ident compile in debug code identified by ident\n\ | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
31
diff
changeset
|
178 -debuglib=name set symbolic debug library to name\n\ |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
31
diff
changeset
|
179 -defaultlib=name set default library to name\n\ |
52 | 180 -dis disassemble module after compiling\n\ |
1 | 181 -g add symbolic debug info\n\ |
182 -gc add symbolic debug info, pretend to be C\n\ | |
183 -H generate 'header' file\n\ | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
184 -Hd<hdrdir> write 'header' file to <hdrdir> directory\n\ |
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
185 -Hf<filename> write 'header' file to <filename>\n\ |
1 | 186 --help print help\n\ |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
187 -I<path> where to look for imports\n\ |
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
188 -E<path> where to look for the core runtime\n\ |
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
189 -J<path> where to look for string imports\n\ |
1 | 190 -inline do function inlining\n\ |
191 -Llinkerflag pass linkerflag to link\n\ | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
192 -m<arch> emit code specific to <arch>\n\ |
1 | 193 x86 x86-64 ppc32 ppc64\n\ |
194 -nofloat do not emit reference to floating point\n\ | |
195 -noruntime do not allow code that generates implicit runtime calls\n\ | |
40 | 196 -noverify do not run the validation pass before writing bitcode\n\ |
1 | 197 -O optimize, same as -O2\n\ |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
198 -O<n> optimize at level <n> (0-5)\n\ |
1 | 199 -o- do not write object file\n\ |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
200 -od<objdir> write object files to directory <objdir>\n\ |
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
201 -of<filename> name output file to <filename>\n\ |
1 | 202 -op do not strip paths from source file\n\ |
40 | 203 -profile profile runtime performance of generated code\n\ |
1 | 204 -quiet suppress unnecessary messages\n\ |
40 | 205 -release compile release version\n\ |
1 | 206 -run srcfile args... run resulting program, passing args\n\ |
207 -unittest compile in unit tests\n\ | |
52 | 208 -v verbose\n\ |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
209 -vv very verbose (does not include -v)\n\ |
1 | 210 -v1 D language version 1\n\ |
211 -version=level compile in version code >= level\n\ | |
212 -version=ident compile in version code identified by ident\n\ | |
213 -w enable warnings\n\ | |
214 ", | |
215 #if WIN32 | |
216 " @cmdfile read arguments from cmdfile\n" | |
217 #else | |
218 "" | |
219 #endif | |
220 ); | |
221 } | |
222 | |
223 int main(int argc, char *argv[]) | |
224 { | |
225 int i; | |
226 Array files; | |
227 char *p; | |
228 Module *m; | |
229 int status = EXIT_SUCCESS; | |
230 int argcstart = argc; | |
231 char* tt_arch = 0; | |
232 char* tt_os = 0; | |
52 | 233 char* data_layout = 0; |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
234 bool very_verbose = false; |
1 | 235 |
236 // Check for malformed input | |
237 if (argc < 1 || !argv) | |
238 { | |
239 Largs: | |
240 error("missing or null command line arguments"); | |
241 fatal(); | |
242 } | |
243 for (i = 0; i < argc; i++) | |
244 { | |
245 if (!argv[i]) | |
246 goto Largs; | |
247 } | |
248 | |
249 #if __DMC__ // DMC unique support for response files | |
250 if (response_expand(&argc,&argv)) // expand response files | |
251 error("can't open response file"); | |
252 #endif | |
253 | |
254 files.reserve(argc - 1); | |
255 | |
256 // Set default values | |
257 global.params.argv0 = argv[0]; | |
258 global.params.link = 1; | |
259 global.params.useAssert = 0; | |
260 global.params.useInvariants = 0; | |
261 global.params.useIn = 0; | |
262 global.params.useOut = 0; | |
263 global.params.useArrayBounds = 0; | |
264 global.params.useSwitchError = 0; | |
265 global.params.useInline = 0; | |
266 global.params.obj = 1; | |
267 global.params.Dversion = 2; | |
268 | |
269 global.params.linkswitches = new Array(); | |
270 global.params.libfiles = new Array(); | |
271 global.params.objfiles = new Array(); | |
272 global.params.ddocfiles = new Array(); | |
273 | |
274 global.params.is64bit = sizeof(void*) == 8 ? 1 : 0; | |
275 | |
276 uint16_t endiantest = 0xFF00; | |
277 uint8_t endianres = ((uint8_t*)&endiantest)[0]; | |
278 if (endianres == 0x00) | |
279 global.params.isLE = true; | |
280 else if (endianres == 0xFF) | |
281 global.params.isLE = false; | |
282 else { | |
283 error("Endian test is broken"); | |
284 fatal(); | |
285 } | |
286 | |
287 global.params.llvmArch = 0; | |
288 global.params.forceBE = 0; | |
289 global.params.noruntime = 0; | |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
19
diff
changeset
|
290 global.params.novalidate = 0; |
1 | 291 global.params.optimizeLevel = 2; |
292 global.params.runtimeImppath = 0; | |
293 | |
19 | 294 global.params.defaultlibname = "phobos"; |
295 global.params.debuglibname = global.params.defaultlibname; | |
296 | |
1 | 297 // Predefine version identifiers |
298 #if IN_LLVM | |
299 VersionCondition::addPredefinedGlobalIdent("LLVM"); | |
300 #endif | |
301 #if _WIN32 | |
302 VersionCondition::addPredefinedGlobalIdent("Windows"); | |
303 VersionCondition::addPredefinedGlobalIdent("Win32"); | |
304 global.params.isWindows = 1; | |
305 #elif linux | |
306 VersionCondition::addPredefinedGlobalIdent("linux"); | |
307 global.params.isLinux = 1; | |
308 tt_os = "-unknown-linux-gnu"; | |
309 #else | |
310 #error | |
311 #endif /* linux */ | |
312 | |
313 //VersionCondition::addPredefinedGlobalIdent("D_Bits"); | |
314 //VersionCondition::addPredefinedGlobalIdent("D_InlineAsm"); | |
315 //VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86"); | |
316 VersionCondition::addPredefinedGlobalIdent("all"); | |
317 | |
318 #if _WIN32 | |
319 inifile(argv[0], "llvmdc.ini"); | |
320 #endif | |
321 #if linux | |
322 inifile(argv[0], "llvmdc.conf"); | |
323 #else | |
324 #error | |
325 #endif | |
326 getenv_setargv("DFLAGS", &argc, &argv); | |
327 | |
328 #if 0 | |
329 for (i = 0; i < argc; i++) | |
330 { | |
331 printf("argv[%d] = '%s'\n", i, argv[i]); | |
332 } | |
333 #endif | |
334 | |
335 for (i = 1; i < argc; i++) | |
336 { | |
337 p = argv[i]; | |
338 if (*p == '-') | |
339 { | |
340 if (strcmp(p + 1, "d") == 0) | |
341 global.params.useDeprecated = 1; | |
342 else if (strcmp(p + 1, "c") == 0) | |
343 global.params.link = 0; | |
344 else if (strcmp(p + 1, "cov") == 0) | |
345 global.params.cov = 1; | |
346 else if (strcmp(p + 1, "fPIC") == 0) | |
347 global.params.pic = 1; | |
348 else if (strcmp(p + 1, "g") == 0) | |
349 global.params.symdebug = 1; | |
350 else if (strcmp(p + 1, "gc") == 0) | |
351 global.params.symdebug = 2; | |
352 else if (strcmp(p + 1, "gt") == 0) | |
353 { error("use -profile instead of -gt\n"); | |
354 global.params.trace = 1; | |
355 } | |
356 else if (strcmp(p + 1, "profile") == 0) | |
357 global.params.trace = 1; | |
358 else if (strcmp(p + 1, "v") == 0) | |
52 | 359 global.params.verbose = 1; |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
360 else if (strcmp(p + 1, "vv") == 0) { |
52 | 361 Logger::enable(); |
362 very_verbose = true; | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
363 } |
1 | 364 else if (strcmp(p + 1, "v1") == 0) |
365 global.params.Dversion = 1; | |
366 else if (strcmp(p + 1, "w") == 0) | |
367 global.params.warnings = 1; | |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
9
diff
changeset
|
368 else if (p[1] == 'O') |
1 | 369 { |
370 global.params.optimize = 1; | |
371 if (p[2] != 0) { | |
372 int optlevel = atoi(p+2); | |
373 if (optlevel < 0 || optlevel > 5) { | |
374 error("Optimization level must be between 0 and 5. Using default (%d)", | |
375 global.params.optimizeLevel); | |
376 } | |
377 else { | |
378 global.params.optimizeLevel = optlevel; | |
379 } | |
380 } | |
381 } | |
382 else if (strcmp(p + 1, "forcebe") == 0) | |
383 global.params.forceBE = 1; | |
384 else if (strcmp(p + 1, "noruntime") == 0) | |
385 global.params.noruntime = 1; | |
40 | 386 else if (strcmp(p + 1, "noverify") == 0) |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
19
diff
changeset
|
387 global.params.novalidate = 1; |
52 | 388 else if (strcmp(p + 1, "dis") == 0) |
389 global.params.disassemble = 1; | |
1 | 390 else if (p[1] == 'o') |
391 { | |
392 switch (p[2]) | |
393 { | |
394 case '-': | |
395 global.params.obj = 0; | |
396 break; | |
397 | |
398 case 'd': | |
399 if (!p[3]) | |
400 goto Lnoarg; | |
401 global.params.objdir = p + 3; | |
402 break; | |
403 | |
404 case 'f': | |
405 if (!p[3]) | |
406 goto Lnoarg; | |
407 global.params.objname = p + 3; | |
408 break; | |
409 | |
410 case 'p': | |
411 if (p[3]) | |
412 goto Lerror; | |
413 global.params.preservePaths = 1; | |
414 break; | |
415 | |
416 case 0: | |
417 error("-o no longer supported, use -of or -od"); | |
418 break; | |
419 | |
420 default: | |
421 goto Lerror; | |
422 } | |
423 } | |
424 else if (p[1] == 'D') | |
425 { global.params.doDocComments = 1; | |
426 switch (p[2]) | |
427 { | |
428 case 'd': | |
429 if (!p[3]) | |
430 goto Lnoarg; | |
431 global.params.docdir = p + 3; | |
432 break; | |
433 case 'f': | |
434 if (!p[3]) | |
435 goto Lnoarg; | |
436 global.params.docname = p + 3; | |
437 break; | |
438 | |
439 case 0: | |
440 break; | |
441 | |
442 default: | |
443 goto Lerror; | |
444 } | |
445 } | |
446 #ifdef _DH | |
447 else if (p[1] == 'H') | |
448 { global.params.doHdrGeneration = 1; | |
449 switch (p[2]) | |
450 { | |
451 case 'd': | |
452 if (!p[3]) | |
453 goto Lnoarg; | |
454 global.params.hdrdir = p + 3; | |
455 break; | |
456 | |
457 case 'f': | |
458 if (!p[3]) | |
459 goto Lnoarg; | |
460 global.params.hdrname = p + 3; | |
461 break; | |
462 | |
463 case 0: | |
464 break; | |
465 | |
466 default: | |
467 goto Lerror; | |
468 } | |
469 } | |
470 #endif | |
471 else if (strcmp(p + 1, "inline") == 0) | |
472 global.params.useInline = 1; | |
473 else if (strcmp(p + 1, "nofloat") == 0) | |
474 global.params.nofloat = 1; | |
475 else if (strcmp(p + 1, "quiet") == 0) | |
476 global.params.quiet = 1; | |
477 else if (strcmp(p + 1, "release") == 0) | |
478 global.params.release = 1; | |
479 else if (strcmp(p + 1, "unittest") == 0) | |
480 global.params.useUnitTests = 1; | |
481 else if (p[1] == 'I') | |
482 { | |
483 if (!global.params.imppath) | |
484 global.params.imppath = new Array(); | |
485 global.params.imppath->push(p + 2); | |
486 } | |
487 else if (p[1] == 'J') | |
488 { | |
489 if (!global.params.fileImppath) | |
490 global.params.fileImppath = new Array(); | |
491 global.params.fileImppath->push(p + 2); | |
492 } | |
493 else if (p[1] == 'E') | |
494 { | |
495 global.params.runtimeImppath = p+2; | |
496 } | |
19 | 497 else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l') |
1 | 498 { |
499 // Parse: | |
500 // -debug | |
501 // -debug=number | |
502 // -debug=identifier | |
503 if (p[6] == '=') | |
504 { | |
505 if (isdigit(p[7])) | |
506 { long level; | |
507 | |
508 errno = 0; | |
509 level = strtol(p + 7, &p, 10); | |
510 if (*p || errno || level > INT_MAX) | |
511 goto Lerror; | |
512 DebugCondition::setGlobalLevel((int)level); | |
513 } | |
514 else if (Lexer::isValidIdentifier(p + 7)) | |
515 DebugCondition::addGlobalIdent(p + 7); | |
516 else | |
517 goto Lerror; | |
518 } | |
519 else if (p[6]) | |
520 goto Lerror; | |
521 else | |
522 global.params.debuglevel = 1; | |
523 } | |
524 else if (memcmp(p + 1, "version", 5) == 0) | |
525 { | |
526 // Parse: | |
527 // -version=number | |
528 // -version=identifier | |
529 if (p[8] == '=') | |
530 { | |
531 if (isdigit(p[9])) | |
532 { long level; | |
533 | |
534 errno = 0; | |
535 level = strtol(p + 9, &p, 10); | |
536 if (*p || errno || level > INT_MAX) | |
537 goto Lerror; | |
538 VersionCondition::setGlobalLevel((int)level); | |
539 } | |
540 else if (Lexer::isValidIdentifier(p + 9)) | |
541 VersionCondition::addGlobalIdent(p + 9); | |
542 else | |
543 goto Lerror; | |
544 } | |
545 else | |
546 goto Lerror; | |
547 } | |
548 else if (strcmp(p + 1, "-b") == 0) | |
549 global.params.debugb = 1; | |
550 else if (strcmp(p + 1, "-c") == 0) | |
551 global.params.debugc = 1; | |
552 else if (strcmp(p + 1, "-f") == 0) | |
553 global.params.debugf = 1; | |
554 else if (strcmp(p + 1, "-help") == 0) | |
555 { usage(); | |
556 exit(EXIT_SUCCESS); | |
557 } | |
558 else if (strcmp(p + 1, "-r") == 0) | |
559 global.params.debugr = 1; | |
560 else if (strcmp(p + 1, "-x") == 0) | |
561 global.params.debugx = 1; | |
562 else if (strcmp(p + 1, "-y") == 0) | |
563 global.params.debugy = 1; | |
564 else if (p[1] == 'L') | |
565 { | |
566 global.params.linkswitches->push(p + 2); | |
567 } | |
19 | 568 else if (memcmp(p + 1, "defaultlib=", 11) == 0) |
569 { | |
570 global.params.defaultlibname = p + 1 + 11; | |
571 } | |
572 else if (memcmp(p + 1, "debuglib=", 9) == 0) | |
573 { | |
574 global.params.debuglibname = p + 1 + 9; | |
575 } | |
1 | 576 else if (strcmp(p + 1, "run") == 0) |
577 { global.params.run = 1; | |
578 global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1; | |
579 if (global.params.runargs_length) | |
580 { | |
581 files.push(argv[i + 1]); | |
582 global.params.runargs = &argv[i + 2]; | |
583 i += global.params.runargs_length; | |
584 global.params.runargs_length--; | |
585 } | |
586 else | |
587 { global.params.run = 0; | |
588 goto Lnoarg; | |
589 } | |
590 } | |
591 else if (p[1] == 'm') | |
592 { | |
593 global.params.llvmArch = p+2; | |
594 } | |
595 else | |
596 { | |
597 Lerror: | |
598 error("unrecognized switch '%s'", argv[i]); | |
599 continue; | |
600 | |
601 Lnoarg: | |
602 error("argument expected for switch '%s'", argv[i]); | |
603 continue; | |
604 } | |
605 } | |
606 else | |
607 files.push(p); | |
608 } | |
609 if (global.errors) | |
610 { | |
611 fatal(); | |
612 } | |
613 if (files.dim == 0) | |
614 { usage(); | |
615 return EXIT_FAILURE; | |
616 } | |
617 | |
618 if (global.params.release) | |
619 { global.params.useInvariants = 0; | |
620 global.params.useIn = 0; | |
621 global.params.useOut = 0; | |
622 global.params.useAssert = 0; | |
623 global.params.useArrayBounds = 0; | |
624 global.params.useSwitchError = 0; | |
625 } | |
626 | |
627 if (global.params.run) | |
628 global.params.quiet = 1; | |
629 | |
630 if (global.params.useUnitTests) | |
631 global.params.useAssert = 1; | |
632 | |
633 if (!global.params.obj) | |
634 global.params.link = 0; | |
635 | |
636 if (global.params.link) | |
637 { | |
638 global.params.exefile = global.params.objname; | |
639 global.params.objname = NULL; | |
640 } | |
641 else if (global.params.run) | |
642 { | |
643 error("flags conflict with -run"); | |
644 fatal(); | |
645 } | |
646 else | |
647 { | |
648 if (global.params.objname && files.dim > 1) | |
649 { | |
650 error("multiple source files, but only one .obj name"); | |
651 fatal(); | |
652 } | |
653 } | |
654 if (global.params.cov) | |
655 VersionCondition::addPredefinedGlobalIdent("D_Coverage"); | |
656 | |
657 bool allowForceEndianness = false; | |
658 | |
659 if (global.params.llvmArch == 0) { | |
660 std::string err_str; | |
661 const llvm::TargetMachineRegistry::Entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str); | |
662 if (e == 0) { | |
663 error("Failed to find a default target machine: %s", err_str.c_str()); | |
664 fatal(); | |
665 } | |
666 else { | |
52 | 667 global.params.llvmArch = const_cast<char*>(e->Name); |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
35
diff
changeset
|
668 if (global.params.verbose || very_verbose) |
1 | 669 printf("Default target found: %s\n", global.params.llvmArch); |
670 } | |
671 } | |
672 | |
673 if (strcmp(global.params.llvmArch,"x86")==0) { | |
674 VersionCondition::addPredefinedGlobalIdent("X86"); | |
675 global.params.isLE = true; | |
676 global.params.is64bit = false; | |
677 tt_arch = "i686"; | |
678 data_layout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:8"; | |
679 } | |
680 else if (strcmp(global.params.llvmArch,"x86-64")==0) { | |
681 VersionCondition::addPredefinedGlobalIdent("X86_64"); | |
682 global.params.isLE = true; | |
683 global.params.is64bit = true; | |
684 tt_arch = "x86_64"; | |
685 data_layout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:8"; | |
686 } | |
687 else if (strcmp(global.params.llvmArch,"ppc32")==0) { | |
688 VersionCondition::addPredefinedGlobalIdent("PPC"); | |
689 global.params.isLE = false; | |
690 global.params.is64bit = false; | |
691 tt_arch = "powerpc"; | |
692 data_layout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:8"; | |
693 } | |
694 else if (strcmp(global.params.llvmArch,"ppc64")==0) { | |
695 VersionCondition::addPredefinedGlobalIdent("PPC64"); | |
696 global.params.isLE = false; | |
697 global.params.is64bit = true; | |
698 tt_arch = "powerpc64"; | |
699 data_layout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:8"; | |
700 } | |
701 else { | |
702 assert(0 && "Invalid arch"); | |
703 } | |
704 | |
705 if (allowForceEndianness && global.params.forceBE) { | |
706 VersionCondition::addPredefinedGlobalIdent("BigEndian"); | |
707 global.params.isLE = false; | |
708 } | |
709 else if (global.params.isLE) { | |
710 VersionCondition::addPredefinedGlobalIdent("LittleEndian"); | |
711 } | |
712 else { | |
713 VersionCondition::addPredefinedGlobalIdent("BigEndian"); | |
714 } | |
715 | |
716 if (global.params.is64bit) { | |
717 VersionCondition::addPredefinedGlobalIdent("LLVM64"); | |
718 } | |
719 | |
720 assert(tt_arch != 0); | |
721 assert(tt_os != 0); | |
722 assert(data_layout != 0); | |
723 global.params.tt_arch = tt_arch; | |
724 global.params.tt_os = tt_os; | |
725 global.params.data_layout = data_layout; | |
726 | |
727 // Initialization | |
728 Type::init(); | |
729 Id::initialize(); | |
730 Module::init(); | |
731 initPrecedence(); | |
732 | |
733 backend_init(); | |
734 | |
735 //printf("%d source files\n",files.dim); | |
736 | |
737 // Build import search path | |
738 if (global.params.imppath) | |
739 { | |
740 for (i = 0; i < global.params.imppath->dim; i++) | |
741 { | |
742 char *path = (char *)global.params.imppath->data[i]; | |
743 Array *a = FileName::splitPath(path); | |
744 | |
745 if (a) | |
746 { | |
747 if (!global.path) | |
748 global.path = new Array(); | |
749 global.path->append(a); | |
750 } | |
751 } | |
752 } | |
753 | |
754 // Build string import search path | |
755 if (global.params.fileImppath) | |
756 { | |
757 for (i = 0; i < global.params.fileImppath->dim; i++) | |
758 { | |
759 char *path = (char *)global.params.fileImppath->data[i]; | |
760 Array *a = FileName::splitPath(path); | |
761 | |
762 if (a) | |
763 { | |
764 if (!global.filePath) | |
765 global.filePath = new Array(); | |
766 global.filePath->append(a); | |
767 } | |
768 } | |
769 } | |
770 | |
771 // Create Modules | |
772 Array modules; | |
773 modules.reserve(files.dim); | |
774 for (i = 0; i < files.dim; i++) | |
775 { Identifier *id; | |
776 char *ext; | |
777 char *name; | |
778 | |
779 p = (char *) files.data[i]; | |
780 | |
781 #if _WIN32 | |
782 // Convert / to \ so linker will work | |
783 for (int i = 0; p[i]; i++) | |
784 { | |
785 if (p[i] == '/') | |
786 p[i] = '\\'; | |
787 } | |
788 #endif | |
789 | |
790 p = FileName::name(p); // strip path | |
791 ext = FileName::ext(p); | |
792 if (ext) | |
793 { | |
794 #if IN_LLVM | |
795 if (strcmp(ext, global.nativeobj_ext) == 0 || | |
796 strcmp(ext, global.obj_ext) == 0) | |
797 #elif TARGET_LINUX | |
798 if (strcmp(ext, global.obj_ext) == 0) | |
799 #else | |
800 if (stricmp(ext, global.obj_ext) == 0) | |
801 #endif | |
802 { | |
803 global.params.objfiles->push(files.data[i]); | |
804 continue; | |
805 } | |
806 | |
807 #if !IN_LLVM | |
808 #if TARGET_LINUX | |
809 if (strcmp(ext, "a") == 0) | |
810 #else | |
811 if (stricmp(ext, "lib") == 0) | |
812 #endif | |
813 { | |
814 global.params.libfiles->push(files.data[i]); | |
815 continue; | |
816 } | |
817 #endif | |
818 | |
819 if (strcmp(ext, global.ddoc_ext) == 0) | |
820 { | |
821 global.params.ddocfiles->push(files.data[i]); | |
822 continue; | |
823 } | |
824 | |
825 #if !TARGET_LINUX | |
826 if (stricmp(ext, "res") == 0) | |
827 { | |
828 global.params.resfile = (char *)files.data[i]; | |
829 continue; | |
830 } | |
831 | |
832 if (stricmp(ext, "def") == 0) | |
833 { | |
834 global.params.deffile = (char *)files.data[i]; | |
835 continue; | |
836 } | |
837 | |
838 if (stricmp(ext, "exe") == 0) | |
839 { | |
840 global.params.exefile = (char *)files.data[i]; | |
841 continue; | |
842 } | |
843 #endif | |
844 | |
845 if (stricmp(ext, global.mars_ext) == 0 || | |
846 stricmp(ext, "htm") == 0 || | |
847 stricmp(ext, "html") == 0 || | |
848 stricmp(ext, "xhtml") == 0) | |
849 { | |
850 ext--; // skip onto '.' | |
851 assert(*ext == '.'); | |
852 name = (char *)mem.malloc((ext - p) + 1); | |
853 memcpy(name, p, ext - p); | |
854 name[ext - p] = 0; // strip extension | |
855 | |
856 if (name[0] == 0 || | |
857 strcmp(name, "..") == 0 || | |
858 strcmp(name, ".") == 0) | |
859 { | |
860 Linvalid: | |
861 error("invalid file name '%s'", (char *)files.data[i]); | |
862 fatal(); | |
863 } | |
864 } | |
865 else | |
866 { error("unrecognized file extension %s\n", ext); | |
867 fatal(); | |
868 } | |
869 } | |
870 else | |
871 { name = p; | |
872 if (!*name) | |
873 goto Linvalid; | |
874 } | |
875 | |
876 id = new Identifier(name, 0); | |
877 m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration); | |
878 modules.push(m); | |
879 | |
880 global.params.objfiles->push(m->objfile->name->str); | |
881 } | |
882 | |
883 #if _WIN32 | |
884 __try | |
885 { | |
886 #endif | |
887 // Read files, parse them | |
888 for (i = 0; i < modules.dim; i++) | |
889 { | |
890 m = (Module *)modules.data[i]; | |
891 if (global.params.verbose) | |
892 printf("parse %s\n", m->toChars()); | |
893 if (!Module::rootModule) | |
894 Module::rootModule = m; | |
895 m->importedFrom = m; | |
896 m->deleteObjFile(); | |
897 m->read(0); | |
898 m->parse(); | |
899 if (m->isDocFile) | |
900 { | |
901 m->gendocfile(); | |
902 | |
903 // Remove m from list of modules | |
904 modules.remove(i); | |
905 i--; | |
906 | |
907 // Remove m's object file from list of object files | |
908 for (int j = 0; j < global.params.objfiles->dim; j++) | |
909 { | |
910 if (m->objfile->name->str == global.params.objfiles->data[j]) | |
911 { | |
912 global.params.objfiles->remove(j); | |
913 break; | |
914 } | |
915 } | |
916 | |
917 if (global.params.objfiles->dim == 0) | |
918 global.params.link = 0; | |
919 } | |
920 } | |
921 if (global.errors) | |
922 fatal(); | |
923 #ifdef _DH | |
924 if (global.params.doHdrGeneration) | |
925 { | |
926 /* Generate 'header' import files. | |
927 * Since 'header' import files must be independent of command | |
928 * line switches and what else is imported, they are generated | |
929 * before any semantic analysis. | |
930 */ | |
931 for (i = 0; i < modules.dim; i++) | |
932 { | |
933 m = (Module *)modules.data[i]; | |
934 if (global.params.verbose) | |
935 printf("import %s\n", m->toChars()); | |
936 m->genhdrfile(); | |
937 } | |
938 } | |
939 if (global.errors) | |
940 fatal(); | |
941 #endif | |
942 | |
943 // Do semantic analysis | |
944 for (i = 0; i < modules.dim; i++) | |
945 { | |
946 m = (Module *)modules.data[i]; | |
947 if (global.params.verbose) | |
948 printf("semantic %s\n", m->toChars()); | |
949 m->semantic(); | |
950 } | |
951 if (global.errors) | |
952 fatal(); | |
953 | |
954 // Do pass 2 semantic analysis | |
955 for (i = 0; i < modules.dim; i++) | |
956 { | |
957 m = (Module *)modules.data[i]; | |
958 if (global.params.verbose) | |
959 printf("semantic2 %s\n", m->toChars()); | |
960 m->semantic2(); | |
961 } | |
962 if (global.errors) | |
963 fatal(); | |
964 | |
965 // Do pass 3 semantic analysis | |
966 for (i = 0; i < modules.dim; i++) | |
967 { | |
968 m = (Module *)modules.data[i]; | |
969 if (global.params.verbose) | |
970 printf("semantic3 %s\n", m->toChars()); | |
971 m->semantic3(); | |
972 } | |
973 if (global.errors) | |
974 fatal(); | |
975 | |
976 // Scan for functions to inline | |
977 if (global.params.useInline) | |
978 { | |
979 /* The problem with useArrayBounds and useAssert is that the | |
980 * module being linked to may not have generated them, so if | |
981 * we inline functions from those modules, the symbols for them will | |
982 * not be found at link time. | |
983 */ | |
984 if (!global.params.useArrayBounds && !global.params.useAssert) | |
985 { | |
986 // Do pass 3 semantic analysis on all imported modules, | |
987 // since otherwise functions in them cannot be inlined | |
988 for (i = 0; i < Module::amodules.dim; i++) | |
989 { | |
990 m = (Module *)Module::amodules.data[i]; | |
991 if (global.params.verbose) | |
992 printf("semantic3 %s\n", m->toChars()); | |
993 m->semantic3(); | |
994 } | |
995 if (global.errors) | |
996 fatal(); | |
997 } | |
998 | |
999 for (i = 0; i < modules.dim; i++) | |
1000 { | |
1001 m = (Module *)modules.data[i]; | |
1002 if (global.params.verbose) | |
1003 printf("inline scan %s\n", m->toChars()); | |
1004 m->inlineScan(); | |
1005 } | |
1006 } | |
1007 if (global.errors) | |
1008 fatal(); | |
1009 | |
1010 // Generate output files | |
1011 for (i = 0; i < modules.dim; i++) | |
1012 { | |
1013 m = (Module *)modules.data[i]; | |
1014 if (global.params.verbose) | |
1015 printf("code %s\n", m->toChars()); | |
1016 if (global.params.obj) | |
1017 m->genobjfile(); | |
1018 if (global.errors) | |
1019 m->deleteObjFile(); | |
1020 else | |
1021 { | |
1022 if (global.params.doDocComments) | |
1023 m->gendocfile(); | |
1024 } | |
1025 } | |
1026 #if _WIN32 | |
1027 } | |
1028 __except (__ehfilter(GetExceptionInformation())) | |
1029 { | |
1030 printf("Stack overflow\n"); | |
1031 fatal(); | |
1032 } | |
1033 #endif | |
1034 backend_term(); | |
1035 if (global.errors) | |
1036 fatal(); | |
1037 | |
1038 if (!global.params.objfiles->dim) | |
1039 { | |
1040 if (global.params.link) | |
1041 error("no object files to link"); | |
1042 } | |
1043 else | |
1044 { | |
1045 if (global.params.link) | |
1046 status = runLINK(); | |
1047 | |
1048 if (global.params.run) | |
1049 { | |
1050 if (!status) | |
1051 { | |
1052 status = runProgram(); | |
1053 | |
1054 /* Delete .obj files and .exe file | |
1055 */ | |
1056 for (i = 0; i < modules.dim; i++) | |
1057 { | |
1058 m = (Module *)modules.data[i]; | |
1059 m->deleteObjFile(); | |
1060 } | |
1061 deleteExeFile(); | |
1062 } | |
1063 } | |
1064 } | |
1065 | |
1066 return status; | |
1067 } | |
1068 | |
1069 | |
1070 | |
1071 /*********************************** | |
1072 * Parse and append contents of environment variable envvar | |
1073 * to argc and argv[]. | |
1074 * The string is separated into arguments, processing \ and ". | |
1075 */ | |
1076 | |
1077 void getenv_setargv(const char *envvar, int *pargc, char** *pargv) | |
1078 { | |
1079 char *env; | |
1080 char *p; | |
1081 Array *argv; | |
1082 int argc; | |
1083 | |
1084 int wildcard; // do wildcard expansion | |
1085 int instring; | |
1086 int slash; | |
1087 char c; | |
1088 int j; | |
1089 | |
1090 env = getenv(envvar); | |
1091 if (!env) | |
1092 return; | |
1093 | |
1094 env = mem.strdup(env); // create our own writable copy | |
1095 | |
1096 argc = *pargc; | |
1097 argv = new Array(); | |
1098 argv->setDim(argc); | |
1099 | |
1100 for (int i = 0; i < argc; i++) | |
1101 argv->data[i] = (void *)(*pargv)[i]; | |
1102 | |
1103 j = 1; // leave argv[0] alone | |
1104 while (1) | |
1105 { | |
1106 wildcard = 1; | |
1107 switch (*env) | |
1108 { | |
1109 case ' ': | |
1110 case '\t': | |
1111 env++; | |
1112 break; | |
1113 | |
1114 case 0: | |
1115 goto Ldone; | |
1116 | |
1117 case '"': | |
1118 wildcard = 0; | |
1119 default: | |
1120 argv->push(env); // append | |
1121 //argv->insert(j, env); // insert at position j | |
1122 j++; | |
1123 argc++; | |
1124 p = env; | |
1125 slash = 0; | |
1126 instring = 0; | |
1127 c = 0; | |
1128 | |
1129 while (1) | |
1130 { | |
1131 c = *env++; | |
1132 switch (c) | |
1133 { | |
1134 case '"': | |
1135 p -= (slash >> 1); | |
1136 if (slash & 1) | |
1137 { p--; | |
1138 goto Laddc; | |
1139 } | |
1140 instring ^= 1; | |
1141 slash = 0; | |
1142 continue; | |
1143 | |
1144 case ' ': | |
1145 case '\t': | |
1146 if (instring) | |
1147 goto Laddc; | |
1148 *p = 0; | |
1149 //if (wildcard) | |
1150 //wildcardexpand(); // not implemented | |
1151 break; | |
1152 | |
1153 case '\\': | |
1154 slash++; | |
1155 *p++ = c; | |
1156 continue; | |
1157 | |
1158 case 0: | |
1159 *p = 0; | |
1160 //if (wildcard) | |
1161 //wildcardexpand(); // not implemented | |
1162 goto Ldone; | |
1163 | |
1164 default: | |
1165 Laddc: | |
1166 slash = 0; | |
1167 *p++ = c; | |
1168 continue; | |
1169 } | |
1170 break; | |
1171 } | |
1172 } | |
1173 } | |
1174 | |
1175 Ldone: | |
1176 *pargc = argc; | |
1177 *pargv = (char **)argv->data; | |
1178 } | |
1179 | |
1180 #if _WIN32 | |
1181 | |
1182 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep) | |
1183 { | |
1184 //printf("%x\n", ep->ExceptionRecord->ExceptionCode); | |
1185 if (ep->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW) | |
1186 { | |
1187 #ifndef DEBUG | |
1188 return EXCEPTION_EXECUTE_HANDLER; | |
1189 #endif | |
1190 } | |
1191 return EXCEPTION_CONTINUE_SEARCH; | |
1192 } | |
1193 | |
1194 #endif |