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