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