Mercurial > projects > ddmd
annotate dmd/Module.d @ 176:fa9a71a9f5a8
Moved all the mutable globals to Global
author | korDen |
---|---|
date | Sun, 10 Oct 2010 05:22:45 +0400 |
parents | af724d3510d7 |
children | e3afd1303184 |
rev | line source |
---|---|
0 | 1 module dmd.Module; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Package; |
5 import dmd.DsymbolTable; | |
6 import dmd.backend.TYM; | |
7 import dmd.Array; | |
8 import dmd.StaticDtorDeclaration; | |
9 import dmd.Scope; | |
10 import dmd.Id; | |
11 import dmd.Import; | |
12 import dmd.ClassDeclaration; | |
13 import dmd.ModuleDeclaration; | |
14 import dmd.File; | |
15 import dmd.Identifier; | |
79 | 16 import dmd.Json; |
0 | 17 import dmd.Dsymbol; |
18 import dmd.ModuleInfoDeclaration; | |
19 import dmd.FuncDeclaration; | |
20 import dmd.Loc; | |
21 import dmd.Macro; | |
22 import dmd.Escape; | |
23 import dmd.OutBuffer; | |
24 import dmd.HdrGenState; | |
25 import dmd.ArrayTypes; | |
26 import dmd.FileName; | |
27 import dmd.Global; | |
28 import dmd.Parser; | |
29 import dmd.Lexer; | |
30 import dmd.Util; | |
31 import dmd.String; | |
32 import dmd.ScopeDsymbol; | |
33 import dmd.Type; | |
34 import dmd.backend.TYPE; | |
35 import dmd.backend.Cstate; | |
36 import dmd.backend.OPER; | |
37 import dmd.backend.REG; | |
38 import dmd.backend.Symbol; | |
39 import dmd.backend.elem; | |
40 import dmd.backend.mTYman; | |
41 import dmd.backend.Util; | |
42 import dmd.backend.SC; | |
43 import dmd.backend.FL; | |
44 import dmd.backend.SFL; | |
45 import dmd.backend.TF; | |
46 import dmd.backend.RTLSYM; | |
47 import dmd.backend.BC; | |
48 import dmd.backend.block; | |
49 import dmd.backend.targ_types; | |
50 import dmd.backend.dt_t; | |
51 import dmd.backend.TYM; | |
52 import dmd.backend.Util; | |
53 import dmd.backend.Classsym; | |
54 import dmd.backend.glue; | |
55 import dmd.backend.LIST; | |
56 import dmd.codegen.Util; | |
57 | |
58 import core.stdc.string; | |
59 import core.stdc.stdlib; | |
60 | |
4 | 61 import core.memory; |
2 | 62 |
0 | 63 uint readwordLE(ushort* p) |
64 { | |
65 version (__I86__) { | |
66 return *p; | |
67 } else { | |
68 return ((cast(ubyte*)p)[1] << 8) | (cast(ubyte*)p)[0]; | |
69 } | |
70 } | |
71 | |
72 uint readwordBE(ushort* p) | |
73 { | |
74 return ((cast(ubyte*)p)[0] << 8) | (cast(ubyte*)p)[1]; | |
75 } | |
76 | |
77 uint readlongLE(uint* p) | |
78 { | |
79 version (__I86__) { | |
80 return *p; | |
81 } else { | |
82 return (cast(ubyte*)p)[0] | | |
83 ((cast(ubyte*)p)[1] << 8) | | |
84 ((cast(ubyte*)p)[2] << 16) | | |
85 ((cast(ubyte*)p)[3] << 24); | |
86 } | |
87 } | |
88 | |
89 uint readlongBE(uint* p) | |
90 { | |
91 return (cast(ubyte*)p)[3] | | |
92 ((cast(ubyte*)p)[2] << 8) | | |
93 ((cast(ubyte*)p)[1] << 16) | | |
94 ((cast(ubyte*)p)[0] << 24); | |
95 } | |
96 | |
97 /* Segments */ | |
98 enum Segment { | |
99 CODE = 1, /* code segment */ | |
100 DATA = 2, /* initialized data */ | |
101 CDATA = 3, /* constant data */ | |
102 UDATA = 4, /* uninitialized data */ | |
103 UNKNOWN = -1, /* unknown segment */ | |
104 } | |
105 | |
174 | 106 struct seg_data |
0 | 107 { |
108 int SDseg; // omf file segment index | |
109 targ_size_t SDoffset; // starting offset for data | |
110 | |
111 bool isfarseg; | |
112 int seg; // segment number | |
113 int lnameidx; // lname idx of segment name | |
114 int classidx; // lname idx of class name | |
115 uint attr; // segment attribute | |
116 targ_size_t origsize; // original size | |
117 int seek; // seek position in output file | |
118 } | |
119 | |
120 extern (C) extern __gshared seg_data** SegData; | |
121 | |
122 ref targ_size_t Offset(Segment seg) { | |
123 return SegData[seg].SDoffset; | |
124 } | |
125 | |
126 ref targ_size_t Doffset() { | |
127 return SegData[Segment.DATA].SDoffset; | |
128 } | |
129 | |
130 ref targ_size_t CDoffset() { | |
131 return SegData[Segment.CDATA].SDoffset; | |
132 } | |
133 | |
134 ref targ_size_t UDoffset() { | |
135 return SegData[Segment.UDATA].SDoffset; | |
136 } | |
137 | |
138 enum CF { | |
139 CFes = 1, // generate an ES: segment override for this instr | |
140 CFjmp16 = 2, // need 16 bit jump offset (long branch) | |
141 CFtarg = 4, // this code is the target of a jump | |
142 CFseg = 8, // get segment of immediate value | |
143 CFoff = 0x10, // get offset of immediate value | |
144 CFss = 0x20, // generate an SS: segment override (not with | |
145 // CFes at the same time, though!) | |
146 CFpsw = 0x40, // we need the flags result after this instruction | |
147 CFopsize = 0x80, // prefix with operand size | |
148 CFaddrsize = 0x100, // prefix with address size | |
174 | 149 CFds = 0x200, // need DS override (not with es, ss, or cs ) |
0 | 150 CFcs = 0x400, // need CS override |
151 CFfs = 0x800, // need FS override | |
152 CFgs = (CFcs | CFfs), // need GS override | |
153 CFwait = 0x1000, // If I32 it indicates when to output a WAIT | |
154 CFselfrel = 0x2000, // if self-relative | |
155 CFunambig = 0x4000, // indicates cannot be accessed by other addressing | |
156 // modes | |
157 CFtarg2 = 0x8000, // like CFtarg, but we can't optimize this away | |
158 CFvolatile = 0x10000, // volatile reference, do not schedule | |
159 CFclassinit = 0x20000, // class init code | |
160 | |
161 CFSEG = (CFes | CFss | CFds | CFcs | CFfs | CFgs), | |
162 CFPREFIX = (CFSEG | CFopsize | CFaddrsize), | |
163 } | |
164 | |
165 class Module : Package | |
166 { | |
167 string arg; // original argument name | |
168 ModuleDeclaration md; // if !null, the contents of the ModuleDeclaration declaration | |
169 File srcfile; // input source file | |
170 File objfile; // output .obj file | |
171 File hdrfile; // 'header' file | |
172 File symfile; // output symbol file | |
173 File docfile; // output documentation file | |
174 uint errors; // if any errors in file | |
175 uint numlines; // number of lines in source file | |
176 int isHtml; // if it is an HTML file | |
177 int isDocFile; // if it is a documentation input file, not D source | |
178 int needmoduleinfo; /// TODO: change to bool | |
179 version (IN_GCC) { | |
180 int strictlyneedmoduleinfo; | |
181 } | |
182 | |
183 int selfimports; // 0: don't know, 1: does not, 2: does | |
184 int selfImports() // returns !=0 if module imports itself | |
185 { | |
186 assert(false); | |
187 } | |
188 | |
189 int insearch; | |
190 Identifier searchCacheIdent; | |
191 Dsymbol searchCacheSymbol; // cached value of search | |
192 int searchCacheFlags; // cached flags | |
193 | |
194 int semanticstarted; // has semantic() been started? | |
195 int semanticRun; // has semantic() been done? | |
196 int root; // != 0 if this is a 'root' module, | |
197 // i.e. a module that will be taken all the | |
198 // way to an object file | |
199 Module importedFrom; // module from command line we're imported from, | |
200 // i.e. a module that will be taken all the | |
201 // way to an object file | |
202 | |
203 Array decldefs; // top level declarations for this Module | |
204 | |
205 Array aimports; // all imported modules | |
206 | |
207 ModuleInfoDeclaration vmoduleinfo; | |
208 | |
209 uint debuglevel; // debug level | |
129 | 210 Vector!string debugids; // debug identifiers |
211 Vector!string debugidsNot; // forward referenced debug identifiers | |
0 | 212 |
213 uint versionlevel; // version level | |
214 Array versionids; // version identifiers | |
215 Array versionidsNot; // forward referenced version identifiers | |
216 | |
217 Macro macrotable; // document comment macros | |
218 Escape escapetable; // document comment escapes | |
219 bool safe; // TRUE if module is marked as 'safe' | |
220 | |
221 this(string filename, Identifier ident, int doDocComment, int doHdrGen) | |
222 { | |
223 super(ident); | |
224 FileName objfilename; | |
174 | 225 |
0 | 226 aimports = new Array(); |
227 | |
174 | 228 //writefln("Module.Module(filename = '%s', ident = '%s')", filename, ident.toChars()); |
0 | 229 this.arg = filename; |
230 | |
231 FileName srcfilename = FileName.defaultExt(filename, global.mars_ext); | |
232 if (!srcfilename.equalsExt(global.mars_ext) && | |
233 !srcfilename.equalsExt(global.hdr_ext) && | |
234 !srcfilename.equalsExt("dd")) | |
235 { | |
236 if (srcfilename.equalsExt("html") || | |
237 srcfilename.equalsExt("htm") || | |
238 srcfilename.equalsExt("xhtml")) | |
239 { | |
240 if (!global.params.useDeprecated) | |
241 error("html source files is deprecated %s", srcfilename.toChars()); | |
242 isHtml = 1; | |
243 } | |
244 else | |
245 { | |
246 error("source file name '%s' must have .%s extension", srcfilename.toChars(), global.mars_ext); | |
247 fatal(); | |
248 } | |
249 } | |
250 | |
251 string argobj; | |
252 if (global.params.objname) | |
253 argobj = global.params.objname; | |
254 else if (global.params.preservePaths) | |
255 argobj = filename; | |
256 else | |
257 argobj = FileName.name(filename); | |
258 if (!FileName.absolute(argobj)) | |
259 { | |
260 argobj = FileName.combine(global.params.objdir, argobj); | |
261 } | |
262 | |
263 if (global.params.objname) | |
264 objfilename = new FileName(argobj); | |
265 else | |
266 objfilename = FileName.forceExt(argobj, global.obj_ext); | |
267 | |
268 FileName symfilename = FileName.forceExt(filename, global.sym_ext); | |
269 | |
174 | 270 //writeln(srcfilename.toChars()); |
0 | 271 srcfile = new File(srcfilename); |
272 | |
273 if (doDocComment) { | |
274 setDocfile(); | |
275 } | |
276 | |
277 if (doHdrGen) { | |
278 setHdrfile(); | |
279 } | |
280 | |
281 objfile = new File(objfilename); | |
282 symfile = new File(symfilename); | |
283 } | |
284 | |
129 | 285 static Module load(Loc loc, Vector!Identifier packages, Identifier ident) |
0 | 286 { |
287 Module m; | |
288 string filename; | |
289 | |
290 //writef("Module.load(ident = '%s')\n", ident.toChars()); | |
291 | |
292 // Build module filename by turning: | |
293 // foo.bar.baz | |
294 // into: | |
295 // foo\bar\baz | |
296 filename = ident.toChars(); | |
297 if (packages && packages.dim) | |
298 { | |
129 | 299 scope OutBuffer buf = new OutBuffer(); |
0 | 300 |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
301 foreach (pid; packages) |
174 | 302 { |
0 | 303 buf.writestring(pid.toChars()); |
114 | 304 version (Windows) |
305 { | |
0 | 306 buf.writeByte('\\'); |
114 | 307 } |
308 else | |
309 { | |
0 | 310 buf.writeByte('/'); |
311 } | |
312 } | |
313 buf.writestring(filename); | |
314 filename = buf.extractString(); | |
315 } | |
316 | |
317 m = new Module(filename, ident, 0, 0); | |
318 m.loc = loc; | |
319 | |
320 /* Search along global.path for .di file, then .d file. | |
321 */ | |
322 string result = null; | |
323 FileName fdi = FileName.forceExt(filename, global.hdr_ext); | |
324 FileName fd = FileName.forceExt(filename, global.mars_ext); | |
325 string sdi = fdi.toChars(); | |
326 string sd = fd.toChars(); | |
174 | 327 |
0 | 328 if (FileName.exists(sdi)) { |
329 result = sdi; | |
330 } else if (FileName.exists(sd)) { | |
331 result = sd; | |
332 } else if (FileName.absolute(filename)) { | |
333 ; | |
334 } | |
335 else | |
336 { | |
337 foreach (p; global.path) | |
338 { | |
339 string n = FileName.combine(p, sdi); | |
340 | |
341 if (FileName.exists(n)) | |
342 { | |
343 result = n; | |
344 break; | |
345 } | |
346 | |
347 n = FileName.combine(p, sd); | |
348 if (FileName.exists(n)) | |
349 { | |
350 result = n; | |
351 break; | |
352 } | |
353 } | |
354 } | |
355 | |
174 | 356 if (result) { |
357 writeln("loading ", result); | |
0 | 358 m.srcfile = new File(result); |
174 | 359 } |
0 | 360 |
361 if (global.params.verbose) | |
362 { | |
363 writef("import "); | |
364 if (packages) | |
365 { | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
366 foreach (pid; packages) |
174 | 367 { |
0 | 368 writef("%s.", pid.toChars()); |
369 } | |
370 } | |
371 writef("%s\t(%s)\n", ident.toChars(), m.srcfile.toChars()); | |
372 } | |
373 | |
374 m.read(loc); | |
375 m.parse(); | |
376 | |
377 version (IN_GCC) { | |
378 d_gcc_magic_module(m); | |
379 } | |
380 | |
381 return m; | |
382 } | |
383 | |
72 | 384 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 385 { |
386 assert(false); | |
387 } | |
174 | 388 |
79 | 389 override void toJsonBuffer(OutBuffer buf) |
390 { | |
96 | 391 buf.writestring("{\n"); |
79 | 392 |
96 | 393 if (md) |
394 JsonProperty(buf, Pname, md.toChars()); | |
79 | 395 |
96 | 396 JsonProperty(buf, Pkind, kind()); |
79 | 397 |
96 | 398 JsonProperty(buf, Pfile, srcfile.toChars()); |
79 | 399 |
96 | 400 if (comment) |
401 JsonProperty(buf, Pcomment, comment); | |
79 | 402 |
96 | 403 JsonString(buf, Pmembers); |
404 buf.writestring(" : [\n"); | |
79 | 405 |
96 | 406 size_t offset = buf.offset; |
407 foreach (Dsymbol s; members) | |
408 { | |
409 if (offset != buf.offset) | |
410 { | |
411 buf.writestring(",\n"); | |
412 offset = buf.offset; | |
413 } | |
414 s.toJsonBuffer(buf); | |
415 } | |
79 | 416 |
96 | 417 JsonRemoveComma(buf); |
418 buf.writestring("]\n"); | |
79 | 419 |
96 | 420 buf.writestring("}\n"); |
421 } | |
174 | 422 |
72 | 423 override string kind() |
0 | 424 { |
425 return "module"; | |
426 } | |
174 | 427 |
0 | 428 void setDocfile() // set docfile member |
429 { | |
430 assert(false); | |
431 } | |
174 | 432 |
0 | 433 void read(Loc loc) // read file |
434 { | |
174 | 435 //writefln("Module.read('%s') file '%s'", toChars(), srcfile.toChars()); |
0 | 436 if (srcfile.read()) |
437 { | |
438 error(loc, "cannot read file '%s'", srcfile.toChars()); | |
439 fatal(); | |
440 } | |
441 } | |
174 | 442 |
0 | 443 version (IN_GCC) { |
444 void parse(bool dump_source = false) // syntactic parse | |
445 { | |
446 assert(false); | |
447 } | |
448 } else { | |
449 void parse() // syntactic parse | |
450 { | |
451 uint le; | |
452 uint bom; | |
453 | |
454 //printf("Module.parse()\n"); | |
455 | |
456 string srcname = srcfile.name.toChars(); | |
457 //printf("Module.parse(srcname = '%s')\n", srcname); | |
458 | |
459 ubyte* buf = srcfile.buffer; | |
460 uint buflen = srcfile.len; | |
461 | |
462 if (buflen >= 2) | |
463 { | |
464 /* Convert all non-UTF-8 formats to UTF-8. | |
465 * BOM : http://www.unicode.org/faq/utf_bom.html | |
466 * 00 00 FE FF UTF-32BE, big-endian | |
467 * FF FE 00 00 UTF-32LE, little-endian | |
468 * FE FF UTF-16BE, big-endian | |
469 * FF FE UTF-16LE, little-endian | |
470 * EF BB BF UTF-8 | |
471 */ | |
472 | |
473 bom = 1; // assume there's a BOM | |
474 if (buf[0] == 0xFF && buf[1] == 0xFE) | |
475 { | |
476 if (buflen >= 4 && buf[2] == 0 && buf[3] == 0) | |
477 { // UTF-32LE | |
478 le = 1; | |
479 | |
480 Lutf32: | |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
14
diff
changeset
|
481 OutBuffer dbuf = new OutBuffer(); |
0 | 482 uint* pu = cast(uint*)buf; |
483 uint* pumax = &pu[buflen / 4]; | |
484 | |
485 if (buflen & 3) | |
486 { error("odd length of UTF-32 char source %u", buflen); | |
487 fatal(); | |
488 } | |
489 | |
490 dbuf.reserve(buflen / 4); | |
491 for (pu += bom; pu < pumax; pu++) | |
174 | 492 { |
0 | 493 uint u = le ? readlongLE(pu) : readlongBE(pu); |
494 if (u & ~0x7F) | |
495 { | |
496 if (u > 0x10FFFF) | |
497 { error("UTF-32 value %08x greater than 0x10FFFF", u); | |
498 fatal(); | |
499 } | |
500 dbuf.writeUTF8(u); | |
501 } | |
502 else | |
503 dbuf.writeByte(u); | |
504 } | |
505 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
506 buflen = dbuf.offset - 1; // don't include sentinel in count | |
507 buf = cast(ubyte*) dbuf.extractData(); | |
508 } | |
509 else | |
174 | 510 { |
0 | 511 // UTF-16LE (X86) |
512 // Convert it to UTF-8 | |
513 le = 1; | |
514 | |
515 Lutf16: | |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
14
diff
changeset
|
516 OutBuffer dbuf = new OutBuffer(); |
0 | 517 ushort* pu = cast(ushort*)(buf); |
518 ushort *pumax = &pu[buflen / 2]; | |
519 | |
520 if (buflen & 1) | |
521 { error("odd length of UTF-16 char source %u", buflen); | |
522 fatal(); | |
523 } | |
524 | |
525 dbuf.reserve(buflen / 2); | |
526 for (pu += bom; pu < pumax; pu++) | |
527 { | |
528 uint u = le ? readwordLE(pu) : readwordBE(pu); | |
529 if (u & ~0x7F) | |
530 { | |
531 if (u >= 0xD800 && u <= 0xDBFF) | |
532 { uint u2; | |
533 | |
534 if (++pu > pumax) | |
535 { error("surrogate UTF-16 high value %04x at EOF", u); | |
536 fatal(); | |
537 } | |
538 u2 = le ? readwordLE(pu) : readwordBE(pu); | |
539 if (u2 < 0xDC00 || u2 > 0xDFFF) | |
540 { error("surrogate UTF-16 low value %04x out of range", u2); | |
541 fatal(); | |
542 } | |
543 u = (u - 0xD7C0) << 10; | |
544 u |= (u2 - 0xDC00); | |
545 } | |
546 else if (u >= 0xDC00 && u <= 0xDFFF) | |
547 { | |
548 error("unpaired surrogate UTF-16 value %04x", u); | |
549 fatal(); | |
550 } | |
551 else if (u == 0xFFFE || u == 0xFFFF) | |
552 { | |
553 error("illegal UTF-16 value %04x", u); | |
554 fatal(); | |
555 } | |
556 dbuf.writeUTF8(u); | |
557 } | |
558 else | |
559 dbuf.writeByte(u); | |
560 } | |
561 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
562 buflen = dbuf.offset - 1; // don't include sentinel in count | |
563 buf = cast(ubyte*) dbuf.extractData(); | |
564 } | |
565 } | |
566 else if (buf[0] == 0xFE && buf[1] == 0xFF) | |
567 { // UTF-16BE | |
568 le = 0; | |
569 goto Lutf16; | |
570 } | |
571 else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) | |
572 { // UTF-32BE | |
573 le = 0; | |
574 goto Lutf32; | |
575 } | |
576 else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) | |
577 { // UTF-8 | |
578 | |
579 buf += 3; | |
580 buflen -= 3; | |
581 } | |
582 else | |
583 { | |
584 /* There is no BOM. Make use of Arcane Jill's insight that | |
585 * the first char of D source must be ASCII to | |
586 * figure out the encoding. | |
587 */ | |
588 | |
589 bom = 0; | |
590 if (buflen >= 4) | |
591 { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0) | |
592 { // UTF-32LE | |
593 le = 1; | |
594 goto Lutf32; | |
595 } | |
596 else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) | |
597 { // UTF-32BE | |
598 le = 0; | |
599 goto Lutf32; | |
600 } | |
601 } | |
602 if (buflen >= 2) | |
603 { | |
604 if (buf[1] == 0) | |
605 { // UTF-16LE | |
606 le = 1; | |
607 goto Lutf16; | |
608 } | |
609 else if (buf[0] == 0) | |
610 { // UTF-16BE | |
611 le = 0; | |
612 goto Lutf16; | |
613 } | |
614 } | |
615 | |
616 // It's UTF-8 | |
617 if (buf[0] >= 0x80) | |
618 { error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]); | |
619 fatal(); | |
620 } | |
621 } | |
622 } | |
623 | |
624 version (IN_GCC) { | |
174 | 625 // dump utf-8 encoded source |
0 | 626 if (dump_source) |
627 { // %% srcname could contain a path ... | |
628 d_gcc_dump_source(srcname, "utf-8", buf, buflen); | |
629 } | |
630 } | |
631 | |
632 /* If it starts with the string "Ddoc", then it's a documentation | |
633 * source file. | |
634 */ | |
635 if (buflen >= 4 && memcmp(buf, "Ddoc".ptr, 4) == 0) | |
636 { | |
79 | 637 comment = cast(string) ((buf + 4)[0 .. buflen]); |
0 | 638 isDocFile = 1; |
639 if (!docfile) | |
640 setDocfile(); | |
641 return; | |
642 } | |
643 if (isHtml) | |
644 { | |
645 assert(false); | |
646 ///OutBuffer dbuf = new OutBuffer(); | |
647 ///Html h = new Html(srcname, buf, buflen); | |
648 ///h.extractCode(dbuf); | |
649 ///buf = dbuf.data; | |
650 ///buflen = dbuf.offset; | |
651 | |
79 | 652 version (IN_GCC) |
653 { | |
0 | 654 // dump extracted source |
655 ///if (dump_source) | |
656 /// d_gcc_dump_source(srcname, "d.utf-8", buf, buflen); | |
657 } | |
658 } | |
659 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
660 auto p = new Parser(this, buf, buflen, docfile !is null); |
0 | 661 p.nextToken(); |
662 members = p.parseModule(); | |
663 md = p.md; | |
664 numlines = p.loc.linnum; | |
665 | |
666 DsymbolTable dst; | |
667 | |
668 if (md !is null) | |
669 { | |
670 this.ident = md.id; | |
671 this.safe = md.safe; | |
672 dst = super.resolve(md.packages, &this.parent, null); | |
673 } | |
674 else | |
675 { | |
169 | 676 dst = global.modules; |
0 | 677 |
678 /* Check to see if module name is a valid identifier | |
679 */ | |
680 if (!Lexer.isValidIdentifier(this.ident.toChars())) | |
681 error("has non-identifier characters in filename, use module declaration instead"); | |
682 } | |
174 | 683 |
0 | 684 // Update global list of modules |
685 if (!dst.insert(this)) | |
686 { | |
687 if (md) | |
688 error(loc, "is in multiple packages %s", md.toChars()); | |
689 else | |
690 error(loc, "is in multiple defined"); | |
691 } | |
692 else | |
693 { | |
169 | 694 global.amodules.push(cast(void*)this); |
0 | 695 } |
696 } | |
697 } | |
698 | |
79 | 699 override void importAll(Scope prevsc) |
700 { | |
701 //writef("+Module.importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
174 | 702 |
79 | 703 if (scope_ !is null) |
704 return; // already done | |
705 | |
706 /* Note that modules get their own scope, from scratch. | |
707 * This is so regardless of where in the syntax a module | |
708 * gets imported, it is unaffected by context. | |
709 * Ignore prevsc. | |
710 */ | |
711 Scope sc = Scope.createGlobal(this); // create root scope | |
174 | 712 |
79 | 713 // Add import of "object" if this module isn't "object" |
714 if (ident != Id.object) | |
715 { | |
716 if (members.dim == 0 || members[0].ident != Id.object) | |
717 { | |
718 Import im = new Import(Loc(), null, Id.object, null, 0); | |
719 members.shift(im); | |
720 } | |
721 } | |
722 | |
723 if (!symtab) | |
724 { | |
725 // Add all symbols into module's symbol table | |
726 symtab = new DsymbolTable(); | |
727 foreach (Dsymbol s; members) | |
728 s.addMember(null, sc.scopesym, 1); | |
729 } | |
730 // anything else should be run after addMember, so version/debug symbols are defined | |
174 | 731 |
79 | 732 /* Set scope for the symbols so that if we forward reference |
733 * a symbol, it can possibly be resolved on the spot. | |
734 * If this works out well, it can be extended to all modules | |
735 * before any semantic() on any of them. | |
736 */ | |
737 setScope(sc); // remember module scope for semantic | |
738 foreach (Dsymbol s; members) | |
739 s.setScope(sc); | |
174 | 740 |
79 | 741 foreach (Dsymbol s; members) |
742 s.importAll(sc); | |
174 | 743 |
79 | 744 sc = sc.pop(); |
745 sc.pop(); // 2 pops because Scope::createGlobal() created 2 | |
746 } | |
747 | |
0 | 748 void semantic() // semantic analysis |
749 { | |
750 if (semanticstarted) | |
751 return; | |
752 | |
753 //printf("+Module.semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
754 semanticstarted = 1; | |
755 | |
756 // Note that modules get their own scope, from scratch. | |
757 // This is so regardless of where in the syntax a module | |
758 // gets imported, it is unaffected by context. | |
79 | 759 Scope sc = scope_; // // see if already got one from importAll() |
760 if (!sc) | |
761 { | |
762 writef("test2\n"); | |
763 Scope.createGlobal(this); // create root scope | |
764 } | |
0 | 765 |
79 | 766 //writef("Module = %p, linkage = %d\n", sc.scopesym, sc.linkage); |
0 | 767 |
79 | 768 static if (false) |
769 { | |
0 | 770 // Add import of "object" if this module isn't "object" |
771 if (ident !is Id.object) | |
772 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
773 auto im = new Import(Loc(0), null, Id.object, null, 0); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
774 members.shift(im); |
0 | 775 } |
776 | |
777 // Add all symbols into module's symbol table | |
778 symtab = new DsymbolTable(); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
779 foreach(s; members) |
174 | 780 { |
13 | 781 s.addMember(null, sc.scopesym, true); |
0 | 782 } |
783 | |
784 /* Set scope for the symbols so that if we forward reference | |
785 * a symbol, it can possibly be resolved on the spot. | |
786 * If this works out well, it can be extended to all modules | |
787 * before any semantic() on any of them. | |
788 */ | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
789 foreach(Dsymbol s; members) |
0 | 790 s.setScope(sc); |
79 | 791 } |
0 | 792 |
793 // Pass 1 semantic routines: do public side of the definition | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
794 foreach (Dsymbol s; members) |
174 | 795 { |
0 | 796 //writef("\tModule('%s'): '%s'.semantic()\n", toChars(), s.toChars()); |
797 s.semantic(sc); | |
798 runDeferredSemantic(); | |
799 } | |
800 | |
79 | 801 if (!scope_) |
802 { | |
803 sc = sc.pop(); | |
804 sc.pop(); // 2 pops because Scope.createGlobal() created 2 | |
805 } | |
0 | 806 semanticRun = semanticstarted; |
807 //printf("-Module.semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
808 } | |
174 | 809 |
0 | 810 void semantic2() // pass 2 semantic analysis |
811 { | |
169 | 812 auto deferred = global.deferred; |
0 | 813 if (deferred.dim) |
814 { | |
815 for (int i = 0; i < deferred.dim; i++) | |
816 { | |
817 Dsymbol sd = cast(Dsymbol)deferred.data[i]; | |
818 | |
819 sd.error("unable to resolve forward reference in definition"); | |
820 } | |
821 return; | |
822 } | |
823 //printf("Module.semantic2('%s'): parent = %p\n", toChars(), parent); | |
824 if (semanticstarted >= 2) | |
825 return; | |
826 assert(semanticstarted == 1); | |
827 semanticstarted = 2; | |
828 | |
829 // Note that modules get their own scope, from scratch. | |
830 // This is so regardless of where in the syntax a module | |
831 // gets imported, it is unaffected by context. | |
832 Scope sc = Scope.createGlobal(this); // create root scope | |
833 //printf("Module = %p\n", sc.scopesym); | |
834 | |
835 // Pass 2 semantic routines: do initializers and function bodies | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
836 foreach(Dsymbol s; members) |
0 | 837 s.semantic2(sc); |
838 | |
839 sc = sc.pop(); | |
840 sc.pop(); | |
841 semanticRun = semanticstarted; | |
842 //printf("-Module.semantic2('%s'): parent = %p\n", toChars(), parent); | |
843 } | |
174 | 844 |
0 | 845 void semantic3() // pass 3 semantic analysis |
846 { | |
847 //printf("Module.semantic3('%s'): parent = %p\n", toChars(), parent); | |
848 if (semanticstarted >= 3) | |
849 return; | |
850 assert(semanticstarted == 2); | |
851 semanticstarted = 3; | |
852 | |
853 // Note that modules get their own scope, from scratch. | |
854 // This is so regardless of where in the syntax a module | |
855 // gets imported, it is unaffected by context. | |
856 Scope sc = Scope.createGlobal(this); // create root scope | |
857 //printf("Module = %p\n", sc.scopesym); | |
858 | |
859 // Pass 3 semantic routines: do initializers and function bodies | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
860 foreach(Dsymbol s; members) |
174 | 861 { |
0 | 862 //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars()); |
863 s.semantic3(sc); | |
864 } | |
865 | |
866 sc = sc.pop(); | |
867 sc.pop(); | |
868 semanticRun = semanticstarted; | |
869 } | |
174 | 870 |
72 | 871 override void inlineScan() // scan for functions to inline |
0 | 872 { |
873 if (semanticstarted >= 4) | |
874 return; | |
875 | |
876 assert(semanticstarted == 3); | |
877 semanticstarted = 4; | |
878 | |
879 // Note that modules get their own scope, from scratch. | |
880 // This is so regardless of where in the syntax a module | |
881 // gets imported, it is unaffected by context. | |
882 //printf("Module = %p\n", sc.scopesym); | |
883 | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
884 foreach(Dsymbol s; members) |
174 | 885 { |
0 | 886 //if (global.params.verbose) |
887 //printf("inline scan symbol %s\n", s.toChars()); | |
888 s.inlineScan(); | |
889 } | |
890 | |
891 semanticRun = semanticstarted; | |
892 } | |
174 | 893 |
0 | 894 void setHdrfile() // set hdrfile member |
895 { | |
896 FileName hdrfilename; | |
897 string arghdr; | |
898 | |
899 if (global.params.hdrname) | |
900 arghdr = global.params.hdrname; | |
901 else if (global.params.preservePaths) | |
902 arghdr = arg; | |
903 else | |
904 arghdr = FileName.name(arg); | |
905 if (!FileName.absolute(arghdr)) | |
174 | 906 { |
0 | 907 //FileName.ensurePathExists(global.params.hdrdir); |
908 arghdr = FileName.combine(global.params.hdrdir, arghdr); | |
909 } | |
910 if (global.params.hdrname) | |
911 hdrfilename = new FileName(arghdr); | |
912 else | |
913 hdrfilename = FileName.forceExt(arghdr, global.hdr_ext); | |
914 | |
915 if (hdrfilename.str == srcfile.name.str) | |
174 | 916 { |
0 | 917 error("Source file and 'header' file have same name '%s'", srcfile.name.str); |
918 fatal(); | |
919 } | |
920 | |
921 hdrfile = new File(hdrfilename); | |
922 } | |
174 | 923 |
0 | 924 version (_DH) { |
925 void genhdrfile() // generate D import file | |
926 { | |
927 assert(false); | |
928 } | |
929 } | |
174 | 930 |
0 | 931 /************************************** |
932 * Generate .obj file for Module. | |
933 */ | |
934 void genobjfile(int multiobj) | |
935 { | |
936 //EEcontext *ee = env.getEEcontext(); | |
937 | |
938 //printf("Module.genobjfile(multiobj = %d) %s\n", multiobj, toChars()); | |
939 | |
176 | 940 auto lastmname = global.lastmname = srcfile.toChars(); |
0 | 941 |
942 obj_initfile(toStringz(lastmname), null, toStringz(toPrettyChars())); | |
943 | |
176 | 944 global.eictor = null; |
945 global.ictorlocalgot = null; | |
946 global.ector = null; | |
947 global.ectorgates.setDim(0); | |
948 global.edtor = null; | |
949 global.etest = null; | |
950 global.dtorcount = 0; | |
0 | 951 |
952 if (doppelganger) | |
953 { | |
954 /* Generate a reference to the moduleinfo, so the module constructors | |
955 * and destructors get linked in. | |
956 */ | |
957 Module m = cast(Module)aimports.data[0]; | |
958 assert(m); | |
959 if (m.sictor || m.sctor || m.sdtor) | |
960 { | |
961 Symbol* s = m.toSymbol(); | |
962 //objextern(s); | |
963 //if (!s.Sxtrnnum) objextdef(s.Sident); | |
964 if (!s.Sxtrnnum) | |
965 { | |
966 //printf("%s\n", s.Sident); | |
967 static if (false) { | |
968 /* This should work, but causes optlink to fail in common/newlib.asm */ | |
969 objextdef(s.Sident); | |
970 } else { | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
971 version (ELFOBJ_OR_MACHOBJ) {///ELFOBJ || MACHOBJ |
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
972 int nbytes = reftoident(Segment.DATA, Offset(Segment.DATA), s, 0, CF.CFoff); |
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
973 Offset(Segment.DATA) += nbytes; |
0 | 974 } else { |
975 int nbytes = reftoident(Segment.DATA, Doffset, s, 0, CF.CFoff); | |
976 Doffset() += nbytes; | |
977 } | |
978 } | |
979 } | |
980 } | |
981 } | |
982 | |
983 if (global.params.cov) | |
984 { | |
985 /* Create coverage identifier: | |
986 * private uint[numlines] __coverage; | |
987 */ | |
988 cov = symbol_calloc("__coverage"); | |
989 cov.Stype = type_fake(TYM.TYint); | |
990 cov.Stype.Tmangle = mTYman.mTYman_c; | |
991 cov.Stype.Tcount++; | |
992 cov.Sclass = SC.SCstatic; | |
993 cov.Sfl = FL.FLdata; | |
994 version (ELFOBJ_OR_MACHOBJ) { | |
995 cov.Sseg = Segment.UDATA; | |
996 } | |
997 dtnzeros(&cov.Sdt, 4 * numlines); | |
998 outdata(cov); | |
999 slist_add(cov); | |
1000 | |
4 | 1001 covb = cast(uint*)GC.calloc(((numlines + 32) / 32) * (*covb).sizeof); |
0 | 1002 } |
174 | 1003 |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
1004 foreach(Dsymbol member; members) |
0 | 1005 member.toObjFile(multiobj); |
174 | 1006 |
0 | 1007 if (global.params.cov) |
1008 { | |
1009 /* Generate | |
1010 * bit[numlines] __bcoverage; | |
1011 */ | |
1012 Symbol* bcov = symbol_calloc("__bcoverage"); | |
1013 bcov.Stype = type_fake(TYM.TYuint); | |
1014 bcov.Stype.Tcount++; | |
1015 bcov.Sclass = SC.SCstatic; | |
1016 bcov.Sfl = FL.FLdata; | |
1017 version (ELFOBJ_OR_MACHOBJ) { | |
1018 bcov.Sseg = Segment.DATA; | |
1019 } | |
1020 dtnbytes(&bcov.Sdt, (numlines + 32) / 32 * (*covb).sizeof, cast(char*)covb); | |
1021 outdata(bcov); | |
1022 | |
2 | 1023 ///free(covb); |
0 | 1024 covb = null; |
1025 | |
1026 /* Generate: | |
1027 * _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename); | |
1028 * and prepend it to the static constructor. | |
1029 */ | |
1030 | |
1031 /* t will be the type of the functions generated: | |
1032 * extern (C) void func(); | |
1033 */ | |
1034 type* t = type_alloc(TYM.TYnfunc); | |
1035 t.Tflags |= TF.TFprototype | TF.TFfixed; | |
1036 t.Tmangle = mTYman.mTYman_c; | |
1037 t.Tnext = tsvoid; | |
1038 tsvoid.Tcount++; | |
1039 | |
1040 sictor = toSymbolX("__modictor", SC.SCglobal, t, "FZv"); | |
1041 cstate.CSpsymtab = &sictor.Sfunc.Flocsym; | |
176 | 1042 global.localgot = global.ictorlocalgot; |
0 | 1043 elem* e; |
1044 | |
1045 e = el_params(el_ptr(cov), el_long(TYM.TYuint, numlines), | |
1046 el_ptr(bcov), el_long(TYM.TYuint, numlines), | |
1047 toEfilename(), | |
1048 null); | |
1049 e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_DCOVER]), e); | |
176 | 1050 global.eictor = el_combine(e, global.eictor); |
1051 global.ictorlocalgot = global.localgot; | |
0 | 1052 } |
1053 | |
1054 // If coverage / static constructor / destructor / unittest calls | |
176 | 1055 if (global.eictor || global.ector || global.ectorgates.dim || global.edtor || global.etest) |
0 | 1056 { |
1057 /* t will be the type of the functions generated: | |
1058 * extern (C) void func(); | |
1059 */ | |
1060 type* t = type_alloc(TYM.TYnfunc); | |
1061 t.Tflags |= TF.TFprototype | TF.TFfixed; | |
1062 t.Tmangle = mTYman.mTYman_c; | |
1063 t.Tnext = tsvoid; | |
1064 tsvoid.Tcount++; | |
1065 | |
170 | 1066 enum moddeco = "FZv"; |
0 | 1067 |
176 | 1068 if (global.eictor) |
0 | 1069 { |
176 | 1070 global.localgot = global.ictorlocalgot; |
0 | 1071 |
1072 block* b = block_calloc(); | |
1073 b.BC = BC.BCret; | |
176 | 1074 b.Belem = global.eictor; |
0 | 1075 sictor.Sfunc.Fstartblock = b; |
1076 writefunc(sictor); | |
1077 } | |
1078 | |
176 | 1079 if (global.ector || global.ectorgates.dim) |
0 | 1080 { |
176 | 1081 global.localgot = null; |
0 | 1082 sctor = toSymbolX("__modctor", SC.SCglobal, t, moddeco); |
1083 cstate.CSpsymtab = &sctor.Sfunc.Flocsym; | |
1084 | |
176 | 1085 for (int i = 0; i < global.ectorgates.dim; i++) |
174 | 1086 { |
176 | 1087 StaticDtorDeclaration f = cast(StaticDtorDeclaration)global.ectorgates.data[i]; |
0 | 1088 |
1089 Symbol* s = f.vgate.toSymbol(); | |
1090 elem* e = el_var(s); | |
1091 e = el_bin(OPER.OPaddass, TYM.TYint, e, el_long(TYM.TYint, 1)); | |
176 | 1092 global.ector = el_combine(global.ector, e); |
0 | 1093 } |
1094 | |
1095 block* b = block_calloc(); | |
1096 b.BC = BC.BCret; | |
176 | 1097 b.Belem = global.ector; |
0 | 1098 sctor.Sfunc.Fstartblock = b; |
1099 writefunc(sctor); | |
1100 version (STATICCTOR) { | |
1101 obj_staticctor(sctor, dtorcount, 1); | |
1102 } | |
1103 } | |
1104 | |
176 | 1105 if (global.edtor) |
0 | 1106 { |
176 | 1107 global.localgot = null; |
0 | 1108 sdtor = toSymbolX("__moddtor", SC.SCglobal, t, moddeco); |
1109 | |
1110 block* b = block_calloc(); | |
1111 b.BC = BC.BCret; | |
176 | 1112 b.Belem = global.edtor; |
0 | 1113 sdtor.Sfunc.Fstartblock = b; |
1114 writefunc(sdtor); | |
1115 } | |
1116 | |
176 | 1117 if (global.etest) |
0 | 1118 { |
176 | 1119 global.localgot = null; |
0 | 1120 stest = toSymbolX("__modtest", SC.SCglobal, t, moddeco); |
1121 | |
1122 block* b = block_calloc(); | |
1123 b.BC = BC.BCret; | |
176 | 1124 b.Belem = global.etest; |
0 | 1125 stest.Sfunc.Fstartblock = b; |
1126 writefunc(stest); | |
1127 } | |
1128 | |
1129 if (doppelganger) | |
1130 genmoduleinfo(); | |
1131 } | |
1132 | |
1133 if (doppelganger) | |
1134 { | |
1135 obj_termfile(); | |
1136 return; | |
1137 } | |
1138 | |
1139 if (global.params.multiobj) | |
1140 { /* This is necessary because the main .obj for this module is written | |
1141 * first, but determining whether marray or massert are needed is done | |
1142 * possibly later in the doppelganger modules. | |
1143 * Another way to fix it is do the main one last. | |
1144 */ | |
1145 toModuleAssert(); | |
1146 toModuleArray(); | |
1147 } | |
1148 | |
1149 // If module assert | |
1150 for (int i = 0; i < 2; i++) | |
1151 { | |
1152 Symbol* ma = i ? marray : massert; | |
1153 | |
1154 if (ma) | |
1155 { | |
1156 elem* elinnum; | |
1157 elem* efilename; | |
1158 | |
176 | 1159 global.localgot = null; |
0 | 1160 |
1161 // Call dassert(filename, line) | |
1162 // Get sole parameter, linnum | |
1163 { | |
1164 Symbol* sp; | |
1165 | |
1166 sp = symbol_calloc("linnum".ptr); | |
1167 sp.Stype = type_fake(TYM.TYint); | |
1168 sp.Stype.Tcount++; | |
1169 sp.Sclass = SC.SCfastpar; | |
1170 sp.Spreg = REG.AX; | |
1171 sp.Sflags &= ~SFL.SFLspill; | |
1172 sp.Sfl = FL.FLpara; // FLauto? | |
1173 cstate.CSpsymtab = &ma.Sfunc.Flocsym; | |
1174 symbol_add(sp); | |
1175 | |
1176 elinnum = el_var(sp); | |
1177 } | |
1178 | |
1179 efilename = toEmodulename(); | |
1180 | |
1181 elem *e = el_var(rtlsym[i ? RTLSYM.RTLSYM_DARRAY : RTLSYM.RTLSYM_DASSERT]); | |
1182 e = el_bin(OPER.OPcall, TYM.TYvoid, e, el_param(elinnum, efilename)); | |
1183 | |
1184 block* b = block_calloc(); | |
1185 b.BC = BC.BCret; | |
1186 b.Belem = e; | |
1187 ma.Sfunc.Fstartblock = b; | |
1188 ma.Sclass = SC.SCglobal; | |
1189 ma.Sfl = 0; | |
1190 writefunc(ma); | |
1191 } | |
1192 } | |
174 | 1193 |
0 | 1194 |
1195 static if (true) { | |
1196 // Always generate module info, because of templates and -cov | |
1197 if (1 || needModuleInfo()) | |
1198 genmoduleinfo(); | |
5
63623152e82a
Fixed memory corruption bug which was introduced when attempting to restore GC functionality
dkoroskin <>
parents:
4
diff
changeset
|
1199 } |
174 | 1200 |
0 | 1201 obj_termfile(); |
1202 } | |
174 | 1203 |
0 | 1204 void gensymfile() |
1205 { | |
1206 assert(false); | |
1207 } | |
174 | 1208 |
0 | 1209 void gendocfile() |
1210 { | |
1211 assert(false); | |
1212 } | |
174 | 1213 |
0 | 1214 /********************************** |
1215 * Determine if we need to generate an instance of ModuleInfo | |
1216 * for this Module. | |
1217 */ | |
1218 bool needModuleInfo() | |
1219 { | |
96 | 1220 // writef("needModuleInfo() %s, %d, %d\n", toChars(), needmoduleinfo, global.params.cov); |
0 | 1221 return needmoduleinfo || global.params.cov; |
1222 } | |
174 | 1223 |
72 | 1224 override Dsymbol search(Loc loc, Identifier ident, int flags) |
0 | 1225 { |
1226 /* Since modules can be circularly referenced, | |
1227 * need to stop infinite recursive searches. | |
79 | 1228 * This is done with the cache. |
0 | 1229 */ |
1230 | |
1231 //printf("%s Module.search('%s', flags = %d) insearch = %d\n", toChars(), ident.toChars(), flags, insearch); | |
1232 Dsymbol s; | |
1233 if (insearch) | |
1234 s = null; | |
79 | 1235 else if (searchCacheIdent == ident && searchCacheFlags == flags) |
73 | 1236 { |
0 | 1237 s = searchCacheSymbol; |
73 | 1238 //printf("%s Module.search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null"); |
1239 } | |
0 | 1240 else |
1241 { | |
1242 insearch = 1; | |
1243 s = ScopeDsymbol.search(loc, ident, flags); | |
1244 insearch = 0; | |
1245 | |
1246 searchCacheIdent = ident; | |
1247 searchCacheSymbol = s; | |
1248 searchCacheFlags = flags; | |
1249 } | |
1250 return s; | |
1251 } | |
174 | 1252 |
0 | 1253 void deleteObjFile() |
1254 { | |
1255 if (global.params.obj) | |
1256 objfile.remove(); | |
1257 if (docfile) | |
1258 docfile.remove(); | |
1259 } | |
1260 | |
79 | 1261 override Dsymbol symtabInsert(Dsymbol s) |
1262 { | |
1263 searchCacheIdent = null; // symbol is inserted, so invalidate cache | |
1264 return Package.symtabInsert(s); | |
1265 } | |
1266 | |
29
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1267 /******************************************* |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1268 * Can't run semantic on s now, try again later. |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1269 */ |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1270 void addDeferredSemantic(Dsymbol s) |
0 | 1271 { |
169 | 1272 auto deferred = global.deferred; |
29
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1273 // Don't add it if it is already there |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1274 for (int i = 0; i < deferred.dim; i++) |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1275 { |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1276 Dsymbol sd = cast(Dsymbol)deferred.data[i]; |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1277 |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1278 if (sd == s) |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1279 return; |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1280 } |
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1281 |
79 | 1282 //printf("Module::addDeferredSemantic('%s')\n", s.toChars()); |
29
9fe59705c82d
Implemented Module.addDeferredSemantic, removed -release from the linux commands file.
Robert Clipsham <robert@octarineparrot.com>
parents:
23
diff
changeset
|
1283 deferred.push(cast(void*)s); |
0 | 1284 } |
174 | 1285 |
0 | 1286 /****************************************** |
1287 * Run semantic() on deferred symbols. | |
1288 */ | |
1289 | |
1290 void runDeferredSemantic() | |
1291 { | |
170 | 1292 if (global.nested) |
1293 return; | |
1294 //if (deferred.dim) printf("+Module.runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); | |
1295 global.nested++; | |
174 | 1296 |
0 | 1297 size_t len; |
1298 | |
169 | 1299 auto deferred = global.deferred; |
174 | 1300 |
0 | 1301 do |
1302 { | |
169 | 1303 global.dprogress = 0; |
0 | 1304 len = deferred.dim; |
1305 if (!len) | |
1306 break; | |
1307 | |
1308 Dsymbol *todo; | |
1309 Dsymbol tmp; | |
1310 if (len == 1) | |
1311 { | |
1312 todo = &tmp; | |
1313 } | |
1314 else | |
1315 { | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
5
diff
changeset
|
1316 version(Bug4054) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
5
diff
changeset
|
1317 todo = cast(Dsymbol*)GC.malloc(len * (Dsymbol*).sizeof); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
5
diff
changeset
|
1318 else |
0 | 1319 todo = cast(Dsymbol*)alloca(len * (Dsymbol*).sizeof); |
1320 assert(todo); | |
1321 } | |
1322 memcpy(todo, deferred.data, len * (Dsymbol*).sizeof); | |
1323 deferred.setDim(0); | |
1324 | |
1325 for (int i = 0; i < len; i++) | |
1326 { | |
1327 Dsymbol s = todo[i]; | |
1328 | |
1329 s.semantic(null); | |
1330 //printf("deferred: %s, parent = %s\n", s.toChars(), s.parent.toChars()); | |
1331 } | |
1332 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress); | |
169 | 1333 } while (deferred.dim < len || global.dprogress); // while making progress |
170 | 1334 global.nested--; |
0 | 1335 //printf("-Module.runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); |
1336 } | |
81 | 1337 |
1338 /************************************ | |
1339 * Recursively look at every module this module imports, | |
1340 * return TRUE if it imports m. | |
1341 * Can be used to detect circular imports. | |
1342 */ | |
1343 bool imports(Module m) | |
0 | 1344 { |
81 | 1345 // writef("%s Module::imports(%s)\n", toChars(), m.toChars()); |
1346 int aimports_dim = aimports.dim; | |
1347 static if (false) | |
1348 { | |
1349 for (int i = 0; i < aimports.dim; i++) | |
1350 { Module mi = cast(Module)aimports.data[i]; | |
1351 writef("\t[%d] %s\n", i, mi.toChars()); | |
1352 } | |
1353 } | |
1354 for (int i = 0; i < aimports.dim; i++) | |
1355 { Module mi = cast(Module)aimports.data[i]; | |
1356 if (mi == m) | |
1357 return true; | |
1358 if (!mi.insearch) | |
1359 { | |
1360 mi.insearch = 1; | |
1361 bool r = mi.imports(m); | |
1362 if (r) | |
1363 return r; | |
1364 } | |
1365 } | |
1366 return false; | |
0 | 1367 } |
1368 | |
1369 // Back end | |
1370 | |
1371 int doppelganger; // sub-module | |
1372 Symbol* cov; // private uint[] __coverage; | |
1373 uint* covb; // bit array of valid code line numbers | |
1374 | |
1375 Symbol* sictor; // module order independent constructor | |
1376 Symbol* sctor; // module constructor | |
1377 Symbol* sdtor; // module destructor | |
1378 Symbol* stest; // module unit test | |
1379 | |
1380 Symbol* sfilename; // symbol for filename | |
1381 | |
1382 Symbol* massert; // module assert function | |
1383 Symbol* toModuleAssert() // get module assert function | |
1384 { | |
1385 if (!massert) | |
1386 { | |
1387 type* t; | |
1388 | |
1389 t = type_alloc(TYjfunc); | |
1390 t.Tflags |= TFprototype | TFfixed; | |
1391 t.Tmangle = mTYman_d; | |
1392 t.Tnext = tsvoid; | |
1393 tsvoid.Tcount++; | |
1394 | |
1395 massert = toSymbolX("__assert", SCextern, t, "FiZv"); | |
1396 massert.Sfl = FLextern; | |
1397 massert.Sflags |= SFLnodebug; | |
1398 slist_add(massert); | |
1399 } | |
1400 return massert; | |
1401 } | |
1402 | |
1403 Symbol* marray; // module array bounds function | |
1404 | |
1405 Symbol* toModuleArray() // get module array bounds function | |
1406 { | |
1407 if (!marray) | |
1408 { | |
1409 type* t; | |
1410 | |
1411 t = type_alloc(TYjfunc); | |
1412 t.Tflags |= TFprototype | TFfixed; | |
1413 t.Tmangle = mTYman_d; | |
1414 t.Tnext = tsvoid; | |
1415 tsvoid.Tcount++; | |
1416 | |
1417 marray = toSymbolX("__array", SCextern, t, "Z"); | |
1418 marray.Sfl = FLextern; | |
1419 marray.Sflags |= SFLnodebug; | |
1420 slist_add(marray); | |
1421 } | |
1422 return marray; | |
1423 } | |
1424 | |
1425 static Symbol* gencritsec() | |
1426 { | |
1427 assert(false); | |
1428 } | |
174 | 1429 |
0 | 1430 elem* toEfilename() |
1431 { | |
1432 elem* efilename; | |
1433 | |
1434 if (!sfilename) | |
1435 { | |
1436 dt_t* dt = null; | |
1437 | |
1438 string id = srcfile.toChars(); | |
1439 int len = id.length; | |
1440 dtdword(&dt, len); | |
1441 dtabytes(&dt,TYnptr, 0, len + 1, toStringz(id)); | |
1442 | |
1443 sfilename = symbol_generate(SCstatic,type_fake(TYdarray)); | |
1444 sfilename.Sdt = dt; | |
1445 sfilename.Sfl = FLdata; | |
1446 version (ELFOBJ) { | |
1447 sfilename.Sseg = Segment.CDATA; | |
1448 } | |
1449 version (MACHOBJ) { | |
1450 // Because of PIC and CDATA being in the _TEXT segment, cannot | |
1451 // have pointers in CDATA | |
1452 sfilename.Sseg = Segment.DATA; | |
1453 } | |
1454 outdata(sfilename); | |
1455 } | |
1456 | |
1457 efilename = el_var(sfilename); | |
1458 return efilename; | |
1459 } | |
174 | 1460 |
0 | 1461 /************************************** |
1462 * Generate elem that is a pointer to the module file name. | |
1463 */ | |
1464 elem* toEmodulename() | |
1465 { | |
1466 elem *efilename; | |
1467 | |
1468 // Get filename | |
1469 if (needModuleInfo()) | |
174 | 1470 { |
0 | 1471 /* Class ModuleInfo is defined in std.moduleinfo. |
1472 * The first member is the name of it, char name[], | |
1473 * which will be at offset 8. | |
1474 */ | |
1475 | |
1476 Symbol* si = toSymbol(); | |
1477 static if (true) { | |
1478 // Use this instead so -fPIC will work | |
1479 efilename = el_ptr(si); | |
1480 efilename = el_bin(OPadd, TYnptr, efilename, el_long(TYuint, 8)); | |
1481 efilename = el_una(OPind, TYdarray, efilename); | |
1482 } else { | |
1483 efilename = el_var(si); | |
1484 efilename.Ety = TYdarray; | |
1485 efilename.EV.sp.Voffset += 8; | |
1486 } | |
1487 } | |
1488 else // generate our own filename | |
1489 { | |
1490 efilename = toEfilename(); | |
1491 } | |
1492 return efilename; | |
1493 } | |
1494 | |
1495 /************************************* | |
1496 * Create the "ModuleInfo" symbol | |
1497 */ | |
72 | 1498 override Symbol* toSymbol() |
0 | 1499 { |
1500 if (!csym) | |
1501 { | |
1502 Symbol* s; | |
1503 | |
170 | 1504 s = toSymbolX("__ModuleInfo", SC.SCextern, global.scc.Stype, "Z"); |
0 | 1505 s.Sfl = FL.FLextern; |
1506 s.Sflags |= SFL.SFLnodebug; | |
1507 csym = s; | |
1508 slist_add(s); | |
1509 } | |
1510 return csym; | |
1511 } | |
1512 | |
1513 // Put out instance of ModuleInfo for this Module | |
1514 void genmoduleinfo() | |
1515 { | |
1516 //printf("Module.genmoduleinfo() %s\n", toChars()); | |
1517 | |
1518 Symbol* msym = toSymbol(); | |
1519 | |
1520 //dumpSymbol(msym); | |
174 | 1521 |
0 | 1522 uint offset; |
1523 version (DMDV2) { | |
1524 uint sizeof_ModuleInfo = 18 * PTRSIZE; | |
1525 } else { | |
1526 uint sizeof_ModuleInfo = 14 * PTRSIZE; | |
1527 } | |
1528 | |
1529 ////////////////////////////////////////////// | |
1530 | |
1531 csym.Sclass = SC.SCglobal; | |
1532 | |
1533 csym.Sfl = FL.FLdata; | |
1534 | |
1535 /* The layout is: | |
1536 { | |
1537 void **vptr; | |
1538 monitor_t monitor; | |
1539 char[] name; // class name | |
1540 ModuleInfo importedModules[]; | |
1541 ClassInfo localClasses[]; | |
1542 uint flags; // initialization state | |
1543 void *ctor; | |
1544 void *dtor; | |
1545 void *unitTest; | |
1546 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function | |
1547 void *ictor; | |
1548 void*[4] reserved; | |
1549 } | |
1550 */ | |
1551 dt_t* dt = null; | |
1552 | |
169 | 1553 if (global.moduleinfo) |
1554 dtxoff(&dt, global.moduleinfo.toVtblSymbol(), 0, TYM.TYnptr); // vtbl for ModuleInfo | |
0 | 1555 else |
174 | 1556 { |
0 | 1557 //printf("moduleinfo is null\n"); |
1558 dtdword(&dt, 0); // BUG: should be an assert() | |
1559 } | |
1560 dtdword(&dt, 0); // monitor | |
1561 | |
1562 // name[] | |
1563 string name = toPrettyChars(); | |
1564 size_t namelen = name.length; | |
1565 dtdword(&dt, namelen); | |
1566 dtabytes(&dt, TYM.TYnptr, 0, namelen + 1, toStringz(name)); | |
1567 | |
1568 ClassDeclarations aclasses = new ClassDeclarations(); | |
1569 | |
1570 //printf("members.dim = %d\n", members.dim); | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
1571 foreach(Dsymbol member; members) |
174 | 1572 { |
0 | 1573 //printf("\tmember '%s'\n", member.toChars()); |
1574 member.addLocalClass(aclasses); | |
1575 } | |
1576 | |
1577 // importedModules[] | |
1578 int aimports_dim = aimports.dim; | |
1579 for (int i = 0; i < aimports.dim; i++) | |
174 | 1580 { |
0 | 1581 Module m = cast(Module)aimports.data[i]; |
1582 if (!m.needModuleInfo()) | |
1583 aimports_dim--; | |
1584 } | |
1585 | |
1586 dtdword(&dt, aimports_dim); | |
1587 if (aimports_dim) | |
1588 dtxoff(&dt, csym, sizeof_ModuleInfo, TYM.TYnptr); | |
1589 else | |
1590 dtdword(&dt, 0); | |
1591 | |
1592 // localClasses[] | |
1593 dtdword(&dt, aclasses.dim); | |
1594 if (aclasses.dim) | |
1595 dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYM.TYnptr); | |
1596 else | |
1597 dtdword(&dt, 0); | |
1598 | |
1599 if (needmoduleinfo) | |
1600 dtdword(&dt, 8|0); // flags (4 means MIstandalone) | |
1601 else | |
1602 dtdword(&dt, 8|4); // flags (4 means MIstandalone) | |
1603 | |
1604 if (sctor) | |
1605 dtxoff(&dt, sctor, 0, TYM.TYnptr); | |
1606 else | |
1607 dtdword(&dt, 0); | |
1608 | |
1609 if (sdtor) | |
1610 dtxoff(&dt, sdtor, 0, TYM.TYnptr); | |
1611 else | |
1612 dtdword(&dt, 0); | |
1613 | |
1614 if (stest) | |
1615 dtxoff(&dt, stest, 0, TYM.TYnptr); | |
1616 else | |
1617 dtdword(&dt, 0); | |
1618 | |
1619 /// version (DMDV2) { | |
1620 FuncDeclaration sgetmembers = findGetMembers(); | |
1621 if (sgetmembers) | |
1622 dtxoff(&dt, sgetmembers.toSymbol(), 0, TYM.TYnptr); | |
1623 else | |
1624 /// } | |
1625 dtdword(&dt, 0); // xgetMembers | |
1626 | |
1627 if (sictor) | |
1628 dtxoff(&dt, sictor, 0, TYM.TYnptr); | |
1629 else | |
1630 dtdword(&dt, 0); | |
1631 | |
1632 version (DMDV2) { | |
1633 // void*[4] reserved; | |
1634 dtdword(&dt, 0); | |
1635 dtdword(&dt, 0); | |
1636 dtdword(&dt, 0); | |
1637 dtdword(&dt, 0); | |
1638 } | |
1639 ////////////////////////////////////////////// | |
1640 | |
1641 for (int i = 0; i < aimports.dim; i++) | |
174 | 1642 { |
0 | 1643 Module m = cast(Module)aimports.data[i]; |
1644 | |
1645 if (m.needModuleInfo()) | |
174 | 1646 { |
0 | 1647 Symbol* s = m.toSymbol(); |
1648 | |
1649 /* Weak references don't pull objects in from the library, | |
1650 * they resolve to 0 if not pulled in by something else. | |
1651 * Don't pull in a module just because it was imported. | |
1652 */ | |
1653 version (OMFOBJ) {// Optlink crashes with weak symbols at EIP 41AFE7, 402000 | |
1654 } else { | |
1655 s.Sflags |= SFL.SFLweak; | |
1656 } | |
1657 dtxoff(&dt, s, 0, TYM.TYnptr); | |
1658 } | |
1659 } | |
1660 | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1661 foreach (cd; aclasses) |
0 | 1662 { |
1663 dtxoff(&dt, cd.toSymbol(), 0, TYM.TYnptr); | |
1664 } | |
1665 | |
1666 csym.Sdt = dt; | |
1667 version (ELFOBJ_OR_MACHOBJ) { | |
1668 // Cannot be CONST because the startup code sets flag bits in it | |
1669 csym.Sseg = Segment.DATA; | |
1670 } | |
1671 | |
1672 outdata(csym); | |
1673 | |
1674 ////////////////////////////////////////////// | |
1675 | |
1676 obj_moduleinfo(msym); | |
1677 } | |
1678 | |
72 | 1679 override Module isModule() { return this; } |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
5
diff
changeset
|
1680 } |