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