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