Mercurial > projects > ldc
annotate dmd/module.c @ 323:0d52412d5b1a trunk
[svn r344] Fixed some very minor issues with the usage listing when calling llvmdc with no arguments.
Changed the way moduleinfo is registered to use the same approach as DMD, this eliminates the need for correct linking order and should make the way for using a natively compiled runtime library. This should speed up linking tremendously and should now be possible.
Fixed the llvm.used array to only be emitted if really necessary.
author | lindquist |
---|---|
date | Wed, 09 Jul 2008 23:43:51 +0200 |
parents | 297690b5d4a5 |
children | aaade6ded589 |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2007 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <assert.h> | |
14 | |
285
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
156
diff
changeset
|
15 #if _MSC_VER || __MINGW32__ |
1 | 16 #include <malloc.h> |
17 #endif | |
18 | |
19 #if IN_GCC | |
20 #include "gdc_alloca.h" | |
21 #endif | |
22 | |
23 #include "mem.h" | |
24 | |
25 #include "mars.h" | |
26 #include "module.h" | |
27 #include "parse.h" | |
28 #include "scope.h" | |
29 #include "identifier.h" | |
30 #include "id.h" | |
31 #include "import.h" | |
32 #include "dsymbol.h" | |
33 #include "hdrgen.h" | |
34 #include "lexer.h" | |
35 | |
36 #define MARS 1 | |
37 #include "html.h" | |
38 | |
39 #ifdef IN_GCC | |
40 #include "d-dmd-gcc.h" | |
41 #endif | |
42 | |
43 ClassDeclaration *Module::moduleinfo; | |
44 | |
45 Module *Module::rootModule; | |
46 DsymbolTable *Module::modules; | |
47 Array Module::amodules; | |
48 | |
49 Array Module::deferred; // deferred Dsymbol's needing semantic() run on them | |
50 unsigned Module::dprogress; | |
51 | |
52 void Module::init() | |
53 { | |
54 modules = new DsymbolTable(); | |
55 } | |
56 | |
57 Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen) | |
58 : Package(ident) | |
59 { | |
60 FileName *srcfilename; | |
61 FileName *cfilename; | |
62 FileName *hfilename; | |
63 FileName *objfilename; | |
64 FileName *llfilename; | |
65 FileName *bcfilename; | |
66 FileName *symfilename; | |
67 | |
68 // printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars()); | |
69 this->arg = filename; | |
70 md = NULL; | |
71 errors = 0; | |
72 numlines = 0; | |
73 members = NULL; | |
74 isHtml = 0; | |
75 isDocFile = 0; | |
76 needmoduleinfo = 0; | |
77 #ifdef IN_GCC | |
78 strictlyneedmoduleinfo = 0; | |
79 #endif | |
80 insearch = 0; | |
81 searchCacheIdent = NULL; | |
82 searchCacheSymbol = NULL; | |
83 searchCacheFlags = 0; | |
84 semanticstarted = 0; | |
85 semanticdone = 0; | |
86 decldefs = NULL; | |
87 vmoduleinfo = NULL; | |
88 massert = NULL; | |
89 marray = NULL; | |
130 | 90 sictor = NULL; |
1 | 91 sctor = NULL; |
92 sdtor = NULL; | |
93 stest = NULL; | |
94 sfilename = NULL; | |
95 root = 0; | |
96 importedFrom = NULL; | |
97 srcfile = NULL; | |
98 docfile = NULL; | |
99 | |
100 debuglevel = 0; | |
101 debugids = NULL; | |
102 debugidsNot = NULL; | |
103 versionlevel = 0; | |
104 versionids = NULL; | |
105 versionidsNot = NULL; | |
106 | |
107 macrotable = NULL; | |
108 escapetable = NULL; | |
109 cov = NULL; | |
110 covb = NULL; | |
111 | |
112 srcfilename = FileName::defaultExt(filename, global.mars_ext); | |
113 if (!srcfilename->equalsExt(global.mars_ext)) | |
114 { | |
115 if (srcfilename->equalsExt("html") || | |
116 srcfilename->equalsExt("htm") || | |
117 srcfilename->equalsExt("xhtml")) | |
118 isHtml = 1; | |
119 else | |
120 { error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext); | |
121 fatal(); | |
122 } | |
123 } | |
124 | |
125 char *argobj; | |
126 if (global.params.objname) | |
127 argobj = global.params.objname; | |
128 else if (global.params.preservePaths) | |
129 argobj = filename; | |
130 else | |
131 argobj = FileName::name(filename); | |
132 if (!FileName::absolute(argobj)) | |
133 { | |
134 argobj = FileName::combine(global.params.objdir, argobj); | |
135 } | |
136 | |
137 if (global.params.objname) | |
138 objfilename = new FileName(argobj, 0); | |
139 else | |
140 objfilename = FileName::forceExt(argobj, global.obj_ext); | |
141 | |
142 llfilename = FileName::forceExt(argobj, global.ll_ext); | |
143 bcfilename = FileName::forceExt(argobj, global.bc_ext); | |
144 | |
145 symfilename = FileName::forceExt(filename, global.sym_ext); | |
146 | |
147 srcfile = new File(srcfilename); | |
148 | |
149 if (doDocComment) | |
150 { | |
151 setDocfile(); | |
152 } | |
153 | |
154 if (doHdrGen) | |
155 { | |
156 setHdrfile(); | |
157 } | |
158 | |
159 objfile = new File(objfilename); | |
160 bcfile = new File(bcfilename); | |
52 | 161 llfile = new File(llfilename); |
1 | 162 symfile = new File(symfilename); |
163 } | |
164 | |
165 void Module::setDocfile() | |
166 { | |
167 FileName *docfilename; | |
168 char *argdoc; | |
169 | |
170 if (global.params.docname) | |
171 argdoc = global.params.docname; | |
172 else if (global.params.preservePaths) | |
173 argdoc = (char *)arg; | |
174 else | |
175 argdoc = FileName::name((char *)arg); | |
176 if (!FileName::absolute(argdoc)) | |
177 { //FileName::ensurePathExists(global.params.docdir); | |
178 argdoc = FileName::combine(global.params.docdir, argdoc); | |
179 } | |
180 if (global.params.docname) | |
181 docfilename = new FileName(argdoc, 0); | |
182 else | |
183 docfilename = FileName::forceExt(argdoc, global.doc_ext); | |
184 | |
185 if (docfilename->equals(srcfile->name)) | |
186 { error("Source file and documentation file have same name '%s'", srcfile->name->str); | |
187 fatal(); | |
188 } | |
189 | |
190 docfile = new File(docfilename); | |
191 } | |
192 | |
193 void Module::setHdrfile() | |
194 { | |
195 FileName *hdrfilename; | |
196 char *arghdr; | |
197 | |
198 if (global.params.hdrname) | |
199 arghdr = global.params.hdrname; | |
200 else if (global.params.preservePaths) | |
201 arghdr = (char *)arg; | |
202 else | |
203 arghdr = FileName::name((char *)arg); | |
204 if (!FileName::absolute(arghdr)) | |
205 { //FileName::ensurePathExists(global.params.hdrdir); | |
206 arghdr = FileName::combine(global.params.hdrdir, arghdr); | |
207 } | |
208 if (global.params.hdrname) | |
209 hdrfilename = new FileName(arghdr, 0); | |
210 else | |
211 hdrfilename = FileName::forceExt(arghdr, global.hdr_ext); | |
212 | |
213 if (hdrfilename->equals(srcfile->name)) | |
214 { error("Source file and 'header' file have same name '%s'", srcfile->name->str); | |
215 fatal(); | |
216 } | |
217 | |
218 hdrfile = new File(hdrfilename); | |
219 } | |
220 | |
221 void Module::deleteObjFile() | |
222 { | |
223 if (global.params.obj) | |
224 objfile->remove(); | |
225 //if (global.params.llvmBC) | |
226 bcfile->remove(); | |
227 if (docfile) | |
228 docfile->remove(); | |
229 } | |
230 | |
231 Module::~Module() | |
232 { | |
233 } | |
234 | |
235 char *Module::kind() | |
236 { | |
237 return "module"; | |
238 } | |
239 | |
240 Module *Module::load(Loc loc, Array *packages, Identifier *ident) | |
241 { Module *m; | |
242 char *filename; | |
243 | |
244 //printf("Module::load(ident = '%s')\n", ident->toChars()); | |
245 | |
246 // Build module filename by turning: | |
247 // foo.bar.baz | |
248 // into: | |
249 // foo\bar\baz | |
250 filename = ident->toChars(); | |
251 if (packages && packages->dim) | |
252 { | |
253 OutBuffer buf; | |
254 int i; | |
255 | |
256 for (i = 0; i < packages->dim; i++) | |
257 { Identifier *pid = (Identifier *)packages->data[i]; | |
258 | |
259 buf.writestring(pid->toChars()); | |
260 #if _WIN32 | |
261 buf.writeByte('\\'); | |
262 #else | |
263 buf.writeByte('/'); | |
264 #endif | |
265 } | |
266 buf.writestring(filename); | |
267 buf.writeByte(0); | |
268 filename = (char *)buf.extractData(); | |
269 } | |
270 | |
271 m = new Module(filename, ident, 0, 0); | |
272 m->loc = loc; | |
273 | |
274 /* Search along global.path for .di file, then .d file. | |
275 */ | |
276 char *result = NULL; | |
277 FileName *fdi = FileName::forceExt(filename, global.hdr_ext); | |
278 FileName *fd = FileName::forceExt(filename, global.mars_ext); | |
279 char *sdi = fdi->toChars(); | |
280 char *sd = fd->toChars(); | |
281 | |
282 if (FileName::exists(sdi)) | |
283 result = sdi; | |
284 else if (FileName::exists(sd)) | |
285 result = sd; | |
286 else if (FileName::absolute(filename)) | |
287 ; | |
288 else if (!global.path) | |
289 ; | |
290 else | |
291 { | |
292 for (size_t i = 0; i < global.path->dim; i++) | |
293 { | |
294 char *p = (char *)global.path->data[i]; | |
295 char *n = FileName::combine(p, sdi); | |
296 if (FileName::exists(n)) | |
297 { result = n; | |
298 break; | |
299 } | |
300 mem.free(n); | |
301 n = FileName::combine(p, sd); | |
302 if (FileName::exists(n)) | |
303 { result = n; | |
304 break; | |
305 } | |
306 mem.free(n); | |
307 } | |
308 } | |
309 if (result) | |
310 m->srcfile = new File(result); | |
311 | |
312 if (global.params.verbose) | |
313 { | |
314 printf("import "); | |
315 if (packages) | |
316 { | |
317 for (size_t i = 0; i < packages->dim; i++) | |
318 { Identifier *pid = (Identifier *)packages->data[i]; | |
319 printf("%s.", pid->toChars()); | |
320 } | |
321 } | |
322 printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); | |
323 } | |
324 | |
325 m->read(loc); | |
326 m->parse(); | |
327 | |
328 #ifdef IN_GCC | |
329 d_gcc_magic_module(m); | |
330 #endif | |
331 | |
332 return m; | |
333 } | |
334 | |
335 void Module::read(Loc loc) | |
336 { | |
337 //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); | |
338 if (srcfile->read()) | |
339 { error(loc, "cannot read file '%s'", srcfile->toChars()); | |
340 fatal(); | |
341 } | |
342 } | |
343 | |
344 inline unsigned readwordLE(unsigned short *p) | |
345 { | |
346 #if __I86__ | |
347 return *p; | |
348 #else | |
349 return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0]; | |
350 #endif | |
351 } | |
352 | |
353 inline unsigned readwordBE(unsigned short *p) | |
354 { | |
355 return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1]; | |
356 } | |
357 | |
358 inline unsigned readlongLE(unsigned *p) | |
359 { | |
360 #if __I86__ | |
361 return *p; | |
362 #else | |
363 return ((unsigned char *)p)[0] | | |
364 (((unsigned char *)p)[1] << 8) | | |
365 (((unsigned char *)p)[2] << 16) | | |
366 (((unsigned char *)p)[3] << 24); | |
367 #endif | |
368 } | |
369 | |
370 inline unsigned readlongBE(unsigned *p) | |
371 { | |
372 return ((unsigned char *)p)[3] | | |
373 (((unsigned char *)p)[2] << 8) | | |
374 (((unsigned char *)p)[1] << 16) | | |
375 (((unsigned char *)p)[0] << 24); | |
376 } | |
377 | |
378 #if IN_GCC | |
379 void Module::parse(bool dump_source) | |
380 #else | |
381 void Module::parse() | |
382 #endif | |
383 { char *srcname; | |
384 unsigned char *buf; | |
385 unsigned buflen; | |
386 unsigned le; | |
387 unsigned bom; | |
388 | |
389 //printf("Module::parse()\n"); | |
390 | |
391 srcname = srcfile->name->toChars(); | |
392 //printf("Module::parse(srcname = '%s')\n", srcname); | |
393 | |
394 buf = srcfile->buffer; | |
395 buflen = srcfile->len; | |
396 | |
397 if (buflen >= 2) | |
398 { | |
399 /* Convert all non-UTF-8 formats to UTF-8. | |
400 * BOM : http://www.unicode.org/faq/utf_bom.html | |
401 * 00 00 FE FF UTF-32BE, big-endian | |
402 * FF FE 00 00 UTF-32LE, little-endian | |
403 * FE FF UTF-16BE, big-endian | |
404 * FF FE UTF-16LE, little-endian | |
405 * EF BB BF UTF-8 | |
406 */ | |
407 | |
408 bom = 1; // assume there's a BOM | |
409 if (buf[0] == 0xFF && buf[1] == 0xFE) | |
410 { | |
411 if (buflen >= 4 && buf[2] == 0 && buf[3] == 0) | |
412 { // UTF-32LE | |
413 le = 1; | |
414 | |
415 Lutf32: | |
416 OutBuffer dbuf; | |
417 unsigned *pu = (unsigned *)(buf); | |
418 unsigned *pumax = &pu[buflen / 4]; | |
419 | |
420 if (buflen & 3) | |
421 { error("odd length of UTF-32 char source %u", buflen); | |
422 fatal(); | |
423 } | |
424 | |
425 dbuf.reserve(buflen / 4); | |
426 for (pu += bom; pu < pumax; pu++) | |
427 { unsigned u; | |
428 | |
429 u = le ? readlongLE(pu) : readlongBE(pu); | |
430 if (u & ~0x7F) | |
431 { | |
432 if (u > 0x10FFFF) | |
433 { error("UTF-32 value %08x greater than 0x10FFFF", u); | |
434 fatal(); | |
435 } | |
436 dbuf.writeUTF8(u); | |
437 } | |
438 else | |
439 dbuf.writeByte(u); | |
440 } | |
441 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
442 buflen = dbuf.offset - 1; // don't include sentinel in count | |
443 buf = (unsigned char *) dbuf.extractData(); | |
444 } | |
445 else | |
446 { // UTF-16LE (X86) | |
447 // Convert it to UTF-8 | |
448 le = 1; | |
449 | |
450 Lutf16: | |
451 OutBuffer dbuf; | |
452 unsigned short *pu = (unsigned short *)(buf); | |
453 unsigned short *pumax = &pu[buflen / 2]; | |
454 | |
455 if (buflen & 1) | |
456 { error("odd length of UTF-16 char source %u", buflen); | |
457 fatal(); | |
458 } | |
459 | |
460 dbuf.reserve(buflen / 2); | |
461 for (pu += bom; pu < pumax; pu++) | |
462 { unsigned u; | |
463 | |
464 u = le ? readwordLE(pu) : readwordBE(pu); | |
465 if (u & ~0x7F) | |
466 { if (u >= 0xD800 && u <= 0xDBFF) | |
467 { unsigned u2; | |
468 | |
469 if (++pu > pumax) | |
470 { error("surrogate UTF-16 high value %04x at EOF", u); | |
471 fatal(); | |
472 } | |
473 u2 = le ? readwordLE(pu) : readwordBE(pu); | |
474 if (u2 < 0xDC00 || u2 > 0xDFFF) | |
475 { error("surrogate UTF-16 low value %04x out of range", u2); | |
476 fatal(); | |
477 } | |
478 u = (u - 0xD7C0) << 10; | |
479 u |= (u2 - 0xDC00); | |
480 } | |
481 else if (u >= 0xDC00 && u <= 0xDFFF) | |
482 { error("unpaired surrogate UTF-16 value %04x", u); | |
483 fatal(); | |
484 } | |
485 else if (u == 0xFFFE || u == 0xFFFF) | |
486 { error("illegal UTF-16 value %04x", u); | |
487 fatal(); | |
488 } | |
489 dbuf.writeUTF8(u); | |
490 } | |
491 else | |
492 dbuf.writeByte(u); | |
493 } | |
494 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
495 buflen = dbuf.offset - 1; // don't include sentinel in count | |
496 buf = (unsigned char *) dbuf.extractData(); | |
497 } | |
498 } | |
499 else if (buf[0] == 0xFE && buf[1] == 0xFF) | |
500 { // UTF-16BE | |
501 le = 0; | |
502 goto Lutf16; | |
503 } | |
504 else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) | |
505 { // UTF-32BE | |
506 le = 0; | |
507 goto Lutf32; | |
508 } | |
509 else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) | |
510 { // UTF-8 | |
511 | |
512 buf += 3; | |
513 buflen -= 3; | |
514 } | |
515 else | |
516 { | |
517 /* There is no BOM. Make use of Arcane Jill's insight that | |
518 * the first char of D source must be ASCII to | |
519 * figure out the encoding. | |
520 */ | |
521 | |
522 bom = 0; | |
523 if (buflen >= 4) | |
524 { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0) | |
525 { // UTF-32LE | |
526 le = 1; | |
527 goto Lutf32; | |
528 } | |
529 else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) | |
530 { // UTF-32BE | |
531 le = 0; | |
532 goto Lutf32; | |
533 } | |
534 } | |
535 if (buflen >= 2) | |
536 { | |
537 if (buf[1] == 0) | |
538 { // UTF-16LE | |
539 le = 1; | |
540 goto Lutf16; | |
541 } | |
542 else if (buf[0] == 0) | |
543 { // UTF-16BE | |
544 le = 0; | |
545 goto Lutf16; | |
546 } | |
547 } | |
548 | |
549 // It's UTF-8 | |
550 if (buf[0] >= 0x80) | |
551 { error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]); | |
552 fatal(); | |
553 } | |
554 } | |
555 } | |
556 | |
557 #ifdef IN_GCC | |
558 // dump utf-8 encoded source | |
559 if (dump_source) | |
560 { // %% srcname could contain a path ... | |
561 d_gcc_dump_source(srcname, "utf-8", buf, buflen); | |
562 } | |
563 #endif | |
564 | |
565 /* If it starts with the string "Ddoc", then it's a documentation | |
566 * source file. | |
567 */ | |
568 if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0) | |
569 { | |
570 comment = buf + 4; | |
571 isDocFile = 1; | |
572 if (!docfile) | |
573 setDocfile(); | |
574 return; | |
575 } | |
576 if (isHtml) | |
577 { | |
578 OutBuffer *dbuf = new OutBuffer(); | |
579 Html h(srcname, buf, buflen); | |
580 h.extractCode(dbuf); | |
581 buf = dbuf->data; | |
582 buflen = dbuf->offset; | |
583 #ifdef IN_GCC | |
584 // dump extracted source | |
585 if (dump_source) | |
586 d_gcc_dump_source(srcname, "d.utf-8", buf, buflen); | |
587 #endif | |
588 } | |
589 Parser p(this, buf, buflen, docfile != NULL); | |
590 p.nextToken(); | |
591 members = p.parseModule(); | |
592 md = p.md; | |
593 numlines = p.loc.linnum; | |
594 | |
595 DsymbolTable *dst; | |
596 | |
597 if (md) | |
598 { this->ident = md->id; | |
599 dst = Package::resolve(md->packages, &this->parent, NULL); | |
600 } | |
601 else | |
602 { | |
603 dst = modules; | |
604 | |
605 /* Check to see if module name is a valid identifier | |
606 */ | |
607 if (!Lexer::isValidIdentifier(this->ident->toChars())) | |
608 error("has non-identifier characters in filename, use module declaration instead"); | |
609 } | |
610 | |
611 // Update global list of modules | |
612 if (!dst->insert(this)) | |
613 { | |
614 if (md) | |
615 error(loc, "is in multiple packages %s", md->toChars()); | |
616 else | |
617 error(loc, "is in multiple defined"); | |
618 } | |
619 else | |
620 { | |
621 amodules.push(this); | |
622 } | |
623 } | |
624 | |
625 void Module::semantic() | |
626 { int i; | |
627 | |
628 if (semanticstarted) | |
629 return; | |
630 | |
631 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
632 semanticstarted = 1; | |
633 | |
634 // Note that modules get their own scope, from scratch. | |
635 // This is so regardless of where in the syntax a module | |
636 // gets imported, it is unaffected by context. | |
637 Scope *sc = Scope::createGlobal(this); // create root scope | |
638 | |
639 //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); | |
640 | |
641 // Add import of "object" if this module isn't "object" | |
642 if (ident != Id::object) | |
643 { | |
644 Import *im = new Import(0, NULL, Id::object, NULL, 0); | |
645 members->shift(im); | |
646 } | |
647 | |
648 // Add all symbols into module's symbol table | |
649 symtab = new DsymbolTable(); | |
650 for (i = 0; i < members->dim; i++) | |
651 { Dsymbol *s; | |
652 | |
653 s = (Dsymbol *)members->data[i]; | |
654 s->addMember(NULL, sc->scopesym, 1); | |
655 } | |
656 | |
657 // Pass 1 semantic routines: do public side of the definition | |
658 for (i = 0; i < members->dim; i++) | |
659 { Dsymbol *s; | |
660 | |
661 s = (Dsymbol *)members->data[i]; | |
662 //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); | |
663 s->semantic(sc); | |
664 runDeferredSemantic(); | |
665 } | |
666 | |
667 sc = sc->pop(); | |
668 sc->pop(); | |
669 semanticdone = semanticstarted; | |
670 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
671 } | |
672 | |
673 void Module::semantic2() | |
674 { int i; | |
675 | |
676 if (deferred.dim) | |
677 { | |
678 for (int i = 0; i < deferred.dim; i++) | |
679 { | |
680 Dsymbol *sd = (Dsymbol *)deferred.data[i]; | |
681 | |
682 sd->error("unable to resolve forward reference in definition"); | |
683 } | |
684 return; | |
685 } | |
686 //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); | |
687 if (semanticstarted >= 2) | |
688 return; | |
689 assert(semanticstarted == 1); | |
690 semanticstarted = 2; | |
691 | |
692 // Note that modules get their own scope, from scratch. | |
693 // This is so regardless of where in the syntax a module | |
694 // gets imported, it is unaffected by context. | |
695 Scope *sc = Scope::createGlobal(this); // create root scope | |
696 //printf("Module = %p\n", sc.scopesym); | |
697 | |
698 // Pass 2 semantic routines: do initializers and function bodies | |
699 for (i = 0; i < members->dim; i++) | |
700 { Dsymbol *s; | |
701 | |
702 s = (Dsymbol *)members->data[i]; | |
703 s->semantic2(sc); | |
704 } | |
705 | |
706 sc = sc->pop(); | |
707 sc->pop(); | |
708 semanticdone = semanticstarted; | |
709 //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); | |
710 } | |
711 | |
712 void Module::semantic3() | |
713 { int i; | |
714 | |
715 //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent); | |
716 if (semanticstarted >= 3) | |
717 return; | |
718 assert(semanticstarted == 2); | |
719 semanticstarted = 3; | |
720 | |
721 // Note that modules get their own scope, from scratch. | |
722 // This is so regardless of where in the syntax a module | |
723 // gets imported, it is unaffected by context. | |
724 Scope *sc = Scope::createGlobal(this); // create root scope | |
725 //printf("Module = %p\n", sc.scopesym); | |
726 | |
727 // Pass 3 semantic routines: do initializers and function bodies | |
728 for (i = 0; i < members->dim; i++) | |
729 { Dsymbol *s; | |
730 | |
731 s = (Dsymbol *)members->data[i]; | |
732 //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars()); | |
733 s->semantic3(sc); | |
734 } | |
735 | |
736 sc = sc->pop(); | |
737 sc->pop(); | |
738 semanticdone = semanticstarted; | |
739 } | |
740 | |
741 void Module::inlineScan() | |
742 { int i; | |
743 | |
744 if (semanticstarted >= 4) | |
745 return; | |
746 assert(semanticstarted == 3); | |
747 semanticstarted = 4; | |
748 | |
749 // Note that modules get their own scope, from scratch. | |
750 // This is so regardless of where in the syntax a module | |
751 // gets imported, it is unaffected by context. | |
752 //printf("Module = %p\n", sc.scopesym); | |
753 | |
754 for (i = 0; i < members->dim; i++) | |
755 { Dsymbol *s; | |
756 | |
757 s = (Dsymbol *)members->data[i]; | |
758 //if (global.params.verbose) | |
759 //printf("inline scan symbol %s\n", s->toChars()); | |
760 | |
761 s->inlineScan(); | |
762 } | |
763 semanticdone = semanticstarted; | |
764 } | |
765 | |
766 /**************************************************** | |
767 */ | |
768 | |
769 void Module::gensymfile() | |
770 { | |
771 OutBuffer buf; | |
772 HdrGenState hgs; | |
773 int i; | |
774 | |
775 //printf("Module::gensymfile()\n"); | |
776 | |
777 buf.printf("// Sym file generated from '%s'", srcfile->toChars()); | |
778 buf.writenl(); | |
779 | |
780 for (i = 0; i < members->dim; i++) | |
781 { | |
782 Dsymbol *s; | |
783 | |
784 s = (Dsymbol *)members->data[i]; | |
785 s->toCBuffer(&buf, &hgs); | |
786 } | |
787 | |
788 // Transfer image to file | |
789 symfile->setbuffer(buf.data, buf.offset); | |
790 buf.data = NULL; | |
791 | |
792 symfile->writev(); | |
793 } | |
794 | |
795 /********************************** | |
796 * Determine if we need to generate an instance of ModuleInfo | |
797 * for this Module. | |
798 */ | |
799 | |
800 int Module::needModuleInfo() | |
801 { | |
802 return needmoduleinfo || global.params.cov; | |
803 } | |
804 | |
805 Dsymbol *Module::search(Loc loc, Identifier *ident, int flags) | |
806 { | |
807 /* Since modules can be circularly referenced, | |
808 * need to stop infinite recursive searches. | |
809 */ | |
810 | |
811 //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch); | |
812 Dsymbol *s; | |
813 if (insearch) | |
814 s = NULL; | |
815 else if (searchCacheIdent == ident && searchCacheFlags == flags) | |
816 s = searchCacheSymbol; | |
817 else | |
818 { | |
819 insearch = 1; | |
820 s = ScopeDsymbol::search(loc, ident, flags); | |
821 insearch = 0; | |
822 | |
823 searchCacheIdent = ident; | |
824 searchCacheSymbol = s; | |
825 searchCacheFlags = flags; | |
826 } | |
827 return s; | |
828 } | |
829 | |
830 /******************************************* | |
831 * Can't run semantic on s now, try again later. | |
832 */ | |
833 | |
834 void Module::addDeferredSemantic(Dsymbol *s) | |
835 { | |
836 // Don't add it if it is already there | |
837 for (int i = 0; i < deferred.dim; i++) | |
838 { | |
839 Dsymbol *sd = (Dsymbol *)deferred.data[i]; | |
840 | |
841 if (sd == s) | |
842 return; | |
843 } | |
844 | |
845 //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); | |
846 deferred.push(s); | |
847 } | |
848 | |
849 | |
850 /****************************************** | |
851 * Run semantic() on deferred symbols. | |
852 */ | |
853 | |
854 void Module::runDeferredSemantic() | |
855 { | |
856 size_t len; | |
857 | |
858 static int nested; | |
859 if (nested) | |
860 return; | |
861 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); | |
862 nested++; | |
863 | |
864 do | |
865 { | |
866 dprogress = 0; | |
867 len = deferred.dim; | |
868 if (!len) | |
869 break; | |
870 | |
871 Dsymbol **todo; | |
872 Dsymbol *tmp; | |
873 if (len == 1) | |
874 { | |
875 todo = &tmp; | |
876 } | |
877 else | |
878 { | |
879 todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *)); | |
880 assert(todo); | |
881 } | |
882 memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); | |
883 deferred.setDim(0); | |
884 | |
885 for (int i = 0; i < len; i++) | |
886 { | |
887 Dsymbol *s = todo[i]; | |
888 | |
889 s->semantic(NULL); | |
890 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars()); | |
891 } | |
892 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress); | |
893 } while (deferred.dim < len || dprogress); // while making progress | |
894 nested--; | |
895 //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); | |
896 } | |
897 | |
898 /* =========================== ModuleDeclaration ===================== */ | |
899 | |
900 ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id) | |
901 { | |
902 this->packages = packages; | |
903 this->id = id; | |
904 } | |
905 | |
906 char *ModuleDeclaration::toChars() | |
907 { | |
908 OutBuffer buf; | |
909 int i; | |
910 | |
911 if (packages && packages->dim) | |
912 { | |
913 for (i = 0; i < packages->dim; i++) | |
914 { Identifier *pid = (Identifier *)packages->data[i]; | |
915 | |
916 buf.writestring(pid->toChars()); | |
917 buf.writeByte('.'); | |
918 } | |
919 } | |
920 buf.writestring(id->toChars()); | |
921 buf.writeByte(0); | |
922 return (char *)buf.extractData(); | |
923 } | |
924 | |
925 /* =========================== Package ===================== */ | |
926 | |
927 Package::Package(Identifier *ident) | |
928 : ScopeDsymbol(ident) | |
929 { | |
930 } | |
931 | |
932 | |
933 char *Package::kind() | |
934 { | |
935 return "package"; | |
936 } | |
937 | |
938 | |
939 DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg) | |
940 { | |
941 DsymbolTable *dst = Module::modules; | |
942 Dsymbol *parent = NULL; | |
943 | |
944 //printf("Package::resolve()\n"); | |
945 if (ppkg) | |
946 *ppkg = NULL; | |
947 | |
948 if (packages) | |
949 { int i; | |
950 | |
951 for (i = 0; i < packages->dim; i++) | |
952 { Identifier *pid = (Identifier *)packages->data[i]; | |
953 Dsymbol *p; | |
954 | |
955 p = dst->lookup(pid); | |
956 if (!p) | |
957 { | |
958 p = new Package(pid); | |
959 dst->insert(p); | |
960 p->parent = parent; | |
961 ((ScopeDsymbol *)p)->symtab = new DsymbolTable(); | |
962 } | |
963 else | |
964 { | |
965 assert(p->isPackage()); | |
966 if (p->isModule()) | |
967 { p->error("module and package have the same name"); | |
968 fatal(); | |
969 break; | |
970 } | |
971 } | |
972 parent = p; | |
973 dst = ((Package *)p)->symtab; | |
974 if (ppkg && !*ppkg) | |
975 *ppkg = (Package *)p; | |
976 } | |
977 if (pparent) | |
978 { | |
979 *pparent = parent; | |
980 } | |
981 } | |
982 return dst; | |
983 } |