Mercurial > projects > ldc
annotate dmd/mtype.c @ 837:331a176c1f4f
Removed error on naked, not fully complete, but I'll be doing more work on it during this Christmas, and some things do work.
Fixed taking delegate of final class method. see mini/delegate3.d.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 14:07:30 +0100 |
parents | 43178a913a28 |
children | bc982f1ad106 |
rev | line source |
---|---|
159 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2008 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #define __USE_ISOC99 1 // so signbit() gets defined | |
12 #include <math.h> | |
13 | |
14 #include <stdio.h> | |
15 #include <assert.h> | |
16 #include <float.h> | |
17 | |
18 #ifdef __DMC__ | |
19 #include <fp.h> | |
20 #endif | |
21 | |
22 #if _MSC_VER | |
23 #include <malloc.h> | |
24 #include <complex> | |
25 #include <limits> | |
26 #elif __DMC__ | |
27 #include <complex.h> | |
285
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
270
diff
changeset
|
28 #elif __MINGW32__ |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
270
diff
changeset
|
29 #include <malloc.h> |
159 | 30 #else |
31 //#define signbit 56 | |
32 #endif | |
33 | |
34 #if __APPLE__ | |
35 #include <math.h> | |
36 static double zero = 0; | |
285
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
270
diff
changeset
|
37 #elif __MINGW32__ |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
270
diff
changeset
|
38 #include <math.h> |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
270
diff
changeset
|
39 static double zero = 0; |
159 | 40 #elif __GNUC__ |
41 #include <math.h> | |
42 #include <bits/nan.h> | |
43 #include <bits/mathdef.h> | |
44 static double zero = 0; | |
45 #endif | |
46 | |
47 #include "mem.h" | |
48 | |
49 #include "dsymbol.h" | |
50 #include "mtype.h" | |
51 #include "scope.h" | |
52 #include "init.h" | |
53 #include "expression.h" | |
54 #include "attrib.h" | |
55 #include "declaration.h" | |
56 #include "template.h" | |
57 #include "id.h" | |
58 #include "enum.h" | |
59 #include "import.h" | |
60 #include "aggregate.h" | |
61 #include "hdrgen.h" | |
62 | |
63 FuncDeclaration *hasThis(Scope *sc); | |
64 | |
65 | |
66 #define LOGDOTEXP 0 // log ::dotExp() | |
67 #define LOGDEFAULTINIT 0 // log ::defaultInit() | |
68 | |
69 // Allow implicit conversion of T[] to T* | |
70 #define IMPLICIT_ARRAY_TO_PTR global.params.useDeprecated | |
71 | |
72 /* These have default values for 32 bit code, they get | |
73 * adjusted for 64 bit code. | |
74 */ | |
75 | |
76 int PTRSIZE = 4; | |
77 #if IN_LLVM | |
78 int REALSIZE = 8; | |
79 int REALPAD = 0; | |
80 #elif TARGET_LINUX | |
81 int REALSIZE = 12; | |
82 int REALPAD = 2; | |
83 #else | |
84 int REALSIZE = 10; | |
85 int REALPAD = 0; | |
86 #endif | |
87 int Tsize_t = Tuns32; | |
88 int Tptrdiff_t = Tint32; | |
89 | |
90 /***************************** Type *****************************/ | |
91 | |
92 ClassDeclaration *Type::typeinfo; | |
93 ClassDeclaration *Type::typeinfoclass; | |
94 ClassDeclaration *Type::typeinfointerface; | |
95 ClassDeclaration *Type::typeinfostruct; | |
96 ClassDeclaration *Type::typeinfotypedef; | |
97 ClassDeclaration *Type::typeinfopointer; | |
98 ClassDeclaration *Type::typeinfoarray; | |
99 ClassDeclaration *Type::typeinfostaticarray; | |
100 ClassDeclaration *Type::typeinfoassociativearray; | |
101 ClassDeclaration *Type::typeinfoenum; | |
102 ClassDeclaration *Type::typeinfofunction; | |
103 ClassDeclaration *Type::typeinfodelegate; | |
104 ClassDeclaration *Type::typeinfotypelist; | |
105 | |
106 Type *Type::tvoidptr; | |
107 Type *Type::basic[TMAX]; | |
108 unsigned char Type::mangleChar[TMAX]; | |
109 StringTable Type::stringtable; | |
110 | |
111 | |
112 Type::Type(TY ty, Type *next) | |
113 { | |
114 this->ty = ty; | |
115 this->mod = 0; | |
116 this->next = next; | |
117 this->deco = NULL; | |
336 | 118 #if DMDV2 |
159 | 119 this->cto = NULL; |
120 this->ito = NULL; | |
121 #endif | |
122 this->pto = NULL; | |
123 this->rto = NULL; | |
124 this->arrayof = NULL; | |
125 this->vtinfo = NULL; | |
126 this->ctype = NULL; | |
127 } | |
128 | |
129 Type *Type::syntaxCopy() | |
130 { | |
131 print(); | |
132 fprintf(stdmsg, "ty = %d\n", ty); | |
133 assert(0); | |
134 return this; | |
135 } | |
136 | |
137 int Type::equals(Object *o) | |
138 { Type *t; | |
139 | |
140 t = (Type *)o; | |
141 //printf("Type::equals(%s, %s)\n", toChars(), t->toChars()); | |
142 if (this == o || | |
143 (t && deco == t->deco) && // deco strings are unique | |
144 deco != NULL) // and semantic() has been run | |
145 { | |
146 //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco); | |
147 return 1; | |
148 } | |
149 //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco); | |
150 return 0; | |
151 } | |
152 | |
153 char Type::needThisPrefix() | |
154 { | |
155 return 'M'; // name mangling prefix for functions needing 'this' | |
156 } | |
157 | |
158 void Type::init() | |
159 { int i; | |
160 int j; | |
161 | |
162 Lexer::initKeywords(); | |
163 | |
164 mangleChar[Tarray] = 'A'; | |
165 mangleChar[Tsarray] = 'G'; | |
166 mangleChar[Taarray] = 'H'; | |
167 mangleChar[Tpointer] = 'P'; | |
168 mangleChar[Treference] = 'R'; | |
169 mangleChar[Tfunction] = 'F'; | |
170 mangleChar[Tident] = 'I'; | |
171 mangleChar[Tclass] = 'C'; | |
172 mangleChar[Tstruct] = 'S'; | |
173 mangleChar[Tenum] = 'E'; | |
174 mangleChar[Ttypedef] = 'T'; | |
175 mangleChar[Tdelegate] = 'D'; | |
176 | |
177 mangleChar[Tnone] = 'n'; | |
178 mangleChar[Tvoid] = 'v'; | |
179 mangleChar[Tint8] = 'g'; | |
180 mangleChar[Tuns8] = 'h'; | |
181 mangleChar[Tint16] = 's'; | |
182 mangleChar[Tuns16] = 't'; | |
183 mangleChar[Tint32] = 'i'; | |
184 mangleChar[Tuns32] = 'k'; | |
185 mangleChar[Tint64] = 'l'; | |
186 mangleChar[Tuns64] = 'm'; | |
187 mangleChar[Tfloat32] = 'f'; | |
188 mangleChar[Tfloat64] = 'd'; | |
189 mangleChar[Tfloat80] = 'e'; | |
190 | |
191 mangleChar[Timaginary32] = 'o'; | |
192 mangleChar[Timaginary64] = 'p'; | |
193 mangleChar[Timaginary80] = 'j'; | |
194 mangleChar[Tcomplex32] = 'q'; | |
195 mangleChar[Tcomplex64] = 'r'; | |
196 mangleChar[Tcomplex80] = 'c'; | |
197 | |
198 mangleChar[Tbool] = 'b'; | |
199 mangleChar[Tascii] = 'a'; | |
200 mangleChar[Twchar] = 'u'; | |
201 mangleChar[Tdchar] = 'w'; | |
202 | |
203 mangleChar[Tbit] = '@'; | |
204 mangleChar[Tinstance] = '@'; | |
205 mangleChar[Terror] = '@'; | |
206 mangleChar[Ttypeof] = '@'; | |
207 mangleChar[Ttuple] = 'B'; | |
208 mangleChar[Tslice] = '@'; | |
209 | |
210 for (i = 0; i < TMAX; i++) | |
211 { if (!mangleChar[i]) | |
212 fprintf(stdmsg, "ty = %d\n", i); | |
213 assert(mangleChar[i]); | |
214 } | |
215 | |
216 // Set basic types | |
217 static TY basetab[] = | |
218 { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64, | |
219 Tfloat32, Tfloat64, Tfloat80, | |
220 Timaginary32, Timaginary64, Timaginary80, | |
221 Tcomplex32, Tcomplex64, Tcomplex80, | |
222 Tbit, Tbool, | |
223 Tascii, Twchar, Tdchar }; | |
224 | |
225 for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++) | |
226 basic[basetab[i]] = new TypeBasic(basetab[i]); | |
227 basic[Terror] = basic[Tint32]; | |
228 | |
229 tvoidptr = tvoid->pointerTo(); | |
230 | |
270
d9d5d59873d8
[svn r291] Fixed a bunch of the old Phobos tests to work with Tango.
lindquist
parents:
243
diff
changeset
|
231 // set size_t / ptrdiff_t types and pointer size |
159 | 232 if (global.params.is64bit) |
233 { | |
742
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
234 Tsize_t = Tuns64; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
235 Tptrdiff_t = Tint64; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
236 PTRSIZE = 8; |
159 | 237 } |
238 else | |
239 { | |
742
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
240 Tsize_t = Tuns32; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
241 Tptrdiff_t = Tint32; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
242 PTRSIZE = 4; |
243
4d006f7b2ada
[svn r260] Changed some of the LLVMDC specific code in the Tango core and did some minor cleanups.
lindquist
parents:
217
diff
changeset
|
243 } |
4d006f7b2ada
[svn r260] Changed some of the LLVMDC specific code in the Tango core and did some minor cleanups.
lindquist
parents:
217
diff
changeset
|
244 |
4d006f7b2ada
[svn r260] Changed some of the LLVMDC specific code in the Tango core and did some minor cleanups.
lindquist
parents:
217
diff
changeset
|
245 // set real size and padding |
445
cc40db549aea
Changed the handling of variadic intrinsics a bit.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
246 if (global.params.cpu == ARCHx86) |
243
4d006f7b2ada
[svn r260] Changed some of the LLVMDC specific code in the Tango core and did some minor cleanups.
lindquist
parents:
217
diff
changeset
|
247 { |
742
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
248 REALSIZE = 12; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
249 REALPAD = 2; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
250 } |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
251 else if (global.params.cpu == ARCHx86_64) |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
252 { |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
253 REALSIZE = 16; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
254 REALPAD = 6; |
243
4d006f7b2ada
[svn r260] Changed some of the LLVMDC specific code in the Tango core and did some minor cleanups.
lindquist
parents:
217
diff
changeset
|
255 } |
4d006f7b2ada
[svn r260] Changed some of the LLVMDC specific code in the Tango core and did some minor cleanups.
lindquist
parents:
217
diff
changeset
|
256 else |
4d006f7b2ada
[svn r260] Changed some of the LLVMDC specific code in the Tango core and did some minor cleanups.
lindquist
parents:
217
diff
changeset
|
257 { |
742
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
258 REALSIZE = 8; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
259 REALPAD = 0; |
159 | 260 } |
261 } | |
262 | |
263 d_uns64 Type::size() | |
264 { | |
265 return size(0); | |
266 } | |
267 | |
268 d_uns64 Type::size(Loc loc) | |
269 { | |
270 error(loc, "no size for type %s", toChars()); | |
271 return 1; | |
272 } | |
273 | |
274 unsigned Type::alignsize() | |
275 { | |
276 return size(0); | |
277 } | |
278 | |
279 Type *Type::semantic(Loc loc, Scope *sc) | |
280 { | |
281 if (next) | |
282 next = next->semantic(loc,sc); | |
283 return merge(); | |
284 } | |
285 | |
286 Type *Type::pointerTo() | |
287 { | |
288 if (!pto) | |
289 { Type *t; | |
290 | |
291 t = new TypePointer(this); | |
292 pto = t->merge(); | |
293 } | |
294 return pto; | |
295 } | |
296 | |
297 Type *Type::referenceTo() | |
298 { | |
299 if (!rto) | |
300 { Type *t; | |
301 | |
302 t = new TypeReference(this); | |
303 rto = t->merge(); | |
304 } | |
305 return rto; | |
306 } | |
307 | |
308 Type *Type::arrayOf() | |
309 { | |
310 if (!arrayof) | |
311 { Type *t; | |
312 | |
313 t = new TypeDArray(this); | |
314 arrayof = t->merge(); | |
315 } | |
316 return arrayof; | |
317 } | |
318 | |
319 Dsymbol *Type::toDsymbol(Scope *sc) | |
320 { | |
321 return NULL; | |
322 } | |
323 | |
324 /******************************* | |
325 * If this is a shell around another type, | |
326 * get that other type. | |
327 */ | |
328 | |
329 Type *Type::toBasetype() | |
330 { | |
331 return this; | |
332 } | |
333 | |
334 /******************************** | |
335 * Name mangling. | |
336 */ | |
337 | |
338 void Type::toDecoBuffer(OutBuffer *buf) | |
339 { | |
340 buf->writeByte(mangleChar[ty]); | |
341 if (next) | |
342 { | |
343 assert(next != this); | |
344 //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty); | |
345 next->toDecoBuffer(buf); | |
346 } | |
347 } | |
348 | |
349 /******************************** | |
350 * For pretty-printing a type. | |
351 */ | |
352 | |
353 char *Type::toChars() | |
354 { OutBuffer *buf; | |
355 HdrGenState hgs; | |
356 | |
357 buf = new OutBuffer(); | |
358 toCBuffer(buf, NULL, &hgs); | |
359 return buf->toChars(); | |
360 } | |
361 | |
362 void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) | |
363 { | |
364 toCBuffer2(buf, hgs, 0); | |
365 if (ident) | |
366 { buf->writeByte(' '); | |
367 buf->writestring(ident->toChars()); | |
368 } | |
369 } | |
370 | |
371 void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
372 { | |
373 if (mod != this->mod) | |
374 { toCBuffer3(buf, hgs, mod); | |
375 return; | |
376 } | |
377 buf->writestring(toChars()); | |
378 } | |
379 | |
380 void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod) | |
381 { | |
382 if (mod != this->mod) | |
383 { char *p; | |
384 | |
385 switch (this->mod) | |
386 { | |
387 case 0: | |
388 toCBuffer2(buf, hgs, this->mod); | |
389 break; | |
390 case MODconst: | |
391 p = "const("; | |
392 goto L1; | |
393 case MODinvariant: | |
394 p = "invariant("; | |
395 L1: buf->writestring(p); | |
396 toCBuffer2(buf, hgs, this->mod); | |
397 buf->writeByte(')'); | |
398 break; | |
399 default: | |
400 assert(0); | |
401 } | |
402 } | |
403 } | |
404 | |
405 | |
406 /************************************ | |
407 */ | |
408 | |
409 Type *Type::merge() | |
410 { Type *t; | |
411 | |
412 //printf("merge(%s)\n", toChars()); | |
413 t = this; | |
414 assert(t); | |
415 if (!deco) | |
416 { | |
417 OutBuffer buf; | |
418 StringValue *sv; | |
419 | |
420 if (next) | |
421 next = next->merge(); | |
422 toDecoBuffer(&buf); | |
423 sv = stringtable.update((char *)buf.data, buf.offset); | |
424 if (sv->ptrvalue) | |
425 { t = (Type *) sv->ptrvalue; | |
426 assert(t->deco); | |
427 //printf("old value, deco = '%s' %p\n", t->deco, t->deco); | |
428 } | |
429 else | |
430 { | |
431 sv->ptrvalue = this; | |
432 deco = sv->lstring.string; | |
433 //printf("new value, deco = '%s' %p\n", t->deco, t->deco); | |
434 } | |
435 } | |
436 return t; | |
437 } | |
438 | |
439 int Type::isbit() | |
440 { | |
441 return FALSE; | |
442 } | |
443 | |
444 int Type::isintegral() | |
445 { | |
446 return FALSE; | |
447 } | |
448 | |
449 int Type::isfloating() | |
450 { | |
451 return FALSE; | |
452 } | |
453 | |
454 int Type::isreal() | |
455 { | |
456 return FALSE; | |
457 } | |
458 | |
459 int Type::isimaginary() | |
460 { | |
461 return FALSE; | |
462 } | |
463 | |
464 int Type::iscomplex() | |
465 { | |
466 return FALSE; | |
467 } | |
468 | |
469 int Type::isscalar() | |
470 { | |
471 return FALSE; | |
472 } | |
473 | |
474 int Type::isunsigned() | |
475 { | |
476 return FALSE; | |
477 } | |
478 | |
479 ClassDeclaration *Type::isClassHandle() | |
480 { | |
481 return NULL; | |
482 } | |
483 | |
484 int Type::isauto() | |
485 { | |
486 return FALSE; | |
487 } | |
488 | |
489 int Type::isString() | |
490 { | |
491 return FALSE; | |
492 } | |
493 | |
494 int Type::checkBoolean() | |
495 { | |
496 return isscalar(); | |
497 } | |
498 | |
499 /********************************* | |
500 * Check type to see if it is based on a deprecated symbol. | |
501 */ | |
502 | |
503 void Type::checkDeprecated(Loc loc, Scope *sc) | |
504 { | |
505 Type *t; | |
506 Dsymbol *s; | |
507 | |
508 for (t = this; t; t = t->next) | |
509 { | |
510 s = t->toDsymbol(sc); | |
511 if (s) | |
512 s->checkDeprecated(loc, sc); | |
513 } | |
514 } | |
515 | |
516 | |
517 Expression *Type::defaultInit(Loc loc) | |
518 { | |
519 #if LOGDEFAULTINIT | |
520 printf("Type::defaultInit() '%s'\n", toChars()); | |
521 #endif | |
522 return NULL; | |
523 } | |
524 | |
525 int Type::isZeroInit() | |
526 { | |
527 return 0; // assume not | |
528 } | |
529 | |
530 int Type::isBaseOf(Type *t, int *poffset) | |
531 { | |
532 return 0; // assume not | |
533 } | |
534 | |
535 /******************************** | |
536 * Determine if 'this' can be implicitly converted | |
537 * to type 'to'. | |
538 * Returns: | |
539 * 0 can't convert | |
540 * 1 can convert using implicit conversions | |
541 * 2 this and to are the same type | |
542 */ | |
543 | |
544 MATCH Type::implicitConvTo(Type *to) | |
545 { | |
546 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to); | |
547 //printf("\tthis->next=%p, to->next=%p\n", this->next, to->next); | |
548 if (this == to) | |
549 return MATCHexact; | |
550 // if (to->ty == Tvoid) | |
551 // return 1; | |
552 return MATCHnomatch; | |
553 } | |
554 | |
555 Expression *Type::getProperty(Loc loc, Identifier *ident) | |
556 { Expression *e; | |
557 | |
558 #if LOGDOTEXP | |
559 printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars()); | |
560 #endif | |
561 if (ident == Id::__sizeof) | |
562 { | |
563 e = new IntegerExp(loc, size(loc), Type::tsize_t); | |
564 } | |
565 else if (ident == Id::size) | |
566 { | |
567 error(loc, ".size property should be replaced with .sizeof"); | |
568 e = new IntegerExp(loc, size(loc), Type::tsize_t); | |
569 } | |
570 else if (ident == Id::alignof) | |
571 { | |
572 e = new IntegerExp(loc, alignsize(), Type::tsize_t); | |
573 } | |
574 else if (ident == Id::typeinfo) | |
575 { | |
576 if (!global.params.useDeprecated) | |
577 error(loc, ".typeinfo deprecated, use typeid(type)"); | |
578 e = getTypeInfo(NULL); | |
579 } | |
580 else if (ident == Id::init) | |
581 { | |
582 if (ty == Tvoid) | |
583 error(loc, "void does not have an initializer"); | |
584 e = defaultInit(loc); | |
585 } | |
586 else if (ident == Id::mangleof) | |
587 { | |
588 assert(deco); | |
589 e = new StringExp(loc, deco, strlen(deco), 'c'); | |
590 Scope sc; | |
591 e = e->semantic(&sc); | |
592 } | |
593 else if (ident == Id::stringof) | |
594 { char *s = toChars(); | |
595 e = new StringExp(loc, s, strlen(s), 'c'); | |
596 Scope sc; | |
597 e = e->semantic(&sc); | |
598 } | |
599 else | |
600 { | |
601 error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars()); | |
602 e = new IntegerExp(loc, 1, Type::tint32); | |
603 } | |
604 return e; | |
605 } | |
606 | |
607 Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
608 { VarDeclaration *v = NULL; | |
609 | |
610 #if LOGDOTEXP | |
611 printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
612 #endif | |
613 if (e->op == TOKdotvar) | |
614 { | |
615 DotVarExp *dv = (DotVarExp *)e; | |
616 v = dv->var->isVarDeclaration(); | |
617 } | |
618 else if (e->op == TOKvar) | |
619 { | |
620 VarExp *ve = (VarExp *)e; | |
621 v = ve->var->isVarDeclaration(); | |
622 } | |
623 if (v) | |
624 { | |
625 if (ident == Id::offset) | |
626 { | |
627 if (!global.params.useDeprecated) | |
628 error(e->loc, ".offset deprecated, use .offsetof"); | |
629 goto Loffset; | |
630 } | |
631 else if (ident == Id::offsetof) | |
632 { | |
633 Loffset: | |
634 if (v->storage_class & STCfield) | |
635 { | |
636 e = new IntegerExp(e->loc, v->offset, Type::tsize_t); | |
637 return e; | |
638 } | |
639 } | |
640 else if (ident == Id::init) | |
641 { | |
642 #if 0 | |
643 if (v->init) | |
644 { | |
645 if (v->init->isVoidInitializer()) | |
646 error(e->loc, "%s.init is void", v->toChars()); | |
647 else | |
648 { Loc loc = e->loc; | |
649 e = v->init->toExpression(); | |
650 if (e->op == TOKassign || e->op == TOKconstruct) | |
651 { | |
652 e = ((AssignExp *)e)->e2; | |
653 | |
654 /* Take care of case where we used a 0 | |
655 * to initialize the struct. | |
656 */ | |
657 if (e->type == Type::tint32 && | |
658 e->isBool(0) && | |
659 v->type->toBasetype()->ty == Tstruct) | |
660 { | |
661 e = v->type->defaultInit(loc); | |
662 } | |
663 } | |
664 e = e->optimize(WANTvalue | WANTinterpret); | |
665 // if (!e->isConst()) | |
666 // error(loc, ".init cannot be evaluated at compile time"); | |
667 } | |
668 return e; | |
669 } | |
670 #endif | |
671 Expression *ex = defaultInit(e->loc); | |
672 return ex; | |
673 } | |
674 } | |
675 if (ident == Id::typeinfo) | |
676 { | |
677 if (!global.params.useDeprecated) | |
678 error(e->loc, ".typeinfo deprecated, use typeid(type)"); | |
679 e = getTypeInfo(sc); | |
680 return e; | |
681 } | |
682 if (ident == Id::stringof) | |
683 { char *s = e->toChars(); | |
684 e = new StringExp(e->loc, s, strlen(s), 'c'); | |
685 Scope sc; | |
686 e = e->semantic(&sc); | |
687 return e; | |
688 } | |
689 return getProperty(e->loc, ident); | |
690 } | |
691 | |
692 unsigned Type::memalign(unsigned salign) | |
693 { | |
694 return salign; | |
695 } | |
696 | |
697 void Type::error(Loc loc, const char *format, ...) | |
698 { | |
699 va_list ap; | |
700 va_start(ap, format); | |
701 ::verror(loc, format, ap); | |
702 va_end( ap ); | |
703 } | |
704 | |
705 Identifier *Type::getTypeInfoIdent(int internal) | |
706 { | |
707 // _init_10TypeInfo_%s | |
708 OutBuffer buf; | |
709 Identifier *id; | |
710 char *name; | |
711 int len; | |
712 | |
713 //toTypeInfoBuffer(&buf); | |
714 if (internal) | |
715 { buf.writeByte(mangleChar[ty]); | |
716 if (ty == Tarray) | |
717 buf.writeByte(mangleChar[next->ty]); | |
718 } | |
719 else | |
720 toDecoBuffer(&buf); | |
721 len = buf.offset; | |
722 name = (char *)alloca(19 + sizeof(len) * 3 + len + 1); | |
723 buf.writeByte(0); | |
724 sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
725 // LDC |
375
3c4460b988bd
Do not strip the leading underscore for typeinfo mangles on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
726 // it is not clear where the underscore that's stripped here is added back in |
3c4460b988bd
Do not strip the leading underscore for typeinfo mangles on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
727 // if (global.params.isWindows) |
3c4460b988bd
Do not strip the leading underscore for typeinfo mangles on Windows.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
728 // name++; // C mangling will add it back in |
159 | 729 //printf("name = %s\n", name); |
730 id = Lexer::idPool(name); | |
731 return id; | |
732 } | |
733 | |
734 TypeBasic *Type::isTypeBasic() | |
735 { | |
736 return NULL; | |
737 } | |
738 | |
739 | |
740 void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) | |
741 { | |
742 Type *t; | |
743 | |
744 t = semantic(loc, sc); | |
745 *pt = t; | |
746 *pe = NULL; | |
747 *ps = NULL; | |
748 } | |
749 | |
750 /******************************* | |
751 * If one of the subtypes of this type is a TypeIdentifier, | |
752 * i.e. it's an unresolved type, return that type. | |
753 */ | |
754 | |
755 Type *Type::reliesOnTident() | |
756 { | |
757 if (!next) | |
758 return NULL; | |
759 else | |
760 return next->reliesOnTident(); | |
761 } | |
762 | |
763 /******************************** | |
764 * We've mistakenly parsed this as a type. | |
765 * Redo it as an Expression. | |
766 * NULL if cannot. | |
767 */ | |
768 | |
769 Expression *Type::toExpression() | |
770 { | |
771 return NULL; | |
772 } | |
773 | |
774 /*************************************** | |
775 * Return !=0 if type has pointers that need to | |
776 * be scanned by the GC during a collection cycle. | |
777 */ | |
778 | |
779 int Type::hasPointers() | |
780 { | |
781 return FALSE; | |
782 } | |
783 | |
784 /* ============================= TypeBasic =========================== */ | |
785 | |
786 TypeBasic::TypeBasic(TY ty) | |
787 : Type(ty, NULL) | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
642
diff
changeset
|
788 { const char *c; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
642
diff
changeset
|
789 const char *d; |
159 | 790 unsigned flags; |
791 | |
792 #define TFLAGSintegral 1 | |
793 #define TFLAGSfloating 2 | |
794 #define TFLAGSunsigned 4 | |
795 #define TFLAGSreal 8 | |
796 #define TFLAGSimaginary 0x10 | |
797 #define TFLAGScomplex 0x20 | |
798 | |
799 flags = 0; | |
800 switch (ty) | |
801 { | |
802 case Tvoid: d = Token::toChars(TOKvoid); | |
803 c = "void"; | |
804 break; | |
805 | |
806 case Tint8: d = Token::toChars(TOKint8); | |
807 c = "byte"; | |
808 flags |= TFLAGSintegral; | |
809 break; | |
810 | |
811 case Tuns8: d = Token::toChars(TOKuns8); | |
812 c = "ubyte"; | |
813 flags |= TFLAGSintegral | TFLAGSunsigned; | |
814 break; | |
815 | |
816 case Tint16: d = Token::toChars(TOKint16); | |
817 c = "short"; | |
818 flags |= TFLAGSintegral; | |
819 break; | |
820 | |
821 case Tuns16: d = Token::toChars(TOKuns16); | |
822 c = "ushort"; | |
823 flags |= TFLAGSintegral | TFLAGSunsigned; | |
824 break; | |
825 | |
826 case Tint32: d = Token::toChars(TOKint32); | |
827 c = "int"; | |
828 flags |= TFLAGSintegral; | |
829 break; | |
830 | |
831 case Tuns32: d = Token::toChars(TOKuns32); | |
832 c = "uint"; | |
833 flags |= TFLAGSintegral | TFLAGSunsigned; | |
834 break; | |
835 | |
836 case Tfloat32: d = Token::toChars(TOKfloat32); | |
837 c = "float"; | |
838 flags |= TFLAGSfloating | TFLAGSreal; | |
839 break; | |
840 | |
841 case Tint64: d = Token::toChars(TOKint64); | |
842 c = "long"; | |
843 flags |= TFLAGSintegral; | |
844 break; | |
845 | |
846 case Tuns64: d = Token::toChars(TOKuns64); | |
847 c = "ulong"; | |
848 flags |= TFLAGSintegral | TFLAGSunsigned; | |
849 break; | |
850 | |
851 case Tfloat64: d = Token::toChars(TOKfloat64); | |
852 c = "double"; | |
853 flags |= TFLAGSfloating | TFLAGSreal; | |
854 break; | |
855 | |
856 case Tfloat80: d = Token::toChars(TOKfloat80); | |
857 c = "real"; | |
858 flags |= TFLAGSfloating | TFLAGSreal; | |
859 break; | |
860 | |
861 case Timaginary32: d = Token::toChars(TOKimaginary32); | |
862 c = "ifloat"; | |
863 flags |= TFLAGSfloating | TFLAGSimaginary; | |
864 break; | |
865 | |
866 case Timaginary64: d = Token::toChars(TOKimaginary64); | |
867 c = "idouble"; | |
868 flags |= TFLAGSfloating | TFLAGSimaginary; | |
869 break; | |
870 | |
871 case Timaginary80: d = Token::toChars(TOKimaginary80); | |
872 c = "ireal"; | |
873 flags |= TFLAGSfloating | TFLAGSimaginary; | |
874 break; | |
875 | |
876 case Tcomplex32: d = Token::toChars(TOKcomplex32); | |
877 c = "cfloat"; | |
878 flags |= TFLAGSfloating | TFLAGScomplex; | |
879 break; | |
880 | |
881 case Tcomplex64: d = Token::toChars(TOKcomplex64); | |
882 c = "cdouble"; | |
883 flags |= TFLAGSfloating | TFLAGScomplex; | |
884 break; | |
885 | |
886 case Tcomplex80: d = Token::toChars(TOKcomplex80); | |
887 c = "creal"; | |
888 flags |= TFLAGSfloating | TFLAGScomplex; | |
889 break; | |
890 | |
891 | |
892 case Tbit: d = Token::toChars(TOKbit); | |
893 c = "bit"; | |
894 flags |= TFLAGSintegral | TFLAGSunsigned; | |
895 break; | |
896 | |
897 case Tbool: d = "bool"; | |
898 c = d; | |
899 flags |= TFLAGSintegral | TFLAGSunsigned; | |
900 break; | |
901 | |
902 case Tascii: d = Token::toChars(TOKchar); | |
903 c = "char"; | |
904 flags |= TFLAGSintegral | TFLAGSunsigned; | |
905 break; | |
906 | |
907 case Twchar: d = Token::toChars(TOKwchar); | |
908 c = "wchar"; | |
909 flags |= TFLAGSintegral | TFLAGSunsigned; | |
910 break; | |
911 | |
912 case Tdchar: d = Token::toChars(TOKdchar); | |
913 c = "dchar"; | |
914 flags |= TFLAGSintegral | TFLAGSunsigned; | |
915 break; | |
916 | |
917 default: assert(0); | |
918 } | |
919 this->dstring = d; | |
920 this->cstring = c; | |
921 this->flags = flags; | |
922 merge(); | |
923 } | |
924 | |
925 Type *TypeBasic::syntaxCopy() | |
926 { | |
927 // No semantic analysis done on basic types, no need to copy | |
928 return this; | |
929 } | |
930 | |
931 | |
932 char *TypeBasic::toChars() | |
933 { | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
642
diff
changeset
|
934 return (char *)dstring; |
159 | 935 } |
936 | |
937 void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
938 { | |
939 //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod); | |
940 if (mod != this->mod) | |
941 { toCBuffer3(buf, hgs, mod); | |
942 return; | |
943 } | |
944 buf->writestring(dstring); | |
945 } | |
946 | |
947 d_uns64 TypeBasic::size(Loc loc) | |
948 { unsigned size; | |
949 | |
950 //printf("TypeBasic::size()\n"); | |
951 switch (ty) | |
952 { | |
953 case Tint8: | |
954 case Tuns8: size = 1; break; | |
955 case Tint16: | |
956 case Tuns16: size = 2; break; | |
957 case Tint32: | |
958 case Tuns32: | |
959 case Tfloat32: | |
960 case Timaginary32: | |
961 size = 4; break; | |
962 case Tint64: | |
963 case Tuns64: | |
964 case Tfloat64: | |
965 case Timaginary64: | |
966 size = 8; break; | |
967 case Tfloat80: | |
968 case Timaginary80: | |
969 size = REALSIZE; break; | |
970 case Tcomplex32: | |
971 size = 8; break; | |
972 case Tcomplex64: | |
973 size = 16; break; | |
974 case Tcomplex80: | |
975 size = REALSIZE * 2; break; | |
976 | |
977 case Tvoid: | |
978 //size = Type::size(); // error message | |
979 size = 1; | |
980 break; | |
981 | |
982 case Tbit: size = 1; break; | |
983 case Tbool: size = 1; break; | |
984 case Tascii: size = 1; break; | |
985 case Twchar: size = 2; break; | |
986 case Tdchar: size = 4; break; | |
987 | |
988 default: | |
989 assert(0); | |
990 break; | |
991 } | |
992 //printf("TypeBasic::size() = %d\n", size); | |
993 return size; | |
994 } | |
995 | |
996 unsigned TypeBasic::alignsize() | |
997 { unsigned sz; | |
998 | |
742
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
999 //LDC: it's bad that we always have to check LLVM's align and |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1000 // dmd's align info match. Can't we somehow get at LLVM's align |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1001 // here? |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1002 |
159 | 1003 switch (ty) |
1004 { | |
1005 case Tfloat80: | |
1006 case Timaginary80: | |
1007 case Tcomplex80: | |
742
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1008 if (global.params.cpu == ARCHx86_64) |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1009 sz = 16; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1010 else |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1011 sz = 4; |
489
822774a94750
Make the alignment computations of the frontend match the llvm default alignment.
Christian Kamm <kamm incasoftware de>
parents:
486
diff
changeset
|
1012 break; |
822774a94750
Make the alignment computations of the frontend match the llvm default alignment.
Christian Kamm <kamm incasoftware de>
parents:
486
diff
changeset
|
1013 |
822774a94750
Make the alignment computations of the frontend match the llvm default alignment.
Christian Kamm <kamm incasoftware de>
parents:
486
diff
changeset
|
1014 case Tint64: |
822774a94750
Make the alignment computations of the frontend match the llvm default alignment.
Christian Kamm <kamm incasoftware de>
parents:
486
diff
changeset
|
1015 case Tuns64: |
822774a94750
Make the alignment computations of the frontend match the llvm default alignment.
Christian Kamm <kamm incasoftware de>
parents:
486
diff
changeset
|
1016 case Tfloat64: |
822774a94750
Make the alignment computations of the frontend match the llvm default alignment.
Christian Kamm <kamm incasoftware de>
parents:
486
diff
changeset
|
1017 case Timaginary64: |
742
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1018 if (global.params.cpu == ARCHx86_64) |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1019 sz = 8; |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1020 else |
05e7657a7811
Fix REALSIZE, REALPAD and alignment of double and real for x86-64.
Christian Kamm <kamm incasoftware de>
parents:
739
diff
changeset
|
1021 sz = 4; |
159 | 1022 break; |
1023 | |
1024 default: | |
1025 sz = size(0); | |
1026 break; | |
1027 } | |
1028 return sz; | |
1029 } | |
1030 | |
1031 | |
1032 Expression *TypeBasic::getProperty(Loc loc, Identifier *ident) | |
1033 { | |
1034 Expression *e; | |
1035 d_int64 ivalue; | |
1036 #ifdef IN_GCC | |
1037 real_t fvalue; | |
1038 #else | |
1039 d_float80 fvalue; | |
1040 #endif | |
1041 | |
1042 //printf("TypeBasic::getProperty('%s')\n", ident->toChars()); | |
1043 if (ident == Id::max) | |
1044 { | |
1045 switch (ty) | |
1046 { | |
1047 case Tint8: ivalue = 0x7F; goto Livalue; | |
1048 case Tuns8: ivalue = 0xFF; goto Livalue; | |
1049 case Tint16: ivalue = 0x7FFFUL; goto Livalue; | |
1050 case Tuns16: ivalue = 0xFFFFUL; goto Livalue; | |
1051 case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue; | |
1052 case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue; | |
1053 case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue; | |
1054 case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue; | |
1055 case Tbit: ivalue = 1; goto Livalue; | |
1056 case Tbool: ivalue = 1; goto Livalue; | |
1057 case Tchar: ivalue = 0xFF; goto Livalue; | |
1058 case Twchar: ivalue = 0xFFFFUL; goto Livalue; | |
1059 case Tdchar: ivalue = 0x10FFFFUL; goto Livalue; | |
1060 | |
1061 case Tcomplex32: | |
1062 case Timaginary32: | |
1063 case Tfloat32: fvalue = FLT_MAX; goto Lfvalue; | |
1064 case Tcomplex64: | |
1065 case Timaginary64: | |
1066 case Tfloat64: fvalue = DBL_MAX; goto Lfvalue; | |
1067 case Tcomplex80: | |
1068 case Timaginary80: | |
1069 case Tfloat80: fvalue = LDBL_MAX; goto Lfvalue; | |
1070 } | |
1071 } | |
1072 else if (ident == Id::min) | |
1073 { | |
1074 switch (ty) | |
1075 { | |
1076 case Tint8: ivalue = -128; goto Livalue; | |
1077 case Tuns8: ivalue = 0; goto Livalue; | |
1078 case Tint16: ivalue = -32768; goto Livalue; | |
1079 case Tuns16: ivalue = 0; goto Livalue; | |
1080 case Tint32: ivalue = -2147483647L - 1; goto Livalue; | |
1081 case Tuns32: ivalue = 0; goto Livalue; | |
1082 case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue; | |
1083 case Tuns64: ivalue = 0; goto Livalue; | |
1084 case Tbit: ivalue = 0; goto Livalue; | |
1085 case Tbool: ivalue = 0; goto Livalue; | |
1086 case Tchar: ivalue = 0; goto Livalue; | |
1087 case Twchar: ivalue = 0; goto Livalue; | |
1088 case Tdchar: ivalue = 0; goto Livalue; | |
1089 | |
1090 case Tcomplex32: | |
1091 case Timaginary32: | |
1092 case Tfloat32: fvalue = FLT_MIN; goto Lfvalue; | |
1093 case Tcomplex64: | |
1094 case Timaginary64: | |
1095 case Tfloat64: fvalue = DBL_MIN; goto Lfvalue; | |
1096 case Tcomplex80: | |
1097 case Timaginary80: | |
1098 case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue; | |
1099 } | |
1100 } | |
1101 else if (ident == Id::nan) | |
1102 { | |
1103 switch (ty) | |
1104 { | |
1105 case Tcomplex32: | |
1106 case Tcomplex64: | |
1107 case Tcomplex80: | |
1108 case Timaginary32: | |
1109 case Timaginary64: | |
1110 case Timaginary80: | |
1111 case Tfloat32: | |
1112 case Tfloat64: | |
1113 case Tfloat80: | |
1114 { | |
1115 #if IN_GCC | |
1116 // mode doesn't matter, will be converted in RealExp anyway | |
1117 fvalue = real_t::getnan(real_t::LongDouble); | |
1118 #elif __GNUC__ | |
1119 // gcc nan's have the sign bit set by default, so turn it off | |
1120 // Need the volatile to prevent gcc from doing incorrect | |
1121 // constant folding. | |
1122 volatile d_float80 foo; | |
1123 foo = NAN; | |
1124 if (signbit(foo)) // signbit sometimes, not always, set | |
1125 foo = -foo; // turn off sign bit | |
1126 fvalue = foo; | |
1127 #elif _MSC_VER | |
1128 unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF }; | |
1129 fvalue = *(double*)nan; | |
1130 #else | |
1131 fvalue = NAN; | |
1132 #endif | |
1133 goto Lfvalue; | |
1134 } | |
1135 } | |
1136 } | |
1137 else if (ident == Id::infinity) | |
1138 { | |
1139 switch (ty) | |
1140 { | |
1141 case Tcomplex32: | |
1142 case Tcomplex64: | |
1143 case Tcomplex80: | |
1144 case Timaginary32: | |
1145 case Timaginary64: | |
1146 case Timaginary80: | |
1147 case Tfloat32: | |
1148 case Tfloat64: | |
1149 case Tfloat80: | |
1150 #if IN_GCC | |
1151 fvalue = real_t::getinfinity(); | |
1152 #elif __GNUC__ | |
1153 fvalue = 1 / zero; | |
1154 #elif _MSC_VER | |
1155 fvalue = std::numeric_limits<long double>::infinity(); | |
1156 #else | |
1157 fvalue = INFINITY; | |
1158 #endif | |
1159 goto Lfvalue; | |
1160 } | |
1161 } | |
1162 else if (ident == Id::dig) | |
1163 { | |
1164 switch (ty) | |
1165 { | |
1166 case Tcomplex32: | |
1167 case Timaginary32: | |
1168 case Tfloat32: ivalue = FLT_DIG; goto Lint; | |
1169 case Tcomplex64: | |
1170 case Timaginary64: | |
1171 case Tfloat64: ivalue = DBL_DIG; goto Lint; | |
1172 case Tcomplex80: | |
1173 case Timaginary80: | |
1174 case Tfloat80: ivalue = LDBL_DIG; goto Lint; | |
1175 } | |
1176 } | |
1177 else if (ident == Id::epsilon) | |
1178 { | |
1179 switch (ty) | |
1180 { | |
1181 case Tcomplex32: | |
1182 case Timaginary32: | |
1183 case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue; | |
1184 case Tcomplex64: | |
1185 case Timaginary64: | |
1186 case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue; | |
1187 case Tcomplex80: | |
1188 case Timaginary80: | |
1189 case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue; | |
1190 } | |
1191 } | |
1192 else if (ident == Id::mant_dig) | |
1193 { | |
1194 switch (ty) | |
1195 { | |
1196 case Tcomplex32: | |
1197 case Timaginary32: | |
1198 case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint; | |
1199 case Tcomplex64: | |
1200 case Timaginary64: | |
1201 case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint; | |
1202 case Tcomplex80: | |
1203 case Timaginary80: | |
1204 case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint; | |
1205 } | |
1206 } | |
1207 else if (ident == Id::max_10_exp) | |
1208 { | |
1209 switch (ty) | |
1210 { | |
1211 case Tcomplex32: | |
1212 case Timaginary32: | |
1213 case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint; | |
1214 case Tcomplex64: | |
1215 case Timaginary64: | |
1216 case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint; | |
1217 case Tcomplex80: | |
1218 case Timaginary80: | |
1219 case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint; | |
1220 } | |
1221 } | |
1222 else if (ident == Id::max_exp) | |
1223 { | |
1224 switch (ty) | |
1225 { | |
1226 case Tcomplex32: | |
1227 case Timaginary32: | |
1228 case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint; | |
1229 case Tcomplex64: | |
1230 case Timaginary64: | |
1231 case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint; | |
1232 case Tcomplex80: | |
1233 case Timaginary80: | |
1234 case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint; | |
1235 } | |
1236 } | |
1237 else if (ident == Id::min_10_exp) | |
1238 { | |
1239 switch (ty) | |
1240 { | |
1241 case Tcomplex32: | |
1242 case Timaginary32: | |
1243 case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint; | |
1244 case Tcomplex64: | |
1245 case Timaginary64: | |
1246 case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint; | |
1247 case Tcomplex80: | |
1248 case Timaginary80: | |
1249 case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint; | |
1250 } | |
1251 } | |
1252 else if (ident == Id::min_exp) | |
1253 { | |
1254 switch (ty) | |
1255 { | |
1256 case Tcomplex32: | |
1257 case Timaginary32: | |
1258 case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint; | |
1259 case Tcomplex64: | |
1260 case Timaginary64: | |
1261 case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint; | |
1262 case Tcomplex80: | |
1263 case Timaginary80: | |
1264 case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint; | |
1265 } | |
1266 } | |
1267 | |
1268 Ldefault: | |
1269 return Type::getProperty(loc, ident); | |
1270 | |
1271 Livalue: | |
1272 e = new IntegerExp(loc, ivalue, this); | |
1273 return e; | |
1274 | |
1275 Lfvalue: | |
1276 if (isreal() || isimaginary()) | |
1277 e = new RealExp(loc, fvalue, this); | |
1278 else | |
1279 { | |
1280 complex_t cvalue; | |
1281 | |
1282 #if __DMC__ | |
1283 //((real_t *)&cvalue)[0] = fvalue; | |
1284 //((real_t *)&cvalue)[1] = fvalue; | |
1285 cvalue = fvalue + fvalue * I; | |
1286 #else | |
1287 cvalue.re = fvalue; | |
1288 cvalue.im = fvalue; | |
1289 #endif | |
1290 //for (int i = 0; i < 20; i++) | |
1291 // printf("%02x ", ((unsigned char *)&cvalue)[i]); | |
1292 //printf("\n"); | |
1293 e = new ComplexExp(loc, cvalue, this); | |
1294 } | |
1295 return e; | |
1296 | |
1297 Lint: | |
1298 e = new IntegerExp(loc, ivalue, Type::tint32); | |
1299 return e; | |
1300 } | |
1301 | |
1302 Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
1303 { | |
1304 #if LOGDOTEXP | |
1305 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
1306 #endif | |
1307 Type *t; | |
1308 | |
1309 if (ident == Id::re) | |
1310 { | |
1311 switch (ty) | |
1312 { | |
1313 case Tcomplex32: t = tfloat32; goto L1; | |
1314 case Tcomplex64: t = tfloat64; goto L1; | |
1315 case Tcomplex80: t = tfloat80; goto L1; | |
1316 L1: | |
1317 e = e->castTo(sc, t); | |
1318 break; | |
1319 | |
1320 case Tfloat32: | |
1321 case Tfloat64: | |
1322 case Tfloat80: | |
1323 break; | |
1324 | |
1325 case Timaginary32: t = tfloat32; goto L2; | |
1326 case Timaginary64: t = tfloat64; goto L2; | |
1327 case Timaginary80: t = tfloat80; goto L2; | |
1328 L2: | |
1329 e = new RealExp(0, 0.0, t); | |
1330 break; | |
1331 | |
1332 default: | |
1333 return Type::getProperty(e->loc, ident); | |
1334 } | |
1335 } | |
1336 else if (ident == Id::im) | |
1337 { Type *t2; | |
1338 | |
1339 switch (ty) | |
1340 { | |
1341 case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3; | |
1342 case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3; | |
1343 case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3; | |
1344 L3: | |
1345 e = e->castTo(sc, t); | |
1346 e->type = t2; | |
1347 break; | |
1348 | |
1349 case Timaginary32: t = tfloat32; goto L4; | |
1350 case Timaginary64: t = tfloat64; goto L4; | |
1351 case Timaginary80: t = tfloat80; goto L4; | |
1352 L4: | |
1353 e->type = t; | |
1354 break; | |
1355 | |
1356 case Tfloat32: | |
1357 case Tfloat64: | |
1358 case Tfloat80: | |
1359 e = new RealExp(0, 0.0, this); | |
1360 break; | |
1361 | |
1362 default: | |
1363 return Type::getProperty(e->loc, ident); | |
1364 } | |
1365 } | |
1366 else | |
1367 { | |
1368 return Type::dotExp(sc, e, ident); | |
1369 } | |
1370 return e; | |
1371 } | |
1372 | |
1373 Expression *TypeBasic::defaultInit(Loc loc) | |
1374 { integer_t value = 0; | |
1375 | |
1376 #if LOGDEFAULTINIT | |
1377 printf("TypeBasic::defaultInit() '%s'\n", toChars()); | |
1378 #endif | |
1379 switch (ty) | |
1380 { | |
591
e6bcc4d9e5ff
Add _d_newarrayvT and _d_newarraymvT to create arrays without initialization.
Christian Kamm <kamm incasoftware de>
parents:
585
diff
changeset
|
1381 case Tvoid: |
e6bcc4d9e5ff
Add _d_newarrayvT and _d_newarraymvT to create arrays without initialization.
Christian Kamm <kamm incasoftware de>
parents:
585
diff
changeset
|
1382 return new IntegerExp(loc, value, Type::tbool); |
e6bcc4d9e5ff
Add _d_newarrayvT and _d_newarraymvT to create arrays without initialization.
Christian Kamm <kamm incasoftware de>
parents:
585
diff
changeset
|
1383 |
159 | 1384 case Tchar: |
1385 value = 0xFF; | |
1386 break; | |
1387 | |
1388 case Twchar: | |
1389 case Tdchar: | |
1390 value = 0xFFFF; | |
1391 break; | |
1392 | |
1393 case Timaginary32: | |
1394 case Timaginary64: | |
1395 case Timaginary80: | |
1396 case Tfloat32: | |
1397 case Tfloat64: | |
1398 case Tfloat80: | |
1399 case Tcomplex32: | |
1400 case Tcomplex64: | |
1401 case Tcomplex80: | |
1402 return getProperty(loc, Id::nan); | |
1403 } | |
1404 return new IntegerExp(loc, value, this); | |
1405 } | |
1406 | |
1407 int TypeBasic::isZeroInit() | |
1408 { | |
1409 switch (ty) | |
1410 { | |
1411 case Tchar: | |
1412 case Twchar: | |
1413 case Tdchar: | |
1414 case Timaginary32: | |
1415 case Timaginary64: | |
1416 case Timaginary80: | |
1417 case Tfloat32: | |
1418 case Tfloat64: | |
1419 case Tfloat80: | |
1420 case Tcomplex32: | |
1421 case Tcomplex64: | |
1422 case Tcomplex80: | |
1423 return 0; // no | |
1424 } | |
1425 return 1; // yes | |
1426 } | |
1427 | |
1428 int TypeBasic::isbit() | |
1429 { | |
1430 return (ty == Tbit); | |
1431 } | |
1432 | |
1433 int TypeBasic::isintegral() | |
1434 { | |
1435 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags); | |
1436 return flags & TFLAGSintegral; | |
1437 } | |
1438 | |
1439 int TypeBasic::isfloating() | |
1440 { | |
1441 return flags & TFLAGSfloating; | |
1442 } | |
1443 | |
1444 int TypeBasic::isreal() | |
1445 { | |
1446 return flags & TFLAGSreal; | |
1447 } | |
1448 | |
1449 int TypeBasic::isimaginary() | |
1450 { | |
1451 return flags & TFLAGSimaginary; | |
1452 } | |
1453 | |
1454 int TypeBasic::iscomplex() | |
1455 { | |
1456 return flags & TFLAGScomplex; | |
1457 } | |
1458 | |
1459 int TypeBasic::isunsigned() | |
1460 { | |
1461 return flags & TFLAGSunsigned; | |
1462 } | |
1463 | |
1464 int TypeBasic::isscalar() | |
1465 { | |
1466 return flags & (TFLAGSintegral | TFLAGSfloating); | |
1467 } | |
1468 | |
1469 MATCH TypeBasic::implicitConvTo(Type *to) | |
1470 { | |
1471 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars()); | |
1472 if (this == to) | |
1473 return MATCHexact; | |
1474 | |
1475 if (ty == Tvoid || to->ty == Tvoid) | |
1476 return MATCHnomatch; | |
1477 if (1 || global.params.Dversion == 1) | |
1478 { | |
1479 if (to->ty == Tbool) | |
1480 return MATCHnomatch; | |
1481 } | |
1482 else | |
1483 { | |
1484 if (ty == Tbool || to->ty == Tbool) | |
1485 return MATCHnomatch; | |
1486 } | |
1487 if (!to->isTypeBasic()) | |
1488 return MATCHnomatch; | |
1489 | |
1490 TypeBasic *tob = (TypeBasic *)to; | |
1491 if (flags & TFLAGSintegral) | |
1492 { | |
1493 // Disallow implicit conversion of integers to imaginary or complex | |
1494 if (tob->flags & (TFLAGSimaginary | TFLAGScomplex)) | |
1495 return MATCHnomatch; | |
1496 | |
1497 // If converting to integral | |
1498 if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral) | |
1499 { d_uns64 sz = size(0); | |
1500 d_uns64 tosz = tob->size(0); | |
1501 | |
1502 /* Can't convert to smaller size or, if same size, change sign | |
1503 */ | |
1504 if (sz > tosz) | |
1505 return MATCHnomatch; | |
1506 | |
1507 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned) | |
1508 return MATCHnomatch;*/ | |
1509 } | |
1510 } | |
1511 else if (flags & TFLAGSfloating) | |
1512 { | |
1513 // Disallow implicit conversion of floating point to integer | |
1514 if (tob->flags & TFLAGSintegral) | |
1515 return MATCHnomatch; | |
1516 | |
1517 assert(tob->flags & TFLAGSfloating); | |
1518 | |
1519 // Disallow implicit conversion from complex to non-complex | |
1520 if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex)) | |
1521 return MATCHnomatch; | |
1522 | |
1523 // Disallow implicit conversion of real or imaginary to complex | |
1524 if (flags & (TFLAGSreal | TFLAGSimaginary) && | |
1525 tob->flags & TFLAGScomplex) | |
1526 return MATCHnomatch; | |
1527 | |
1528 // Disallow implicit conversion to-from real and imaginary | |
1529 if ((flags & (TFLAGSreal | TFLAGSimaginary)) != | |
1530 (tob->flags & (TFLAGSreal | TFLAGSimaginary))) | |
1531 return MATCHnomatch; | |
1532 } | |
1533 return MATCHconvert; | |
1534 } | |
1535 | |
1536 TypeBasic *TypeBasic::isTypeBasic() | |
1537 { | |
1538 return (TypeBasic *)this; | |
1539 } | |
1540 | |
1541 /***************************** TypeArray *****************************/ | |
1542 | |
1543 TypeArray::TypeArray(TY ty, Type *next) | |
1544 : Type(ty, next) | |
1545 { | |
1546 } | |
1547 | |
1548 Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
1549 { | |
1550 Type *n = this->next->toBasetype(); // uncover any typedef's | |
1551 | |
1552 #if LOGDOTEXP | |
1553 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
1554 #endif | |
1555 if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar)) | |
1556 { | |
1557 Expression *ec; | |
1558 Expressions *arguments; | |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1559 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
1560 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1561 static FuncDeclaration *adReverseChar_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1562 if(!adReverseChar_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1563 Arguments* args = new Arguments; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1564 Type* arrty = Type::tchar->arrayOf(); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1565 args->push(new Argument(STCin, arrty, NULL, NULL)); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1566 adReverseChar_fd = FuncDeclaration::genCfunc(args, arrty, "_adReverseChar"); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1567 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1568 static FuncDeclaration *adReverseWchar_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1569 if(!adReverseWchar_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1570 Arguments* args = new Arguments; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1571 Type* arrty = Type::twchar->arrayOf(); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1572 args->push(new Argument(STCin, arrty, NULL, NULL)); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1573 adReverseWchar_fd = FuncDeclaration::genCfunc(args, arrty, "_adReverseWchar"); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1574 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1575 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1576 if(n->ty == Twchar) |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1577 ec = new VarExp(0, adReverseWchar_fd); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1578 else |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1579 ec = new VarExp(0, adReverseChar_fd); |
159 | 1580 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array |
1581 arguments = new Expressions(); | |
1582 arguments->push(e); | |
1583 e = new CallExp(e->loc, ec, arguments); | |
1584 e->type = next->arrayOf(); | |
1585 } | |
1586 else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar)) | |
1587 { | |
1588 Expression *ec; | |
1589 Expressions *arguments; | |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1590 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
1591 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1592 static FuncDeclaration *adSortChar_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1593 if(!adSortChar_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1594 Arguments* args = new Arguments; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1595 Type* arrty = Type::tchar->arrayOf(); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1596 args->push(new Argument(STCin, arrty, NULL, NULL)); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1597 adSortChar_fd = FuncDeclaration::genCfunc(args, arrty, "_adSortChar"); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1598 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1599 static FuncDeclaration *adSortWchar_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1600 if(!adSortWchar_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1601 Arguments* args = new Arguments; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1602 Type* arrty = Type::twchar->arrayOf(); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1603 args->push(new Argument(STCin, arrty, NULL, NULL)); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1604 adSortWchar_fd = FuncDeclaration::genCfunc(args, arrty, "_adSortWchar"); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1605 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1606 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1607 if(n->ty == Twchar) |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1608 ec = new VarExp(0, adSortWchar_fd); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1609 else |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1610 ec = new VarExp(0, adSortChar_fd); |
159 | 1611 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array |
1612 arguments = new Expressions(); | |
1613 arguments->push(e); | |
1614 e = new CallExp(e->loc, ec, arguments); | |
1615 e->type = next->arrayOf(); | |
1616 } | |
1617 else if (ident == Id::reverse || ident == Id::dup) | |
1618 { | |
1619 Expression *ec; | |
1620 Expressions *arguments; | |
1621 int size = next->size(e->loc); | |
1622 int dup; | |
1623 | |
1624 assert(size); | |
1625 dup = (ident == Id::dup); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
1626 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1627 static FuncDeclaration *adDup_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1628 if(!adDup_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1629 Arguments* args = new Arguments; |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
375
diff
changeset
|
1630 args->push(new Argument(STCin, Type::typeinfo->type, NULL, NULL)); |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1631 args->push(new Argument(STCin, Type::tvoid->arrayOf(), NULL, NULL)); |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1632 adDup_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::adDup); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1633 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1634 static FuncDeclaration *adReverse_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1635 if(!adReverse_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1636 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1637 args->push(new Argument(STCin, Type::tvoid->arrayOf(), NULL, NULL)); |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
375
diff
changeset
|
1638 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1639 adReverse_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::adReverse); |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
375
diff
changeset
|
1640 } |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1641 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1642 if(dup) |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1643 ec = new VarExp(0, adDup_fd); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1644 else |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1645 ec = new VarExp(0, adReverse_fd); |
159 | 1646 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array |
1647 arguments = new Expressions(); | |
1648 if (dup) | |
1649 arguments->push(getTypeInfo(sc)); | |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1650 |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1651 // LDC repaint array type to void[] |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1652 if (n->ty != Tvoid) { |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1653 e = new CastExp(e->loc, e, e->type); |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1654 e->type = Type::tvoid->arrayOf(); |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1655 } |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1656 arguments->push(e); |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1657 |
159 | 1658 if (!dup) |
1659 arguments->push(new IntegerExp(0, size, Type::tint32)); | |
1660 e = new CallExp(e->loc, ec, arguments); | |
1661 e->type = next->arrayOf(); | |
1662 } | |
1663 else if (ident == Id::sort) | |
1664 { | |
1665 Expression *ec; | |
1666 Expressions *arguments; | |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1667 bool isBit = (n->ty == Tbit); |
159 | 1668 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
1669 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1670 static FuncDeclaration *adSort_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1671 if(!adSort_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1672 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1673 args->push(new Argument(STCin, Type::tvoid->arrayOf(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1674 args->push(new Argument(STCin, Type::typeinfo->type, NULL, NULL)); |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1675 adSort_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSort"); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1676 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1677 static FuncDeclaration *adSortBit_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1678 if(!adSortBit_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1679 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1680 args->push(new Argument(STCin, Type::tvoid->arrayOf(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1681 args->push(new Argument(STCin, Type::typeinfo->type, NULL, NULL)); |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1682 adSortBit_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSortBit"); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1683 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1684 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1685 if(isBit) |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1686 ec = new VarExp(0, adSortBit_fd); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1687 else |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
1688 ec = new VarExp(0, adSort_fd); |
159 | 1689 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array |
1690 arguments = new Expressions(); | |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1691 |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1692 // LDC repaint array type to void[] |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1693 if (n->ty != Tvoid) { |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1694 e = new CastExp(e->loc, e, e->type); |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1695 e->type = Type::tvoid->arrayOf(); |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1696 } |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1697 arguments->push(e); |
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1698 |
509
337554fd34f1
Fixed mini/missingti.d
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
489
diff
changeset
|
1699 if (next->ty != Tbit) |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
1700 arguments->push(n->getTypeInfo(sc)); // LDC, we don't support the getInternalTypeInfo |
509
337554fd34f1
Fixed mini/missingti.d
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
489
diff
changeset
|
1701 // optimization arbitrarily, not yet at least... |
159 | 1702 e = new CallExp(e->loc, ec, arguments); |
1703 e->type = next->arrayOf(); | |
1704 } | |
1705 else | |
1706 { | |
1707 e = Type::dotExp(sc, e, ident); | |
1708 } | |
1709 return e; | |
1710 } | |
1711 | |
1712 | |
1713 /***************************** TypeSArray *****************************/ | |
1714 | |
1715 TypeSArray::TypeSArray(Type *t, Expression *dim) | |
1716 : TypeArray(Tsarray, t) | |
1717 { | |
1718 //printf("TypeSArray(%s)\n", dim->toChars()); | |
1719 this->dim = dim; | |
1720 } | |
1721 | |
1722 Type *TypeSArray::syntaxCopy() | |
1723 { | |
1724 Type *t = next->syntaxCopy(); | |
1725 Expression *e = dim->syntaxCopy(); | |
1726 t = new TypeSArray(t, e); | |
1727 return t; | |
1728 } | |
1729 | |
1730 d_uns64 TypeSArray::size(Loc loc) | |
1731 { integer_t sz; | |
1732 | |
1733 if (!dim) | |
1734 return Type::size(loc); | |
1735 sz = dim->toInteger(); | |
1736 if (next->toBasetype()->ty == Tbit) // if array of bits | |
1737 { | |
1738 if (sz + 31 < sz) | |
1739 goto Loverflow; | |
1740 sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords | |
1741 } | |
1742 else | |
1743 { integer_t n, n2; | |
1744 | |
1745 n = next->size(); | |
1746 n2 = n * sz; | |
1747 if (n && (n2 / n) != sz) | |
1748 goto Loverflow; | |
1749 sz = n2; | |
1750 } | |
1751 return sz; | |
1752 | |
1753 Loverflow: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1754 error(loc, "index %lld overflow for static array", sz); |
159 | 1755 return 1; |
1756 } | |
1757 | |
1758 unsigned TypeSArray::alignsize() | |
1759 { | |
1760 return next->alignsize(); | |
1761 } | |
1762 | |
1763 /************************** | |
1764 * This evaluates exp while setting length to be the number | |
1765 * of elements in the tuple t. | |
1766 */ | |
1767 Expression *semanticLength(Scope *sc, Type *t, Expression *exp) | |
1768 { | |
1769 if (t->ty == Ttuple) | |
1770 { ScopeDsymbol *sym = new ArrayScopeSymbol((TypeTuple *)t); | |
1771 sym->parent = sc->scopesym; | |
1772 sc = sc->push(sym); | |
1773 | |
1774 exp = exp->semantic(sc); | |
1775 | |
1776 sc->pop(); | |
1777 } | |
1778 else | |
1779 exp = exp->semantic(sc); | |
1780 return exp; | |
1781 } | |
1782 | |
1783 Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp) | |
1784 { | |
1785 ScopeDsymbol *sym = new ArrayScopeSymbol(s); | |
1786 sym->parent = sc->scopesym; | |
1787 sc = sc->push(sym); | |
1788 | |
1789 exp = exp->semantic(sc); | |
1790 | |
1791 sc->pop(); | |
1792 return exp; | |
1793 } | |
1794 | |
1795 void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) | |
1796 { | |
1797 //printf("TypeSArray::resolve() %s\n", toChars()); | |
1798 next->resolve(loc, sc, pe, pt, ps); | |
1799 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); | |
1800 if (*pe) | |
1801 { // It's really an index expression | |
1802 Expression *e; | |
1803 e = new IndexExp(loc, *pe, dim); | |
1804 *pe = e; | |
1805 } | |
1806 else if (*ps) | |
1807 { Dsymbol *s = *ps; | |
1808 TupleDeclaration *td = s->isTupleDeclaration(); | |
1809 if (td) | |
1810 { | |
1811 ScopeDsymbol *sym = new ArrayScopeSymbol(td); | |
1812 sym->parent = sc->scopesym; | |
1813 sc = sc->push(sym); | |
1814 | |
1815 dim = dim->semantic(sc); | |
1816 dim = dim->optimize(WANTvalue | WANTinterpret); | |
1817 uinteger_t d = dim->toUInteger(); | |
1818 | |
1819 sc = sc->pop(); | |
1820 | |
1821 if (d >= td->objects->dim) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1822 { error(loc, "tuple index %llu exceeds %u", d, td->objects->dim); |
159 | 1823 goto Ldefault; |
1824 } | |
1825 Object *o = (Object *)td->objects->data[(size_t)d]; | |
1826 if (o->dyncast() == DYNCAST_DSYMBOL) | |
1827 { | |
1828 *ps = (Dsymbol *)o; | |
1829 return; | |
1830 } | |
1831 if (o->dyncast() == DYNCAST_EXPRESSION) | |
1832 { | |
1833 *ps = NULL; | |
1834 *pe = (Expression *)o; | |
1835 return; | |
1836 } | |
1837 | |
1838 /* Create a new TupleDeclaration which | |
1839 * is a slice [d..d+1] out of the old one. | |
1840 * Do it this way because TemplateInstance::semanticTiargs() | |
1841 * can handle unresolved Objects this way. | |
1842 */ | |
1843 Objects *objects = new Objects; | |
1844 objects->setDim(1); | |
1845 objects->data[0] = o; | |
1846 | |
1847 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects); | |
1848 *ps = tds; | |
1849 } | |
1850 else | |
1851 goto Ldefault; | |
1852 } | |
1853 else | |
1854 { | |
1855 Ldefault: | |
1856 Type::resolve(loc, sc, pe, pt, ps); | |
1857 } | |
1858 } | |
1859 | |
1860 Type *TypeSArray::semantic(Loc loc, Scope *sc) | |
1861 { | |
1862 //printf("TypeSArray::semantic() %s\n", toChars()); | |
1863 | |
1864 Type *t; | |
1865 Expression *e; | |
1866 Dsymbol *s; | |
1867 next->resolve(loc, sc, &e, &t, &s); | |
1868 if (dim && s && s->isTupleDeclaration()) | |
1869 { TupleDeclaration *sd = s->isTupleDeclaration(); | |
1870 | |
1871 dim = semanticLength(sc, sd, dim); | |
1872 dim = dim->optimize(WANTvalue | WANTinterpret); | |
1873 uinteger_t d = dim->toUInteger(); | |
1874 | |
1875 if (d >= sd->objects->dim) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1876 { error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim); |
159 | 1877 return Type::terror; |
1878 } | |
1879 Object *o = (Object *)sd->objects->data[(size_t)d]; | |
1880 if (o->dyncast() != DYNCAST_TYPE) | |
1881 { error(loc, "%s is not a type", toChars()); | |
1882 return Type::terror; | |
1883 } | |
1884 t = (Type *)o; | |
1885 return t; | |
1886 } | |
1887 | |
1888 next = next->semantic(loc,sc); | |
1889 Type *tbn = next->toBasetype(); | |
1890 | |
1891 if (dim) | |
1892 { integer_t n, n2; | |
1893 | |
1894 dim = semanticLength(sc, tbn, dim); | |
1895 | |
1896 dim = dim->optimize(WANTvalue | WANTinterpret); | |
1897 if (sc->parameterSpecialization && dim->op == TOKvar && | |
1898 ((VarExp *)dim)->var->storage_class & STCtemplateparameter) | |
1899 { | |
1900 /* It could be a template parameter N which has no value yet: | |
1901 * template Foo(T : T[N], size_t N); | |
1902 */ | |
1903 return this; | |
1904 } | |
1905 integer_t d1 = dim->toInteger(); | |
1906 dim = dim->castTo(sc, tsize_t); | |
1907 dim = dim->optimize(WANTvalue); | |
1908 integer_t d2 = dim->toInteger(); | |
1909 | |
1910 if (d1 != d2) | |
1911 goto Loverflow; | |
1912 | |
1913 if (tbn->isintegral() || | |
1914 tbn->isfloating() || | |
1915 tbn->ty == Tpointer || | |
1916 tbn->ty == Tarray || | |
1917 tbn->ty == Tsarray || | |
1918 tbn->ty == Taarray || | |
1919 tbn->ty == Tclass) | |
1920 { | |
1921 /* Only do this for types that don't need to have semantic() | |
1922 * run on them for the size, since they may be forward referenced. | |
1923 */ | |
1924 n = tbn->size(loc); | |
1925 n2 = n * d2; | |
1926 if ((int)n2 < 0) | |
1927 goto Loverflow; | |
1928 if (n2 >= 0x1000000) // put a 'reasonable' limit on it | |
1929 goto Loverflow; | |
1930 if (n && n2 / n != d2) | |
1931 { | |
1932 Loverflow: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1933 error(loc, "index %lld overflow for static array", d1); |
159 | 1934 dim = new IntegerExp(0, 1, tsize_t); |
1935 } | |
1936 } | |
1937 } | |
1938 switch (tbn->ty) | |
1939 { | |
1940 case Ttuple: | |
1941 { // Index the tuple to get the type | |
1942 assert(dim); | |
1943 TypeTuple *tt = (TypeTuple *)tbn; | |
1944 uinteger_t d = dim->toUInteger(); | |
1945 | |
1946 if (d >= tt->arguments->dim) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1947 { error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim); |
159 | 1948 return Type::terror; |
1949 } | |
1950 Argument *arg = (Argument *)tt->arguments->data[(size_t)d]; | |
1951 return arg->type; | |
1952 } | |
1953 case Tfunction: | |
1954 case Tnone: | |
1955 error(loc, "can't have array of %s", tbn->toChars()); | |
1956 tbn = next = tint32; | |
1957 break; | |
1958 } | |
1959 if (tbn->isauto()) | |
1960 error(loc, "cannot have array of auto %s", tbn->toChars()); | |
1961 return merge(); | |
1962 } | |
1963 | |
1964 void TypeSArray::toDecoBuffer(OutBuffer *buf) | |
1965 { | |
1966 buf->writeByte(mangleChar[ty]); | |
1967 if (dim) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1968 buf->printf("%llu", dim->toInteger()); |
159 | 1969 if (next) |
1970 next->toDecoBuffer(buf); | |
1971 } | |
1972 | |
1973 void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
1974 { | |
1975 if (mod != this->mod) | |
1976 { toCBuffer3(buf, hgs, mod); | |
1977 return; | |
1978 } | |
1979 next->toCBuffer2(buf, hgs, this->mod); | |
1980 buf->printf("[%s]", dim->toChars()); | |
1981 } | |
1982 | |
1983 Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
1984 { | |
1985 #if LOGDOTEXP | |
1986 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
1987 #endif | |
1988 if (ident == Id::length) | |
1989 { | |
1990 e = dim; | |
1991 } | |
1992 else if (ident == Id::ptr) | |
1993 { | |
1994 e = e->castTo(sc, next->pointerTo()); | |
1995 } | |
1996 else | |
1997 { | |
1998 e = TypeArray::dotExp(sc, e, ident); | |
1999 } | |
2000 return e; | |
2001 } | |
2002 | |
2003 int TypeSArray::isString() | |
2004 { | |
2005 TY nty = next->toBasetype()->ty; | |
2006 return nty == Tchar || nty == Twchar || nty == Tdchar; | |
2007 } | |
2008 | |
2009 unsigned TypeSArray::memalign(unsigned salign) | |
2010 { | |
2011 return next->memalign(salign); | |
2012 } | |
2013 | |
2014 MATCH TypeSArray::implicitConvTo(Type *to) | |
2015 { | |
2016 //printf("TypeSArray::implicitConvTo()\n"); | |
2017 | |
2018 // Allow implicit conversion of static array to pointer or dynamic array | |
2019 if ((IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer) && | |
2020 (to->next->ty == Tvoid || next->equals(to->next) | |
2021 /*|| to->next->isBaseOf(next)*/)) | |
2022 { | |
2023 return MATCHconvert; | |
2024 } | |
2025 if (to->ty == Tarray) | |
2026 { int offset = 0; | |
2027 | |
2028 if (next->equals(to->next) || | |
2029 (to->next->isBaseOf(next, &offset) && offset == 0) || | |
2030 to->next->ty == Tvoid) | |
2031 return MATCHconvert; | |
2032 } | |
2033 #if 0 | |
2034 if (to->ty == Tsarray) | |
2035 { | |
2036 TypeSArray *tsa = (TypeSArray *)to; | |
2037 | |
2038 if (next->equals(tsa->next) && dim->equals(tsa->dim)) | |
2039 { | |
2040 return MATCHconvert; | |
2041 } | |
2042 } | |
2043 #endif | |
2044 return Type::implicitConvTo(to); | |
2045 } | |
2046 | |
2047 Expression *TypeSArray::defaultInit(Loc loc) | |
2048 { | |
2049 #if LOGDEFAULTINIT | |
2050 printf("TypeSArray::defaultInit() '%s'\n", toChars()); | |
2051 #endif | |
2052 return next->defaultInit(loc); | |
2053 } | |
2054 | |
2055 int TypeSArray::isZeroInit() | |
2056 { | |
2057 return next->isZeroInit(); | |
2058 } | |
2059 | |
2060 | |
2061 Expression *TypeSArray::toExpression() | |
2062 { | |
2063 Expression *e = next->toExpression(); | |
2064 if (e) | |
2065 { Expressions *arguments = new Expressions(); | |
2066 arguments->push(dim); | |
2067 e = new ArrayExp(dim->loc, e, arguments); | |
2068 } | |
2069 return e; | |
2070 } | |
2071 | |
2072 int TypeSArray::hasPointers() | |
2073 { | |
2074 return next->hasPointers(); | |
2075 } | |
2076 | |
2077 /***************************** TypeDArray *****************************/ | |
2078 | |
2079 TypeDArray::TypeDArray(Type *t) | |
2080 : TypeArray(Tarray, t) | |
2081 { | |
2082 //printf("TypeDArray(t = %p)\n", t); | |
2083 } | |
2084 | |
2085 Type *TypeDArray::syntaxCopy() | |
2086 { | |
2087 Type *t = next->syntaxCopy(); | |
2088 if (t == next) | |
2089 t = this; | |
2090 else | |
2091 t = new TypeDArray(t); | |
2092 return t; | |
2093 } | |
2094 | |
2095 d_uns64 TypeDArray::size(Loc loc) | |
2096 { | |
2097 //printf("TypeDArray::size()\n"); | |
2098 return PTRSIZE * 2; | |
2099 } | |
2100 | |
2101 unsigned TypeDArray::alignsize() | |
2102 { | |
2103 // A DArray consists of two ptr-sized values, so align it on pointer size | |
2104 // boundary | |
2105 return PTRSIZE; | |
2106 } | |
2107 | |
2108 Type *TypeDArray::semantic(Loc loc, Scope *sc) | |
2109 { Type *tn = next; | |
2110 | |
2111 tn = next->semantic(loc,sc); | |
2112 Type *tbn = tn->toBasetype(); | |
2113 switch (tbn->ty) | |
2114 { | |
2115 case Tfunction: | |
2116 case Tnone: | |
2117 case Ttuple: | |
2118 error(loc, "can't have array of %s", tbn->toChars()); | |
2119 tn = next = tint32; | |
2120 break; | |
2121 } | |
2122 if (tn->isauto()) | |
2123 error(loc, "cannot have array of auto %s", tn->toChars()); | |
2124 if (next != tn) | |
2125 //deco = NULL; // redo | |
2126 return tn->arrayOf(); | |
2127 return merge(); | |
2128 } | |
2129 | |
2130 void TypeDArray::toDecoBuffer(OutBuffer *buf) | |
2131 { | |
2132 buf->writeByte(mangleChar[ty]); | |
2133 if (next) | |
2134 next->toDecoBuffer(buf); | |
2135 } | |
2136 | |
2137 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
2138 { | |
2139 if (mod != this->mod) | |
2140 { toCBuffer3(buf, hgs, mod); | |
2141 return; | |
2142 } | |
2143 next->toCBuffer2(buf, hgs, this->mod); | |
2144 buf->writestring("[]"); | |
2145 } | |
2146 | |
2147 Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
2148 { | |
2149 #if LOGDOTEXP | |
2150 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
2151 #endif | |
2152 if (ident == Id::length) | |
2153 { | |
2154 if (e->op == TOKstring) | |
2155 { StringExp *se = (StringExp *)e; | |
2156 | |
2157 return new IntegerExp(se->loc, se->len, Type::tindex); | |
2158 } | |
2159 e = new ArrayLengthExp(e->loc, e); | |
2160 e->type = Type::tsize_t; | |
2161 return e; | |
2162 } | |
2163 else if (ident == Id::ptr) | |
2164 { | |
2165 e = e->castTo(sc, next->pointerTo()); | |
2166 return e; | |
2167 } | |
2168 else | |
2169 { | |
2170 e = TypeArray::dotExp(sc, e, ident); | |
2171 } | |
2172 return e; | |
2173 } | |
2174 | |
2175 int TypeDArray::isString() | |
2176 { | |
2177 TY nty = next->toBasetype()->ty; | |
2178 return nty == Tchar || nty == Twchar || nty == Tdchar; | |
2179 } | |
2180 | |
2181 MATCH TypeDArray::implicitConvTo(Type *to) | |
2182 { | |
2183 //printf("TypeDArray::implicitConvTo()\n"); | |
2184 | |
2185 // Allow implicit conversion of array to pointer | |
2186 if (IMPLICIT_ARRAY_TO_PTR && | |
2187 to->ty == Tpointer && | |
2188 (to->next->ty == Tvoid || next->equals(to->next) /*|| to->next->isBaseOf(next)*/)) | |
2189 { | |
2190 return MATCHconvert; | |
2191 } | |
2192 | |
2193 if (to->ty == Tarray) | |
2194 { int offset = 0; | |
2195 | |
2196 if ((to->next->isBaseOf(next, &offset) && offset == 0) || | |
2197 to->next->ty == Tvoid) | |
2198 return MATCHconvert; | |
2199 } | |
2200 return Type::implicitConvTo(to); | |
2201 } | |
2202 | |
2203 Expression *TypeDArray::defaultInit(Loc loc) | |
2204 { | |
2205 #if LOGDEFAULTINIT | |
2206 printf("TypeDArray::defaultInit() '%s'\n", toChars()); | |
2207 #endif | |
2208 Expression *e; | |
2209 e = new NullExp(loc); | |
2210 e->type = this; | |
2211 return e; | |
2212 } | |
2213 | |
2214 int TypeDArray::isZeroInit() | |
2215 { | |
2216 return 1; | |
2217 } | |
2218 | |
2219 int TypeDArray::checkBoolean() | |
2220 { | |
2221 return TRUE; | |
2222 } | |
2223 | |
2224 int TypeDArray::hasPointers() | |
2225 { | |
2226 return TRUE; | |
2227 } | |
2228 | |
2229 /***************************** TypeAArray *****************************/ | |
2230 | |
2231 TypeAArray::TypeAArray(Type *t, Type *index) | |
2232 : TypeArray(Taarray, t) | |
2233 { | |
2234 this->index = index; | |
2235 this->key = NULL; | |
2236 } | |
2237 | |
2238 Type *TypeAArray::syntaxCopy() | |
2239 { | |
2240 Type *t = next->syntaxCopy(); | |
2241 Type *ti = index->syntaxCopy(); | |
2242 if (t == next && ti == index) | |
2243 t = this; | |
2244 else | |
2245 t = new TypeAArray(t, ti); | |
2246 return t; | |
2247 } | |
2248 | |
2249 d_uns64 TypeAArray::size(Loc loc) | |
2250 { | |
2251 return PTRSIZE /* * 2*/; | |
2252 } | |
2253 | |
2254 | |
2255 Type *TypeAArray::semantic(Loc loc, Scope *sc) | |
2256 { | |
2257 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty); | |
2258 | |
2259 // Deal with the case where we thought the index was a type, but | |
2260 // in reality it was an expression. | |
2261 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray) | |
2262 { | |
2263 Expression *e; | |
2264 Type *t; | |
2265 Dsymbol *s; | |
2266 | |
2267 index->resolve(loc, sc, &e, &t, &s); | |
2268 if (e) | |
2269 { // It was an expression - | |
2270 // Rewrite as a static array | |
2271 TypeSArray *tsa; | |
2272 | |
2273 tsa = new TypeSArray(next, e); | |
2274 return tsa->semantic(loc,sc); | |
2275 } | |
2276 else if (t) | |
2277 index = t; | |
2278 else | |
2279 index->error(loc, "index is not a type or an expression"); | |
2280 } | |
2281 else | |
2282 index = index->semantic(loc,sc); | |
2283 | |
2284 // Compute key type; the purpose of the key type is to | |
2285 // minimize the permutations of runtime library | |
2286 // routines as much as possible. | |
2287 key = index->toBasetype(); | |
2288 switch (key->ty) | |
2289 { | |
2290 #if 0 | |
2291 case Tint8: | |
2292 case Tuns8: | |
2293 case Tint16: | |
2294 case Tuns16: | |
2295 key = tint32; | |
2296 break; | |
2297 #endif | |
2298 | |
2299 case Tsarray: | |
2300 #if 0 | |
2301 // Convert to Tarray | |
2302 key = key->next->arrayOf(); | |
2303 #endif | |
2304 break; | |
2305 case Tbit: | |
2306 case Tbool: | |
2307 case Tfunction: | |
2308 case Tvoid: | |
2309 case Tnone: | |
2310 error(loc, "can't have associative array key of %s", key->toChars()); | |
2311 break; | |
2312 } | |
2313 next = next->semantic(loc,sc); | |
2314 switch (next->toBasetype()->ty) | |
2315 { | |
2316 case Tfunction: | |
2317 case Tnone: | |
2318 error(loc, "can't have associative array of %s", next->toChars()); | |
2319 break; | |
2320 } | |
2321 if (next->isauto()) | |
2322 error(loc, "cannot have array of auto %s", next->toChars()); | |
2323 | |
2324 return merge(); | |
2325 } | |
2326 | |
336 | 2327 void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) |
2328 { | |
2329 //printf("TypeAArray::resolve() %s\n", toChars()); | |
2330 | |
2331 // Deal with the case where we thought the index was a type, but | |
2332 // in reality it was an expression. | |
2333 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray) | |
2334 { | |
2335 Expression *e; | |
2336 Type *t; | |
2337 Dsymbol *s; | |
2338 | |
2339 index->resolve(loc, sc, &e, &t, &s); | |
2340 if (e) | |
2341 { // It was an expression - | |
2342 // Rewrite as a static array | |
2343 | |
2344 TypeSArray *tsa = new TypeSArray(next, e); | |
2345 return tsa->resolve(loc, sc, pe, pt, ps); | |
2346 } | |
2347 else if (t) | |
2348 index = t; | |
2349 else | |
2350 index->error(loc, "index is not a type or an expression"); | |
2351 } | |
2352 Type::resolve(loc, sc, pe, pt, ps); | |
2353 } | |
2354 | |
2355 | |
159 | 2356 Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) |
2357 { | |
2358 #if LOGDOTEXP | |
2359 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
2360 #endif | |
2361 if (ident == Id::length) | |
2362 { | |
2363 Expression *ec; | |
2364 Expressions *arguments; | |
2365 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
2366 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2367 static FuncDeclaration *aaLen_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2368 if(!aaLen_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2369 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2370 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2371 aaLen_fd = FuncDeclaration::genCfunc(args, Type::tsize_t, Id::aaLen); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2372 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2373 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2374 ec = new VarExp(0, aaLen_fd); |
159 | 2375 arguments = new Expressions(); |
2376 arguments->push(e); | |
2377 e = new CallExp(e->loc, ec, arguments); | |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2378 e->type = aaLen_fd->type->next; |
159 | 2379 } |
2380 else if (ident == Id::keys) | |
2381 { | |
2382 Expression *ec; | |
2383 Expressions *arguments; | |
2384 int size = key->size(e->loc); | |
2385 | |
2386 assert(size); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
2387 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2388 static FuncDeclaration *aaKeys_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2389 if(!aaKeys_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2390 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2391 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2392 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2393 aaKeys_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::aaKeys); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2394 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2395 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2396 ec = new VarExp(0, aaKeys_fd); |
159 | 2397 arguments = new Expressions(); |
2398 arguments->push(e); | |
2399 arguments->push(new IntegerExp(0, size, Type::tsize_t)); | |
2400 e = new CallExp(e->loc, ec, arguments); | |
2401 e->type = index->arrayOf(); | |
2402 } | |
2403 else if (ident == Id::values) | |
2404 { | |
2405 Expression *ec; | |
2406 Expressions *arguments; | |
2407 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
2408 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2409 static FuncDeclaration *aaValues_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2410 if(!aaValues_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2411 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2412 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2413 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2414 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2415 aaValues_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::aaValues); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2416 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2417 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2418 ec = new VarExp(0, aaValues_fd); |
159 | 2419 arguments = new Expressions(); |
2420 arguments->push(e); | |
2421 size_t keysize = key->size(e->loc); | |
771
bfabbac8e705
Fixed 64bit problem with aaValues runtime calls (assumed 32bits)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
742
diff
changeset
|
2422 keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1); |
159 | 2423 arguments->push(new IntegerExp(0, keysize, Type::tsize_t)); |
2424 arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t)); | |
2425 e = new CallExp(e->loc, ec, arguments); | |
2426 e->type = next->arrayOf(); | |
2427 } | |
2428 else if (ident == Id::rehash) | |
2429 { | |
2430 Expression *ec; | |
2431 Expressions *arguments; | |
2432 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
2433 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2434 static FuncDeclaration *aaRehash_fd = NULL; |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2435 if(!aaRehash_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2436 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2437 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2438 args->push(new Argument(STCin, Type::typeinfo->type, NULL, NULL)); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2439 aaRehash_fd = FuncDeclaration::genCfunc(args, Type::tvoidptr, Id::aaRehash); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2440 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2441 |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
387
diff
changeset
|
2442 ec = new VarExp(0, aaRehash_fd); |
159 | 2443 arguments = new Expressions(); |
2444 arguments->push(e->addressOf(sc)); | |
2445 arguments->push(key->getInternalTypeInfo(sc)); | |
2446 e = new CallExp(e->loc, ec, arguments); | |
2447 e->type = this; | |
2448 } | |
2449 else | |
2450 { | |
2451 e = Type::dotExp(sc, e, ident); | |
2452 } | |
2453 return e; | |
2454 } | |
2455 | |
2456 void TypeAArray::toDecoBuffer(OutBuffer *buf) | |
2457 { | |
2458 buf->writeByte(mangleChar[ty]); | |
2459 index->toDecoBuffer(buf); | |
2460 next->toDecoBuffer(buf); | |
2461 } | |
2462 | |
2463 void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
2464 { | |
2465 if (mod != this->mod) | |
2466 { toCBuffer3(buf, hgs, mod); | |
2467 return; | |
2468 } | |
2469 next->toCBuffer2(buf, hgs, this->mod); | |
2470 buf->writeByte('['); | |
2471 index->toCBuffer2(buf, hgs, 0); | |
2472 buf->writeByte(']'); | |
2473 } | |
2474 | |
2475 Expression *TypeAArray::defaultInit(Loc loc) | |
2476 { | |
2477 #if LOGDEFAULTINIT | |
2478 printf("TypeAArray::defaultInit() '%s'\n", toChars()); | |
2479 #endif | |
2480 Expression *e; | |
2481 e = new NullExp(loc); | |
2482 e->type = this; | |
2483 return e; | |
2484 } | |
2485 | |
211
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
162
diff
changeset
|
2486 int TypeAArray::isZeroInit() |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
162
diff
changeset
|
2487 { |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
162
diff
changeset
|
2488 return 1; |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
162
diff
changeset
|
2489 } |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
162
diff
changeset
|
2490 |
159 | 2491 int TypeAArray::checkBoolean() |
2492 { | |
2493 return TRUE; | |
2494 } | |
2495 | |
2496 int TypeAArray::hasPointers() | |
2497 { | |
2498 return TRUE; | |
2499 } | |
2500 | |
2501 /***************************** TypePointer *****************************/ | |
2502 | |
2503 TypePointer::TypePointer(Type *t) | |
2504 : Type(Tpointer, t) | |
2505 { | |
2506 } | |
2507 | |
2508 Type *TypePointer::syntaxCopy() | |
2509 { | |
2510 Type *t = next->syntaxCopy(); | |
2511 if (t == next) | |
2512 t = this; | |
2513 else | |
2514 t = new TypePointer(t); | |
2515 return t; | |
2516 } | |
2517 | |
2518 Type *TypePointer::semantic(Loc loc, Scope *sc) | |
2519 { | |
2520 //printf("TypePointer::semantic()\n"); | |
2521 Type *n = next->semantic(loc, sc); | |
2522 switch (n->toBasetype()->ty) | |
2523 { | |
2524 case Ttuple: | |
2525 error(loc, "can't have pointer to %s", n->toChars()); | |
2526 n = tint32; | |
2527 break; | |
2528 } | |
2529 if (n != next) | |
2530 deco = NULL; | |
2531 next = n; | |
2532 return merge(); | |
2533 } | |
2534 | |
2535 | |
2536 d_uns64 TypePointer::size(Loc loc) | |
2537 { | |
2538 return PTRSIZE; | |
2539 } | |
2540 | |
2541 void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
2542 { | |
2543 //printf("TypePointer::toCBuffer2() next = %d\n", next->ty); | |
2544 if (mod != this->mod) | |
2545 { toCBuffer3(buf, hgs, mod); | |
2546 return; | |
2547 } | |
2548 next->toCBuffer2(buf, hgs, this->mod); | |
2549 if (next->ty != Tfunction) | |
2550 buf->writeByte('*'); | |
2551 } | |
2552 | |
2553 MATCH TypePointer::implicitConvTo(Type *to) | |
2554 { | |
2555 //printf("TypePointer::implicitConvTo()\n"); | |
2556 | |
2557 if (this == to) | |
2558 return MATCHexact; | |
2559 if (to->ty == Tpointer && to->next) | |
2560 { | |
2561 if (to->next->ty == Tvoid) | |
2562 return MATCHconvert; | |
2563 | |
2564 #if 0 | |
2565 if (to->next->isBaseOf(next)) | |
2566 return MATCHconvert; | |
2567 #endif | |
2568 | |
2569 if (next->ty == Tfunction && to->next->ty == Tfunction) | |
2570 { TypeFunction *tf; | |
2571 TypeFunction *tfto; | |
2572 | |
2573 tf = (TypeFunction *)(next); | |
2574 tfto = (TypeFunction *)(to->next); | |
2575 return tfto->equals(tf) ? MATCHexact : MATCHnomatch; | |
2576 } | |
2577 } | |
2578 // if (to->ty == Tvoid) | |
2579 // return MATCHconvert; | |
2580 return MATCHnomatch; | |
2581 } | |
2582 | |
2583 int TypePointer::isscalar() | |
2584 { | |
2585 return TRUE; | |
2586 } | |
2587 | |
2588 Expression *TypePointer::defaultInit(Loc loc) | |
2589 { | |
2590 #if LOGDEFAULTINIT | |
2591 printf("TypePointer::defaultInit() '%s'\n", toChars()); | |
2592 #endif | |
2593 Expression *e; | |
2594 e = new NullExp(loc); | |
2595 e->type = this; | |
2596 return e; | |
2597 } | |
2598 | |
2599 int TypePointer::isZeroInit() | |
2600 { | |
2601 return 1; | |
2602 } | |
2603 | |
2604 int TypePointer::hasPointers() | |
2605 { | |
2606 return TRUE; | |
2607 } | |
2608 | |
2609 | |
2610 /***************************** TypeReference *****************************/ | |
2611 | |
2612 TypeReference::TypeReference(Type *t) | |
2613 : Type(Treference, t) | |
2614 { | |
2615 if (t->ty == Tbit) | |
2616 error(0,"cannot make reference to a bit"); | |
2617 // BUG: what about references to static arrays? | |
2618 } | |
2619 | |
2620 Type *TypeReference::syntaxCopy() | |
2621 { | |
2622 Type *t = next->syntaxCopy(); | |
2623 if (t == next) | |
2624 t = this; | |
2625 else | |
2626 t = new TypeReference(t); | |
2627 return t; | |
2628 } | |
2629 | |
2630 d_uns64 TypeReference::size(Loc loc) | |
2631 { | |
2632 return PTRSIZE; | |
2633 } | |
2634 | |
2635 void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
2636 { | |
2637 if (mod != this->mod) | |
2638 { toCBuffer3(buf, hgs, mod); | |
2639 return; | |
2640 } | |
2641 next->toCBuffer2(buf, hgs, this->mod); | |
2642 buf->writeByte('&'); | |
2643 } | |
2644 | |
2645 Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
2646 { | |
2647 #if LOGDOTEXP | |
2648 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
2649 #endif | |
2650 | |
2651 // References just forward things along | |
2652 return next->dotExp(sc, e, ident); | |
2653 } | |
2654 | |
2655 Expression *TypeReference::defaultInit(Loc loc) | |
2656 { | |
2657 #if LOGDEFAULTINIT | |
2658 printf("TypeReference::defaultInit() '%s'\n", toChars()); | |
2659 #endif | |
2660 Expression *e; | |
2661 e = new NullExp(loc); | |
2662 e->type = this; | |
2663 return e; | |
2664 } | |
2665 | |
2666 int TypeReference::isZeroInit() | |
2667 { | |
2668 return 1; | |
2669 } | |
2670 | |
2671 | |
2672 /***************************** TypeFunction *****************************/ | |
2673 | |
2674 TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage) | |
2675 : Type(Tfunction, treturn) | |
2676 { | |
2677 //if (!treturn) *(char*)0=0; | |
2678 // assert(treturn); | |
2679 this->parameters = parameters; | |
2680 this->varargs = varargs; | |
2681 this->linkage = linkage; | |
2682 this->inuse = 0; | |
486
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2683 this->retInPtr = false; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2684 this->usesThis = false; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2685 this->usesNest = false; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2686 this->retAttrs = 0; |
720
e177ae483f8e
Added inreg attribute where appropriate on x86 to follow ABI docs.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
2687 this->thisAttrs = 0; |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2688 this->reverseParams = false; |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2689 this->reverseIndex = 0; |
159 | 2690 } |
2691 | |
2692 Type *TypeFunction::syntaxCopy() | |
2693 { | |
2694 Type *treturn = next ? next->syntaxCopy() : NULL; | |
2695 Arguments *params = Argument::arraySyntaxCopy(parameters); | |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
211
diff
changeset
|
2696 TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage); |
486
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2697 t->retInPtr = retInPtr; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2698 t->usesThis = usesThis; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2699 t->usesNest = usesNest; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
2700 t->retAttrs = retAttrs; |
720
e177ae483f8e
Added inreg attribute where appropriate on x86 to follow ABI docs.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
2701 t->thisAttrs = thisAttrs; |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2702 t->reverseParams = reverseParams; |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2703 t->reverseIndex = reverseIndex; |
159 | 2704 return t; |
2705 } | |
2706 | |
2707 /******************************* | |
2708 * Returns: | |
2709 * 0 types are distinct | |
2710 * 1 this is covariant with t | |
2711 * 2 arguments match as far as overloading goes, | |
2712 * but types are not covariant | |
2713 * 3 cannot determine covariance because of forward references | |
2714 */ | |
2715 | |
2716 int Type::covariant(Type *t) | |
2717 { | |
2718 #if 0 | |
2719 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars()); | |
2720 printf("deco = %p, %p\n", deco, t->deco); | |
2721 printf("ty = %d\n", next->ty); | |
2722 #endif | |
2723 | |
2724 int inoutmismatch = 0; | |
2725 | |
2726 if (equals(t)) | |
2727 goto Lcovariant; | |
2728 if (ty != Tfunction || t->ty != Tfunction) | |
2729 goto Ldistinct; | |
2730 | |
2731 { | |
2732 TypeFunction *t1 = (TypeFunction *)this; | |
2733 TypeFunction *t2 = (TypeFunction *)t; | |
2734 | |
2735 if (t1->varargs != t2->varargs) | |
2736 goto Ldistinct; | |
2737 | |
2738 if (t1->parameters && t2->parameters) | |
2739 { | |
2740 size_t dim = Argument::dim(t1->parameters); | |
2741 if (dim != Argument::dim(t2->parameters)) | |
2742 goto Ldistinct; | |
2743 | |
2744 for (size_t i = 0; i < dim; i++) | |
2745 { Argument *arg1 = Argument::getNth(t1->parameters, i); | |
2746 Argument *arg2 = Argument::getNth(t2->parameters, i); | |
2747 | |
2748 if (!arg1->type->equals(arg2->type)) | |
2749 goto Ldistinct; | |
2750 if (arg1->storageClass != arg2->storageClass) | |
2751 inoutmismatch = 1; | |
2752 } | |
2753 } | |
2754 else if (t1->parameters != t2->parameters) | |
2755 goto Ldistinct; | |
2756 | |
2757 // The argument lists match | |
2758 if (inoutmismatch) | |
2759 goto Lnotcovariant; | |
2760 if (t1->linkage != t2->linkage) | |
2761 goto Lnotcovariant; | |
2762 | |
2763 Type *t1n = t1->next; | |
2764 Type *t2n = t2->next; | |
2765 | |
2766 if (t1n->equals(t2n)) | |
2767 goto Lcovariant; | |
2768 if (t1n->ty != Tclass || t2n->ty != Tclass) | |
2769 goto Lnotcovariant; | |
2770 | |
2771 // If t1n is forward referenced: | |
2772 ClassDeclaration *cd = ((TypeClass *)t1n)->sym; | |
2773 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration()) | |
2774 { | |
2775 return 3; | |
2776 } | |
2777 | |
2778 if (t1n->implicitConvTo(t2n)) | |
2779 goto Lcovariant; | |
2780 goto Lnotcovariant; | |
2781 } | |
2782 | |
2783 Lcovariant: | |
2784 //printf("\tcovaraint: 1\n"); | |
2785 return 1; | |
2786 | |
2787 Ldistinct: | |
2788 //printf("\tcovaraint: 0\n"); | |
2789 return 0; | |
2790 | |
2791 Lnotcovariant: | |
2792 //printf("\tcovaraint: 2\n"); | |
2793 return 2; | |
2794 } | |
2795 | |
2796 void TypeFunction::toDecoBuffer(OutBuffer *buf) | |
2797 { unsigned char mc; | |
2798 | |
2799 //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars()); | |
2800 //static int nest; if (++nest == 50) *(char*)0=0; | |
2801 if (inuse) | |
2802 { inuse = 2; // flag error to caller | |
2803 return; | |
2804 } | |
2805 inuse++; | |
2806 switch (linkage) | |
2807 { | |
2808 case LINKd: mc = 'F'; break; | |
2809 case LINKc: mc = 'U'; break; | |
2810 case LINKwindows: mc = 'W'; break; | |
2811 case LINKpascal: mc = 'V'; break; | |
2812 case LINKcpp: mc = 'R'; break; | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2813 |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2814 // LDC |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2815 case LINKintrinsic: mc = 'Q'; break; |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2816 |
159 | 2817 default: |
2818 assert(0); | |
2819 } | |
2820 buf->writeByte(mc); | |
2821 // Write argument types | |
2822 Argument::argsToDecoBuffer(buf, parameters); | |
2823 //if (buf->data[buf->offset - 1] == '@') halt(); | |
2824 buf->writeByte('Z' - varargs); // mark end of arg list | |
2825 next->toDecoBuffer(buf); | |
2826 inuse--; | |
2827 } | |
2828 | |
2829 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) | |
2830 { | |
2831 char *p = NULL; | |
2832 | |
2833 if (inuse) | |
2834 { inuse = 2; // flag error to caller | |
2835 return; | |
2836 } | |
2837 inuse++; | |
2838 if (next && (!ident || ident->toHChars2() == ident->toChars())) | |
2839 next->toCBuffer2(buf, hgs, 0); | |
2840 if (hgs->ddoc != 1) | |
2841 { | |
2842 switch (linkage) | |
2843 { | |
2844 case LINKd: p = NULL; break; | |
2845 case LINKc: p = "C "; break; | |
2846 case LINKwindows: p = "Windows "; break; | |
2847 case LINKpascal: p = "Pascal "; break; | |
2848 case LINKcpp: p = "C++ "; break; | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2849 |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2850 // LDC |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2851 case LINKintrinsic: p = "Intrinsic"; break; |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2852 |
159 | 2853 default: |
2854 assert(0); | |
2855 } | |
2856 } | |
2857 | |
2858 if (!hgs->hdrgen && p) | |
2859 buf->writestring(p); | |
2860 if (ident) | |
2861 { buf->writeByte(' '); | |
2862 buf->writestring(ident->toHChars2()); | |
2863 } | |
2864 Argument::argsToCBuffer(buf, hgs, parameters, varargs); | |
2865 inuse--; | |
2866 } | |
2867 | |
2868 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
2869 { | |
2870 char *p = NULL; | |
2871 | |
2872 if (inuse) | |
2873 { inuse = 2; // flag error to caller | |
2874 return; | |
2875 } | |
2876 inuse++; | |
2877 if (next) | |
2878 next->toCBuffer2(buf, hgs, 0); | |
2879 if (hgs->ddoc != 1) | |
2880 { | |
2881 switch (linkage) | |
2882 { | |
2883 case LINKd: p = NULL; break; | |
2884 case LINKc: p = "C "; break; | |
2885 case LINKwindows: p = "Windows "; break; | |
2886 case LINKpascal: p = "Pascal "; break; | |
2887 case LINKcpp: p = "C++ "; break; | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2888 |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2889 // LDC |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2890 case LINKintrinsic: p = "Intrinsic"; break; |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
720
diff
changeset
|
2891 |
159 | 2892 default: |
2893 assert(0); | |
2894 } | |
2895 } | |
2896 | |
2897 if (!hgs->hdrgen && p) | |
2898 buf->writestring(p); | |
2899 buf->writestring(" function"); | |
2900 Argument::argsToCBuffer(buf, hgs, parameters, varargs); | |
2901 inuse--; | |
2902 } | |
2903 | |
2904 Type *TypeFunction::semantic(Loc loc, Scope *sc) | |
2905 { | |
2906 if (deco) // if semantic() already run | |
2907 { | |
2908 //printf("already done\n"); | |
2909 return this; | |
2910 } | |
2911 //printf("TypeFunction::semantic() this = %p\n", this); | |
2912 | |
2913 TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction)); | |
2914 memcpy(tf, this, sizeof(TypeFunction)); | |
2915 if (parameters) | |
2916 { tf->parameters = (Arguments *)parameters->copy(); | |
2917 for (size_t i = 0; i < parameters->dim; i++) | |
2918 { Argument *arg = (Argument *)parameters->data[i]; | |
2919 Argument *cpy = (Argument *)mem.malloc(sizeof(Argument)); | |
2920 memcpy(cpy, arg, sizeof(Argument)); | |
2921 tf->parameters->data[i] = (void *)cpy; | |
2922 } | |
2923 } | |
2924 | |
2925 tf->linkage = sc->linkage; | |
2926 if (!tf->next) | |
2927 { | |
2928 assert(global.errors); | |
2929 tf->next = tvoid; | |
2930 } | |
2931 tf->next = tf->next->semantic(loc,sc); | |
2932 if (tf->next->toBasetype()->ty == Tsarray) | |
2933 { error(loc, "functions cannot return static array %s", tf->next->toChars()); | |
2934 tf->next = Type::terror; | |
2935 } | |
2936 if (tf->next->toBasetype()->ty == Tfunction) | |
2937 { error(loc, "functions cannot return a function"); | |
2938 tf->next = Type::terror; | |
2939 } | |
2940 if (tf->next->toBasetype()->ty == Ttuple) | |
2941 { error(loc, "functions cannot return a tuple"); | |
2942 tf->next = Type::terror; | |
2943 } | |
2944 if (tf->next->isauto() && !(sc->flags & SCOPEctor)) | |
2945 error(loc, "functions cannot return auto %s", tf->next->toChars()); | |
2946 | |
2947 if (tf->parameters) | |
2948 { size_t dim = Argument::dim(tf->parameters); | |
2949 | |
2950 for (size_t i = 0; i < dim; i++) | |
2951 { Argument *arg = Argument::getNth(tf->parameters, i); | |
2952 Type *t; | |
2953 | |
2954 tf->inuse++; | |
2955 arg->type = arg->type->semantic(loc,sc); | |
2956 if (tf->inuse == 1) tf->inuse--; | |
780
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2957 |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2958 // each function needs its own copy of a tuple arg, since |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2959 // they mustn't share arg flags like inreg, ... |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2960 if (arg->type->ty == Ttuple) { |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2961 arg->type = arg->type->syntaxCopy(); |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2962 tf->inuse++; |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2963 arg->type = arg->type->semantic(loc,sc); |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2964 if (tf->inuse == 1) tf->inuse--; |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2965 } |
2cf440d511bb
Move tuple syntax copy for function arguments after semantic, to make sure
Christian Kamm <kamm incasoftware de>
parents:
772
diff
changeset
|
2966 |
159 | 2967 t = arg->type->toBasetype(); |
2968 | |
2969 if (arg->storageClass & (STCout | STCref | STClazy)) | |
2970 { | |
2971 if (t->ty == Tsarray) | |
2972 error(loc, "cannot have out or ref parameter of type %s", t->toChars()); | |
2973 } | |
2974 if (!(arg->storageClass & STClazy) && t->ty == Tvoid) | |
2975 error(loc, "cannot have parameter of type %s", arg->type->toChars()); | |
2976 | |
2977 if (arg->defaultArg) | |
2978 { | |
2979 arg->defaultArg = arg->defaultArg->semantic(sc); | |
2980 arg->defaultArg = resolveProperties(sc, arg->defaultArg); | |
2981 arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type); | |
2982 } | |
2983 | |
2984 /* If arg turns out to be a tuple, the number of parameters may | |
2985 * change. | |
2986 */ | |
2987 if (t->ty == Ttuple) | |
2988 { dim = Argument::dim(tf->parameters); | |
2989 i--; | |
2990 } | |
2991 } | |
2992 } | |
2993 tf->deco = tf->merge()->deco; | |
2994 | |
2995 if (tf->inuse) | |
2996 { error(loc, "recursive type"); | |
2997 tf->inuse = 0; | |
2998 return terror; | |
2999 } | |
3000 | |
3001 if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0) | |
3002 error(loc, "variadic functions with non-D linkage must have at least one parameter"); | |
3003 | |
3004 /* Don't return merge(), because arg identifiers and default args | |
3005 * can be different | |
3006 * even though the types match | |
3007 */ | |
3008 return tf; | |
3009 } | |
3010 | |
3011 /******************************** | |
3012 * 'args' are being matched to function 'this' | |
3013 * Determine match level. | |
3014 * Returns: | |
3015 * MATCHxxxx | |
3016 */ | |
3017 | |
3018 int TypeFunction::callMatch(Expressions *args) | |
3019 { | |
3020 //printf("TypeFunction::callMatch()\n"); | |
3021 int match = MATCHexact; // assume exact match | |
3022 | |
3023 size_t nparams = Argument::dim(parameters); | |
3024 size_t nargs = args ? args->dim : 0; | |
3025 if (nparams == nargs) | |
3026 ; | |
3027 else if (nargs > nparams) | |
3028 { | |
3029 if (varargs == 0) | |
3030 goto Nomatch; // too many args; no match | |
3031 match = MATCHconvert; // match ... with a "conversion" match level | |
3032 } | |
3033 | |
3034 for (size_t u = 0; u < nparams; u++) | |
3035 { int m; | |
3036 Expression *arg; | |
3037 | |
3038 // BUG: what about out and ref? | |
3039 | |
3040 Argument *p = Argument::getNth(parameters, u); | |
3041 assert(p); | |
3042 if (u >= nargs) | |
3043 { | |
3044 if (p->defaultArg) | |
3045 continue; | |
3046 if (varargs == 2 && u + 1 == nparams) | |
3047 goto L1; | |
3048 goto Nomatch; // not enough arguments | |
3049 } | |
3050 arg = (Expression *)args->data[u]; | |
3051 assert(arg); | |
3052 if (p->storageClass & STClazy && p->type->ty == Tvoid && arg->type->ty != Tvoid) | |
3053 m = MATCHconvert; | |
3054 else | |
3055 m = arg->implicitConvTo(p->type); | |
3056 //printf("\tm = %d\n", m); | |
3057 if (m == MATCHnomatch) // if no match | |
3058 { | |
3059 L1: | |
3060 if (varargs == 2 && u + 1 == nparams) // if last varargs param | |
3061 { Type *tb = p->type->toBasetype(); | |
3062 TypeSArray *tsa; | |
3063 integer_t sz; | |
3064 | |
3065 switch (tb->ty) | |
3066 { | |
3067 case Tsarray: | |
3068 tsa = (TypeSArray *)tb; | |
3069 sz = tsa->dim->toInteger(); | |
3070 if (sz != nargs - u) | |
3071 goto Nomatch; | |
3072 case Tarray: | |
3073 for (; u < nargs; u++) | |
3074 { | |
3075 arg = (Expression *)args->data[u]; | |
3076 assert(arg); | |
3077 #if 1 | |
3078 /* If lazy array of delegates, | |
3079 * convert arg(s) to delegate(s) | |
3080 */ | |
3081 Type *tret = p->isLazyArray(); | |
3082 if (tret) | |
3083 { | |
3084 if (tb->next->equals(arg->type)) | |
3085 { m = MATCHexact; | |
3086 } | |
3087 else | |
3088 { | |
3089 m = arg->implicitConvTo(tret); | |
3090 if (m == MATCHnomatch) | |
3091 { | |
3092 if (tret->toBasetype()->ty == Tvoid) | |
3093 m = MATCHconvert; | |
3094 } | |
3095 } | |
3096 } | |
3097 else | |
3098 m = arg->implicitConvTo(tb->next); | |
3099 #else | |
3100 m = arg->implicitConvTo(tb->next); | |
3101 #endif | |
3102 if (m == 0) | |
3103 goto Nomatch; | |
3104 if (m < match) | |
3105 match = m; | |
3106 } | |
3107 goto Ldone; | |
3108 | |
3109 case Tclass: | |
3110 // Should see if there's a constructor match? | |
3111 // Or just leave it ambiguous? | |
3112 goto Ldone; | |
3113 | |
3114 default: | |
3115 goto Nomatch; | |
3116 } | |
3117 } | |
3118 goto Nomatch; | |
3119 } | |
3120 if (m < match) | |
3121 match = m; // pick worst match | |
3122 } | |
3123 | |
3124 Ldone: | |
3125 //printf("match = %d\n", match); | |
3126 return match; | |
3127 | |
3128 Nomatch: | |
3129 //printf("no match\n"); | |
3130 return MATCHnomatch; | |
3131 } | |
3132 | |
3133 Type *TypeFunction::reliesOnTident() | |
3134 { | |
3135 if (parameters) | |
3136 { | |
3137 for (size_t i = 0; i < parameters->dim; i++) | |
3138 { Argument *arg = (Argument *)parameters->data[i]; | |
3139 Type *t = arg->type->reliesOnTident(); | |
3140 if (t) | |
3141 return t; | |
3142 } | |
3143 } | |
3144 return next->reliesOnTident(); | |
3145 } | |
3146 | |
3147 /***************************** TypeDelegate *****************************/ | |
3148 | |
3149 TypeDelegate::TypeDelegate(Type *t) | |
3150 : Type(Tfunction, t) | |
3151 { | |
3152 ty = Tdelegate; | |
3153 } | |
3154 | |
3155 Type *TypeDelegate::syntaxCopy() | |
3156 { | |
3157 Type *t = next->syntaxCopy(); | |
3158 if (t == next) | |
3159 t = this; | |
3160 else | |
3161 t = new TypeDelegate(t); | |
3162 return t; | |
3163 } | |
3164 | |
3165 Type *TypeDelegate::semantic(Loc loc, Scope *sc) | |
3166 { | |
3167 if (deco) // if semantic() already run | |
3168 { | |
3169 //printf("already done\n"); | |
3170 return this; | |
3171 } | |
3172 next = next->semantic(loc,sc); | |
3173 return merge(); | |
3174 } | |
3175 | |
3176 d_uns64 TypeDelegate::size(Loc loc) | |
3177 { | |
3178 return PTRSIZE * 2; | |
3179 } | |
3180 | |
797
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3181 // LDC added, no reason to align to 2*PTRSIZE |
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3182 unsigned TypeDelegate::alignsize() |
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3183 { |
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3184 // A Delegate consists of two ptr values, so align it on pointer size |
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3185 // boundary |
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3186 return PTRSIZE; |
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3187 } |
340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
780
diff
changeset
|
3188 |
159 | 3189 void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) |
3190 { | |
3191 if (mod != this->mod) | |
3192 { toCBuffer3(buf, hgs, mod); | |
3193 return; | |
3194 } | |
3195 TypeFunction *tf = (TypeFunction *)next; | |
3196 | |
3197 tf->next->toCBuffer2(buf, hgs, 0); | |
3198 buf->writestring(" delegate"); | |
3199 Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs); | |
3200 } | |
3201 | |
3202 Expression *TypeDelegate::defaultInit(Loc loc) | |
3203 { | |
3204 #if LOGDEFAULTINIT | |
3205 printf("TypeDelegate::defaultInit() '%s'\n", toChars()); | |
3206 #endif | |
3207 Expression *e; | |
3208 e = new NullExp(loc); | |
3209 e->type = this; | |
3210 return e; | |
3211 } | |
3212 | |
3213 int TypeDelegate::isZeroInit() | |
3214 { | |
3215 return 1; | |
3216 } | |
3217 | |
3218 int TypeDelegate::checkBoolean() | |
3219 { | |
3220 return TRUE; | |
3221 } | |
3222 | |
3223 Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
3224 { | |
3225 #if LOGDOTEXP | |
3226 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
3227 #endif | |
3228 if (ident == Id::ptr) | |
3229 { | |
599
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
591
diff
changeset
|
3230 e = new GEPExp(e->loc, e, ident, 0); |
159 | 3231 e->type = tvoidptr; |
3232 return e; | |
3233 } | |
3234 else if (ident == Id::funcptr) | |
3235 { | |
599
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
591
diff
changeset
|
3236 e = new GEPExp(e->loc, e, ident, 1); |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
591
diff
changeset
|
3237 e->type = tvoidptr; |
159 | 3238 return e; |
3239 } | |
3240 else | |
3241 { | |
3242 e = Type::dotExp(sc, e, ident); | |
3243 } | |
3244 return e; | |
3245 } | |
3246 | |
3247 int TypeDelegate::hasPointers() | |
3248 { | |
3249 return TRUE; | |
3250 } | |
3251 | |
3252 | |
3253 | |
3254 /***************************** TypeQualified *****************************/ | |
3255 | |
3256 TypeQualified::TypeQualified(TY ty, Loc loc) | |
3257 : Type(ty, NULL) | |
3258 { | |
3259 this->loc = loc; | |
3260 } | |
3261 | |
3262 void TypeQualified::syntaxCopyHelper(TypeQualified *t) | |
3263 { | |
3264 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars()); | |
3265 idents.setDim(t->idents.dim); | |
3266 for (int i = 0; i < idents.dim; i++) | |
3267 { | |
3268 Identifier *id = (Identifier *)t->idents.data[i]; | |
3269 if (id->dyncast() == DYNCAST_DSYMBOL) | |
3270 { | |
3271 TemplateInstance *ti = (TemplateInstance *)id; | |
3272 | |
3273 ti = (TemplateInstance *)ti->syntaxCopy(NULL); | |
3274 id = (Identifier *)ti; | |
3275 } | |
3276 idents.data[i] = id; | |
3277 } | |
3278 } | |
3279 | |
3280 | |
3281 void TypeQualified::addIdent(Identifier *ident) | |
3282 { | |
3283 idents.push(ident); | |
3284 } | |
3285 | |
3286 void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs) | |
3287 { | |
3288 int i; | |
3289 | |
3290 for (i = 0; i < idents.dim; i++) | |
3291 { Identifier *id = (Identifier *)idents.data[i]; | |
3292 | |
3293 buf->writeByte('.'); | |
3294 | |
3295 if (id->dyncast() == DYNCAST_DSYMBOL) | |
3296 { | |
3297 TemplateInstance *ti = (TemplateInstance *)id; | |
3298 ti->toCBuffer(buf, hgs); | |
3299 } | |
3300 else | |
3301 buf->writestring(id->toChars()); | |
3302 } | |
3303 } | |
3304 | |
3305 d_uns64 TypeQualified::size(Loc loc) | |
3306 { | |
3307 error(this->loc, "size of type %s is not known", toChars()); | |
3308 return 1; | |
3309 } | |
3310 | |
3311 /************************************* | |
3312 * Takes an array of Identifiers and figures out if | |
3313 * it represents a Type or an Expression. | |
3314 * Output: | |
3315 * if expression, *pe is set | |
3316 * if type, *pt is set | |
3317 */ | |
3318 | |
3319 void TypeQualified::resolveHelper(Loc loc, Scope *sc, | |
3320 Dsymbol *s, Dsymbol *scopesym, | |
3321 Expression **pe, Type **pt, Dsymbol **ps) | |
3322 { | |
3323 Identifier *id = NULL; | |
3324 int i; | |
3325 VarDeclaration *v; | |
3326 EnumMember *em; | |
3327 TupleDeclaration *td; | |
3328 Type *t; | |
3329 Expression *e; | |
3330 | |
3331 #if 0 | |
3332 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars()); | |
3333 if (scopesym) | |
3334 printf("\tscopesym = '%s'\n", scopesym->toChars()); | |
3335 #endif | |
3336 *pe = NULL; | |
3337 *pt = NULL; | |
3338 *ps = NULL; | |
3339 if (s) | |
3340 { | |
3341 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); | |
336 | 3342 s->checkDeprecated(loc, sc); // check for deprecated aliases |
159 | 3343 s = s->toAlias(); |
3344 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); | |
3345 for (i = 0; i < idents.dim; i++) | |
3346 { Dsymbol *sm; | |
3347 | |
3348 id = (Identifier *)idents.data[i]; | |
3349 sm = s->searchX(loc, sc, id); | |
3350 //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); | |
3351 //printf("getType = '%s'\n", s->getType()->toChars()); | |
3352 if (!sm) | |
3353 { | |
3354 v = s->isVarDeclaration(); | |
3355 if (v && id == Id::length) | |
3356 { | |
3357 if (v->isConst() && v->getExpInitializer()) | |
3358 { e = v->getExpInitializer()->exp; | |
3359 } | |
3360 else | |
3361 e = new VarExp(loc, v); | |
3362 t = e->type; | |
3363 if (!t) | |
3364 goto Lerror; | |
3365 goto L3; | |
3366 } | |
3367 t = s->getType(); | |
3368 if (!t && s->isDeclaration()) | |
3369 t = s->isDeclaration()->type; | |
3370 if (t) | |
3371 { | |
3372 sm = t->toDsymbol(sc); | |
3373 if (sm) | |
3374 { sm = sm->search(loc, id, 0); | |
3375 if (sm) | |
3376 goto L2; | |
3377 } | |
3378 //e = t->getProperty(loc, id); | |
3379 e = new TypeExp(loc, t); | |
3380 e = t->dotExp(sc, e, id); | |
3381 i++; | |
3382 L3: | |
3383 for (; i < idents.dim; i++) | |
3384 { | |
3385 id = (Identifier *)idents.data[i]; | |
3386 //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type); | |
3387 e = e->type->dotExp(sc, e, id); | |
3388 } | |
3389 *pe = e; | |
3390 } | |
3391 else | |
3392 Lerror: | |
3393 error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); | |
3394 return; | |
3395 } | |
3396 L2: | |
3397 s = sm->toAlias(); | |
3398 } | |
3399 | |
3400 v = s->isVarDeclaration(); | |
3401 if (v) | |
3402 { | |
3403 // It's not a type, it's an expression | |
3404 if (v->isConst() && v->getExpInitializer()) | |
3405 { | |
3406 ExpInitializer *ei = v->getExpInitializer(); | |
3407 assert(ei); | |
3408 *pe = ei->exp->copy(); // make copy so we can change loc | |
3409 (*pe)->loc = loc; | |
3410 } | |
3411 else | |
3412 { | |
3413 #if 0 | |
3414 WithScopeSymbol *withsym; | |
3415 if (scopesym && (withsym = scopesym->isWithScopeSymbol()) != NULL) | |
3416 { | |
3417 // Same as wthis.ident | |
3418 e = new VarExp(loc, withsym->withstate->wthis); | |
3419 e = new DotIdExp(loc, e, ident); | |
3420 //assert(0); // BUG: should handle this | |
3421 } | |
3422 else | |
3423 #endif | |
3424 *pe = new VarExp(loc, v); | |
3425 } | |
3426 return; | |
3427 } | |
3428 em = s->isEnumMember(); | |
3429 if (em) | |
3430 { | |
3431 // It's not a type, it's an expression | |
3432 *pe = em->value->copy(); | |
3433 return; | |
3434 } | |
3435 | |
3436 L1: | |
3437 t = s->getType(); | |
3438 if (!t) | |
3439 { | |
3440 // If the symbol is an import, try looking inside the import | |
3441 Import *si; | |
3442 | |
3443 si = s->isImport(); | |
3444 if (si) | |
3445 { | |
3446 s = si->search(loc, s->ident, 0); | |
3447 if (s && s != si) | |
3448 goto L1; | |
3449 s = si; | |
3450 } | |
3451 *ps = s; | |
3452 return; | |
3453 } | |
3454 if (t->ty == Tinstance && t != this && !t->deco) | |
3455 { error(loc, "forward reference to '%s'", t->toChars()); | |
3456 return; | |
3457 } | |
3458 | |
3459 if (t != this) | |
3460 { | |
3461 if (t->reliesOnTident()) | |
3462 { | |
3463 Scope *scx; | |
3464 | |
3465 for (scx = sc; 1; scx = scx->enclosing) | |
3466 { | |
3467 if (!scx) | |
3468 { error(loc, "forward reference to '%s'", t->toChars()); | |
3469 return; | |
3470 } | |
3471 if (scx->scopesym == scopesym) | |
3472 break; | |
3473 } | |
3474 t = t->semantic(loc, scx); | |
3475 //((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps); | |
3476 } | |
3477 } | |
3478 if (t->ty == Ttuple) | |
772
cd7da2ba14d1
Fix bug reported by downs. Related to delegate types within tuple template parameters.
Christian Kamm <kamm incasoftware de>
parents:
771
diff
changeset
|
3479 *pt = t; |
159 | 3480 else |
3481 *pt = t->merge(); | |
3482 } | |
3483 if (!s) | |
3484 { | |
3485 error(loc, "identifier '%s' is not defined", toChars()); | |
3486 } | |
3487 } | |
3488 | |
3489 /***************************** TypeIdentifier *****************************/ | |
3490 | |
3491 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident) | |
3492 : TypeQualified(Tident, loc) | |
3493 { | |
3494 this->ident = ident; | |
3495 } | |
3496 | |
3497 | |
3498 Type *TypeIdentifier::syntaxCopy() | |
3499 { | |
3500 TypeIdentifier *t; | |
3501 | |
3502 t = new TypeIdentifier(loc, ident); | |
3503 t->syntaxCopyHelper(this); | |
3504 return t; | |
3505 } | |
3506 | |
3507 void TypeIdentifier::toDecoBuffer(OutBuffer *buf) | |
3508 { unsigned len; | |
3509 char *name; | |
3510 | |
3511 name = ident->toChars(); | |
3512 len = strlen(name); | |
3513 buf->printf("%c%d%s", mangleChar[ty], len, name); | |
3514 //buf->printf("%c%s", mangleChar[ty], name); | |
3515 } | |
3516 | |
3517 void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
3518 { | |
3519 if (mod != this->mod) | |
3520 { toCBuffer3(buf, hgs, mod); | |
3521 return; | |
3522 } | |
3523 buf->writestring(this->ident->toChars()); | |
3524 toCBuffer2Helper(buf, hgs); | |
3525 } | |
3526 | |
3527 /************************************* | |
3528 * Takes an array of Identifiers and figures out if | |
3529 * it represents a Type or an Expression. | |
3530 * Output: | |
3531 * if expression, *pe is set | |
3532 * if type, *pt is set | |
3533 */ | |
3534 | |
3535 void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) | |
3536 { Dsymbol *s; | |
3537 Dsymbol *scopesym; | |
3538 | |
3539 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars()); | |
3540 s = sc->search(loc, ident, &scopesym); | |
3541 resolveHelper(loc, sc, s, scopesym, pe, pt, ps); | |
3542 } | |
3543 | |
3544 /***************************************** | |
3545 * See if type resolves to a symbol, if so, | |
3546 * return that symbol. | |
3547 */ | |
3548 | |
3549 Dsymbol *TypeIdentifier::toDsymbol(Scope *sc) | |
3550 { | |
3551 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars()); | |
3552 if (!sc) | |
3553 return NULL; | |
3554 //printf("ident = '%s'\n", ident->toChars()); | |
3555 | |
3556 Dsymbol *scopesym; | |
3557 Dsymbol *s = sc->search(loc, ident, &scopesym); | |
3558 if (s) | |
3559 { | |
3560 for (int i = 0; i < idents.dim; i++) | |
3561 { | |
3562 Identifier *id = (Identifier *)idents.data[i]; | |
3563 s = s->searchX(loc, sc, id); | |
3564 if (!s) // failed to find a symbol | |
3565 { //printf("\tdidn't find a symbol\n"); | |
3566 break; | |
3567 } | |
3568 } | |
3569 } | |
3570 return s; | |
3571 } | |
3572 | |
3573 Type *TypeIdentifier::semantic(Loc loc, Scope *sc) | |
3574 { | |
3575 Type *t; | |
3576 Expression *e; | |
3577 Dsymbol *s; | |
3578 | |
3579 //printf("TypeIdentifier::semantic(%s)\n", toChars()); | |
3580 resolve(loc, sc, &e, &t, &s); | |
3581 if (t) | |
3582 { | |
3583 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco); | |
3584 | |
3585 if (t->ty == Ttypedef) | |
3586 { TypeTypedef *tt = (TypeTypedef *)t; | |
3587 | |
3588 if (tt->sym->sem == 1) | |
3589 error(loc, "circular reference of typedef %s", tt->toChars()); | |
3590 } | |
3591 } | |
3592 else | |
3593 { | |
3594 #ifdef DEBUG | |
3595 if (!global.gag) | |
3596 printf("1: "); | |
3597 #endif | |
3598 if (s) | |
3599 { | |
3600 s->error(loc, "is used as a type"); | |
3601 } | |
3602 else | |
3603 error(loc, "%s is used as a type", toChars()); | |
3604 t = tvoid; | |
3605 } | |
3606 //t->print(); | |
3607 return t; | |
3608 } | |
3609 | |
3610 Type *TypeIdentifier::reliesOnTident() | |
3611 { | |
3612 return this; | |
3613 } | |
3614 | |
3615 Expression *TypeIdentifier::toExpression() | |
3616 { | |
3617 Expression *e = new IdentifierExp(loc, ident); | |
3618 for (int i = 0; i < idents.dim; i++) | |
3619 { | |
3620 Identifier *id = (Identifier *)idents.data[i]; | |
3621 e = new DotIdExp(loc, e, id); | |
3622 } | |
3623 | |
3624 return e; | |
3625 } | |
3626 | |
3627 /***************************** TypeInstance *****************************/ | |
3628 | |
3629 TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst) | |
3630 : TypeQualified(Tinstance, loc) | |
3631 { | |
3632 this->tempinst = tempinst; | |
3633 } | |
3634 | |
3635 Type *TypeInstance::syntaxCopy() | |
3636 { | |
3637 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim); | |
3638 TypeInstance *t; | |
3639 | |
3640 t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL)); | |
3641 t->syntaxCopyHelper(this); | |
3642 return t; | |
3643 } | |
3644 | |
3645 | |
3646 void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
3647 { | |
3648 if (mod != this->mod) | |
3649 { toCBuffer3(buf, hgs, mod); | |
3650 return; | |
3651 } | |
3652 tempinst->toCBuffer(buf, hgs); | |
3653 toCBuffer2Helper(buf, hgs); | |
3654 } | |
3655 | |
3656 void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) | |
3657 { | |
3658 // Note close similarity to TypeIdentifier::resolve() | |
3659 | |
3660 Dsymbol *s; | |
3661 | |
3662 *pe = NULL; | |
3663 *pt = NULL; | |
3664 *ps = NULL; | |
3665 | |
3666 #if 0 | |
3667 if (!idents.dim) | |
3668 { | |
3669 error(loc, "template instance '%s' has no identifier", toChars()); | |
3670 return; | |
3671 } | |
3672 #endif | |
3673 //id = (Identifier *)idents.data[0]; | |
3674 //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars()); | |
3675 s = tempinst; | |
3676 if (s) | |
3677 s->semantic(sc); | |
3678 resolveHelper(loc, sc, s, NULL, pe, pt, ps); | |
3679 //printf("pt = '%s'\n", (*pt)->toChars()); | |
3680 } | |
3681 | |
3682 Type *TypeInstance::semantic(Loc loc, Scope *sc) | |
3683 { | |
3684 Type *t; | |
3685 Expression *e; | |
3686 Dsymbol *s; | |
3687 | |
3688 //printf("TypeInstance::semantic(%s)\n", toChars()); | |
3689 | |
3690 if (sc->parameterSpecialization) | |
3691 { | |
3692 unsigned errors = global.errors; | |
3693 global.gag++; | |
3694 | |
3695 resolve(loc, sc, &e, &t, &s); | |
3696 | |
3697 global.gag--; | |
3698 if (errors != global.errors) | |
3699 { if (global.gag == 0) | |
3700 global.errors = errors; | |
3701 return this; | |
3702 } | |
3703 } | |
3704 else | |
3705 resolve(loc, sc, &e, &t, &s); | |
3706 | |
3707 if (!t) | |
3708 { | |
3709 #ifdef DEBUG | |
3710 printf("2: "); | |
3711 #endif | |
3712 error(loc, "%s is used as a type", toChars()); | |
3713 t = tvoid; | |
3714 } | |
3715 return t; | |
3716 } | |
3717 | |
3718 | |
3719 /***************************** TypeTypeof *****************************/ | |
3720 | |
3721 TypeTypeof::TypeTypeof(Loc loc, Expression *exp) | |
3722 : TypeQualified(Ttypeof, loc) | |
3723 { | |
3724 this->exp = exp; | |
3725 } | |
3726 | |
3727 Type *TypeTypeof::syntaxCopy() | |
3728 { | |
3729 TypeTypeof *t; | |
3730 | |
3731 t = new TypeTypeof(loc, exp->syntaxCopy()); | |
3732 t->syntaxCopyHelper(this); | |
3733 return t; | |
3734 } | |
3735 | |
3736 Dsymbol *TypeTypeof::toDsymbol(Scope *sc) | |
3737 { | |
3738 Type *t; | |
3739 | |
336 | 3740 t = semantic(loc, sc); |
159 | 3741 if (t == this) |
3742 return NULL; | |
3743 return t->toDsymbol(sc); | |
3744 } | |
3745 | |
3746 void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
3747 { | |
3748 if (mod != this->mod) | |
3749 { toCBuffer3(buf, hgs, mod); | |
3750 return; | |
3751 } | |
3752 buf->writestring("typeof("); | |
3753 exp->toCBuffer(buf, hgs); | |
3754 buf->writeByte(')'); | |
3755 toCBuffer2Helper(buf, hgs); | |
3756 } | |
3757 | |
3758 Type *TypeTypeof::semantic(Loc loc, Scope *sc) | |
3759 { Expression *e; | |
3760 Type *t; | |
3761 | |
3762 //printf("TypeTypeof::semantic() %p\n", this); | |
3763 | |
3764 //static int nest; if (++nest == 50) *(char*)0=0; | |
3765 | |
3766 #if 0 | |
3767 /* Special case for typeof(this) and typeof(super) since both | |
3768 * should work even if they are not inside a non-static member function | |
3769 */ | |
3770 if (exp->op == TOKthis || exp->op == TOKsuper) | |
3771 { | |
3772 // Find enclosing struct or class | |
3773 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
3774 { | |
3775 ClassDeclaration *cd; | |
3776 StructDeclaration *sd; | |
3777 | |
3778 if (!s) | |
3779 { | |
3780 error(loc, "%s is not in a struct or class scope", exp->toChars()); | |
3781 goto Lerr; | |
3782 } | |
3783 cd = s->isClassDeclaration(); | |
3784 if (cd) | |
3785 { | |
3786 if (exp->op == TOKsuper) | |
3787 { | |
3788 cd = cd->baseClass; | |
3789 if (!cd) | |
3790 { error(loc, "class %s has no 'super'", s->toChars()); | |
3791 goto Lerr; | |
3792 } | |
3793 } | |
3794 t = cd->type; | |
3795 break; | |
3796 } | |
3797 sd = s->isStructDeclaration(); | |
3798 if (sd) | |
3799 { | |
3800 if (exp->op == TOKsuper) | |
3801 { | |
3802 error(loc, "struct %s has no 'super'", sd->toChars()); | |
3803 goto Lerr; | |
3804 } | |
3805 t = sd->type->pointerTo(); | |
3806 break; | |
3807 } | |
3808 } | |
3809 } | |
3810 else | |
3811 #endif | |
3812 { | |
3813 sc->intypeof++; | |
3814 exp = exp->semantic(sc); | |
3815 sc->intypeof--; | |
336 | 3816 if (exp->op == TOKtype) |
3817 { | |
3818 error(loc, "argument %s to typeof is not an expression", exp->toChars()); | |
3819 } | |
159 | 3820 t = exp->type; |
3821 if (!t) | |
3822 { | |
3823 error(loc, "expression (%s) has no type", exp->toChars()); | |
3824 goto Lerr; | |
3825 } | |
3826 } | |
3827 | |
3828 if (idents.dim) | |
3829 { | |
3830 Dsymbol *s = t->toDsymbol(sc); | |
3831 for (size_t i = 0; i < idents.dim; i++) | |
3832 { | |
3833 if (!s) | |
3834 break; | |
3835 Identifier *id = (Identifier *)idents.data[i]; | |
3836 s = s->searchX(loc, sc, id); | |
3837 } | |
3838 if (s) | |
3839 { | |
3840 t = s->getType(); | |
3841 if (!t) | |
3842 { error(loc, "%s is not a type", s->toChars()); | |
3843 goto Lerr; | |
3844 } | |
3845 } | |
3846 else | |
3847 { error(loc, "cannot resolve .property for %s", toChars()); | |
3848 goto Lerr; | |
3849 } | |
3850 } | |
3851 return t; | |
3852 | |
3853 Lerr: | |
3854 return tvoid; | |
3855 } | |
3856 | |
3857 d_uns64 TypeTypeof::size(Loc loc) | |
3858 { | |
3859 if (exp->type) | |
3860 return exp->type->size(loc); | |
3861 else | |
3862 return TypeQualified::size(loc); | |
3863 } | |
3864 | |
3865 | |
3866 | |
3867 /***************************** TypeEnum *****************************/ | |
3868 | |
3869 TypeEnum::TypeEnum(EnumDeclaration *sym) | |
3870 : Type(Tenum, NULL) | |
3871 { | |
3872 this->sym = sym; | |
3873 } | |
3874 | |
3875 char *TypeEnum::toChars() | |
3876 { | |
3877 return sym->toChars(); | |
3878 } | |
3879 | |
486
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
3880 Type *TypeEnum::syntaxCopy() |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
3881 { |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
3882 return this; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
3883 } |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
3884 |
159 | 3885 Type *TypeEnum::semantic(Loc loc, Scope *sc) |
3886 { | |
3887 sym->semantic(sc); | |
3888 return merge(); | |
3889 } | |
3890 | |
3891 d_uns64 TypeEnum::size(Loc loc) | |
3892 { | |
3893 if (!sym->memtype) | |
3894 { | |
3895 error(loc, "enum %s is forward referenced", sym->toChars()); | |
3896 return 4; | |
3897 } | |
3898 return sym->memtype->size(loc); | |
3899 } | |
3900 | |
3901 unsigned TypeEnum::alignsize() | |
3902 { | |
3903 if (!sym->memtype) | |
3904 { | |
3905 #ifdef DEBUG | |
3906 printf("1: "); | |
3907 #endif | |
3908 error(0, "enum %s is forward referenced", sym->toChars()); | |
3909 return 4; | |
3910 } | |
3911 return sym->memtype->alignsize(); | |
3912 } | |
3913 | |
3914 Dsymbol *TypeEnum::toDsymbol(Scope *sc) | |
3915 { | |
3916 return sym; | |
3917 } | |
3918 | |
3919 Type *TypeEnum::toBasetype() | |
3920 { | |
3921 if (!sym->memtype) | |
3922 { | |
3923 #ifdef DEBUG | |
3924 printf("2: "); | |
3925 #endif | |
3926 error(sym->loc, "enum %s is forward referenced", sym->toChars()); | |
3927 return tint32; | |
3928 } | |
3929 return sym->memtype->toBasetype(); | |
3930 } | |
3931 | |
3932 void TypeEnum::toDecoBuffer(OutBuffer *buf) | |
3933 { char *name; | |
3934 | |
3935 name = sym->mangle(); | |
3936 // if (name[0] == '_' && name[1] == 'D') | |
3937 // name += 2; | |
3938 buf->printf("%c%s", mangleChar[ty], name); | |
3939 } | |
3940 | |
3941 void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
3942 { | |
3943 if (mod != this->mod) | |
3944 { toCBuffer3(buf, hgs, mod); | |
3945 return; | |
3946 } | |
3947 buf->writestring(sym->toChars()); | |
3948 } | |
3949 | |
3950 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
3951 { | |
3952 EnumMember *m; | |
3953 Dsymbol *s; | |
3954 Expression *em; | |
3955 | |
3956 #if LOGDOTEXP | |
3957 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars()); | |
3958 #endif | |
3959 if (!sym->symtab) | |
3960 goto Lfwd; | |
3961 s = sym->symtab->lookup(ident); | |
3962 if (!s) | |
3963 { | |
3964 return getProperty(e->loc, ident); | |
3965 } | |
3966 m = s->isEnumMember(); | |
3967 em = m->value->copy(); | |
3968 em->loc = e->loc; | |
3969 return em; | |
3970 | |
3971 Lfwd: | |
3972 error(e->loc, "forward reference of %s.%s", toChars(), ident->toChars()); | |
3973 return new IntegerExp(0, 0, this); | |
3974 } | |
3975 | |
3976 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident) | |
3977 { Expression *e; | |
3978 | |
3979 if (ident == Id::max) | |
3980 { | |
3981 if (!sym->symtab) | |
3982 goto Lfwd; | |
3983 e = new IntegerExp(0, sym->maxval, this); | |
3984 } | |
3985 else if (ident == Id::min) | |
3986 { | |
3987 if (!sym->symtab) | |
3988 goto Lfwd; | |
3989 e = new IntegerExp(0, sym->minval, this); | |
3990 } | |
3991 else if (ident == Id::init) | |
3992 { | |
3993 if (!sym->symtab) | |
3994 goto Lfwd; | |
3995 e = defaultInit(loc); | |
3996 } | |
3997 else | |
3998 { | |
3999 if (!sym->memtype) | |
4000 goto Lfwd; | |
4001 e = sym->memtype->getProperty(loc, ident); | |
4002 } | |
4003 return e; | |
4004 | |
4005 Lfwd: | |
4006 error(loc, "forward reference of %s.%s", toChars(), ident->toChars()); | |
4007 return new IntegerExp(0, 0, this); | |
4008 } | |
4009 | |
4010 int TypeEnum::isintegral() | |
4011 { | |
4012 return 1; | |
4013 } | |
4014 | |
4015 int TypeEnum::isfloating() | |
4016 { | |
4017 return 0; | |
4018 } | |
4019 | |
4020 int TypeEnum::isunsigned() | |
4021 { | |
4022 return sym->memtype->isunsigned(); | |
4023 } | |
4024 | |
4025 int TypeEnum::isscalar() | |
4026 { | |
4027 return 1; | |
4028 //return sym->memtype->isscalar(); | |
4029 } | |
4030 | |
4031 MATCH TypeEnum::implicitConvTo(Type *to) | |
4032 { MATCH m; | |
4033 | |
4034 //printf("TypeEnum::implicitConvTo()\n"); | |
4035 if (this->equals(to)) | |
4036 m = MATCHexact; // exact match | |
4037 else if (sym->memtype->implicitConvTo(to)) | |
4038 m = MATCHconvert; // match with conversions | |
4039 else | |
4040 m = MATCHnomatch; // no match | |
4041 return m; | |
4042 } | |
4043 | |
4044 Expression *TypeEnum::defaultInit(Loc loc) | |
4045 { | |
4046 #if LOGDEFAULTINIT | |
4047 printf("TypeEnum::defaultInit() '%s'\n", toChars()); | |
4048 #endif | |
4049 // Initialize to first member of enum | |
4050 Expression *e; | |
4051 e = new IntegerExp(loc, sym->defaultval, this); | |
4052 return e; | |
4053 } | |
4054 | |
4055 int TypeEnum::isZeroInit() | |
4056 { | |
4057 return (sym->defaultval == 0); | |
4058 } | |
4059 | |
4060 int TypeEnum::hasPointers() | |
4061 { | |
4062 return toBasetype()->hasPointers(); | |
4063 } | |
4064 | |
4065 /***************************** TypeTypedef *****************************/ | |
4066 | |
4067 TypeTypedef::TypeTypedef(TypedefDeclaration *sym) | |
4068 : Type(Ttypedef, NULL) | |
4069 { | |
4070 this->sym = sym; | |
4071 } | |
4072 | |
4073 Type *TypeTypedef::syntaxCopy() | |
4074 { | |
4075 return this; | |
4076 } | |
4077 | |
4078 char *TypeTypedef::toChars() | |
4079 { | |
4080 return sym->toChars(); | |
4081 } | |
4082 | |
4083 Type *TypeTypedef::semantic(Loc loc, Scope *sc) | |
4084 { | |
4085 //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem); | |
4086 sym->semantic(sc); | |
4087 return merge(); | |
4088 } | |
4089 | |
4090 d_uns64 TypeTypedef::size(Loc loc) | |
4091 { | |
4092 return sym->basetype->size(loc); | |
4093 } | |
4094 | |
4095 unsigned TypeTypedef::alignsize() | |
4096 { | |
4097 return sym->basetype->alignsize(); | |
4098 } | |
4099 | |
4100 Dsymbol *TypeTypedef::toDsymbol(Scope *sc) | |
4101 { | |
4102 return sym; | |
4103 } | |
4104 | |
4105 void TypeTypedef::toDecoBuffer(OutBuffer *buf) | |
4106 { unsigned len; | |
4107 char *name; | |
4108 | |
4109 name = sym->mangle(); | |
4110 // if (name[0] == '_' && name[1] == 'D') | |
4111 // name += 2; | |
4112 //len = strlen(name); | |
4113 //buf->printf("%c%d%s", mangleChar[ty], len, name); | |
4114 buf->printf("%c%s", mangleChar[ty], name); | |
4115 } | |
4116 | |
4117 void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
4118 { | |
4119 //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars()); | |
4120 if (mod != this->mod) | |
4121 { toCBuffer3(buf, hgs, mod); | |
4122 return; | |
4123 } | |
4124 buf->writestring(sym->toChars()); | |
4125 } | |
4126 | |
4127 Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
4128 { | |
4129 #if LOGDOTEXP | |
4130 printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars()); | |
4131 #endif | |
4132 if (ident == Id::init) | |
4133 { | |
4134 return Type::dotExp(sc, e, ident); | |
4135 } | |
4136 return sym->basetype->dotExp(sc, e, ident); | |
4137 } | |
4138 | |
4139 Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident) | |
4140 { | |
4141 if (ident == Id::init) | |
4142 { | |
4143 return Type::getProperty(loc, ident); | |
4144 } | |
4145 return sym->basetype->getProperty(loc, ident); | |
4146 } | |
4147 | |
4148 int TypeTypedef::isbit() | |
4149 { | |
4150 return sym->basetype->isbit(); | |
4151 } | |
4152 | |
4153 int TypeTypedef::isintegral() | |
4154 { | |
4155 //printf("TypeTypedef::isintegral()\n"); | |
4156 //printf("sym = '%s'\n", sym->toChars()); | |
4157 //printf("basetype = '%s'\n", sym->basetype->toChars()); | |
4158 return sym->basetype->isintegral(); | |
4159 } | |
4160 | |
4161 int TypeTypedef::isfloating() | |
4162 { | |
4163 return sym->basetype->isfloating(); | |
4164 } | |
4165 | |
4166 int TypeTypedef::isreal() | |
4167 { | |
4168 return sym->basetype->isreal(); | |
4169 } | |
4170 | |
4171 int TypeTypedef::isimaginary() | |
4172 { | |
4173 return sym->basetype->isimaginary(); | |
4174 } | |
4175 | |
4176 int TypeTypedef::iscomplex() | |
4177 { | |
4178 return sym->basetype->iscomplex(); | |
4179 } | |
4180 | |
4181 int TypeTypedef::isunsigned() | |
4182 { | |
4183 return sym->basetype->isunsigned(); | |
4184 } | |
4185 | |
4186 int TypeTypedef::isscalar() | |
4187 { | |
4188 return sym->basetype->isscalar(); | |
4189 } | |
4190 | |
4191 int TypeTypedef::checkBoolean() | |
4192 { | |
4193 return sym->basetype->checkBoolean(); | |
4194 } | |
4195 | |
4196 Type *TypeTypedef::toBasetype() | |
4197 { | |
4198 if (sym->inuse) | |
4199 { | |
4200 sym->error("circular definition"); | |
4201 sym->basetype = Type::terror; | |
4202 return Type::terror; | |
4203 } | |
4204 sym->inuse = 1; | |
4205 Type *t = sym->basetype->toBasetype(); | |
4206 sym->inuse = 0; | |
4207 return t; | |
4208 } | |
4209 | |
4210 MATCH TypeTypedef::implicitConvTo(Type *to) | |
4211 { MATCH m; | |
4212 | |
4213 //printf("TypeTypedef::implicitConvTo()\n"); | |
4214 if (this->equals(to)) | |
4215 m = MATCHexact; // exact match | |
4216 else if (sym->basetype->implicitConvTo(to)) | |
4217 m = MATCHconvert; // match with conversions | |
4218 else | |
4219 m = MATCHnomatch; // no match | |
4220 return m; | |
4221 } | |
4222 | |
4223 Expression *TypeTypedef::defaultInit(Loc loc) | |
4224 { Expression *e; | |
4225 Type *bt; | |
4226 | |
4227 #if LOGDEFAULTINIT | |
4228 printf("TypeTypedef::defaultInit() '%s'\n", toChars()); | |
4229 #endif | |
4230 if (sym->init) | |
4231 { | |
4232 //sym->init->toExpression()->print(); | |
4233 return sym->init->toExpression(); | |
4234 } | |
4235 bt = sym->basetype; | |
4236 e = bt->defaultInit(loc); | |
4237 e->type = this; | |
4238 while (bt->ty == Tsarray) | |
4239 { | |
4240 e->type = bt->next; | |
4241 bt = bt->next->toBasetype(); | |
4242 } | |
4243 return e; | |
4244 } | |
4245 | |
4246 int TypeTypedef::isZeroInit() | |
4247 { | |
4248 if (sym->init) | |
4249 { | |
4250 if (sym->init->isVoidInitializer()) | |
4251 return 1; // initialize voids to 0 | |
4252 Expression *e = sym->init->toExpression(); | |
4253 if (e && e->isBool(FALSE)) | |
4254 return 1; | |
4255 return 0; // assume not | |
4256 } | |
4257 if (sym->inuse) | |
4258 { | |
4259 sym->error("circular definition"); | |
4260 sym->basetype = Type::terror; | |
4261 } | |
4262 sym->inuse = 1; | |
4263 int result = sym->basetype->isZeroInit(); | |
4264 sym->inuse = 0; | |
4265 return result; | |
4266 } | |
4267 | |
4268 int TypeTypedef::hasPointers() | |
4269 { | |
4270 return toBasetype()->hasPointers(); | |
4271 } | |
4272 | |
4273 /***************************** TypeStruct *****************************/ | |
4274 | |
4275 TypeStruct::TypeStruct(StructDeclaration *sym) | |
4276 : Type(Tstruct, NULL) | |
4277 { | |
4278 this->sym = sym; | |
4279 } | |
4280 | |
4281 char *TypeStruct::toChars() | |
4282 { | |
4283 //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco); | |
4284 TemplateInstance *ti = sym->parent->isTemplateInstance(); | |
4285 if (ti && ti->toAlias() == sym) | |
4286 return ti->toChars(); | |
4287 return sym->toChars(); | |
4288 } | |
4289 | |
4290 Type *TypeStruct::syntaxCopy() | |
4291 { | |
4292 return this; | |
4293 } | |
4294 | |
4295 Type *TypeStruct::semantic(Loc loc, Scope *sc) | |
4296 { | |
4297 //printf("TypeStruct::semantic('%s')\n", sym->toChars()); | |
4298 | |
4299 /* Cannot do semantic for sym because scope chain may not | |
4300 * be right. | |
4301 */ | |
4302 //sym->semantic(sc); | |
4303 | |
4304 return merge(); | |
4305 } | |
4306 | |
4307 d_uns64 TypeStruct::size(Loc loc) | |
4308 { | |
4309 return sym->size(loc); | |
4310 } | |
4311 | |
4312 unsigned TypeStruct::alignsize() | |
4313 { unsigned sz; | |
4314 | |
4315 sym->size(0); // give error for forward references | |
4316 sz = sym->alignsize; | |
4317 if (sz > sym->structalign) | |
4318 sz = sym->structalign; | |
4319 return sz; | |
4320 } | |
4321 | |
4322 Dsymbol *TypeStruct::toDsymbol(Scope *sc) | |
4323 { | |
4324 return sym; | |
4325 } | |
4326 | |
4327 void TypeStruct::toDecoBuffer(OutBuffer *buf) | |
4328 { unsigned len; | |
4329 char *name; | |
4330 | |
4331 name = sym->mangle(); | |
4332 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name); | |
4333 // if (name[0] == '_' && name[1] == 'D') | |
4334 // name += 2; | |
4335 //len = strlen(name); | |
4336 //buf->printf("%c%d%s", mangleChar[ty], len, name); | |
4337 buf->printf("%c%s", mangleChar[ty], name); | |
4338 } | |
4339 | |
4340 void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
4341 { | |
4342 if (mod != this->mod) | |
4343 { toCBuffer3(buf, hgs, mod); | |
4344 return; | |
4345 } | |
4346 TemplateInstance *ti = sym->parent->isTemplateInstance(); | |
4347 if (ti && ti->toAlias() == sym) | |
4348 buf->writestring(ti->toChars()); | |
4349 else | |
4350 buf->writestring(sym->toChars()); | |
4351 } | |
4352 | |
4353 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
4354 { unsigned offset; | |
4355 | |
4356 Expression *b; | |
4357 VarDeclaration *v; | |
4358 Dsymbol *s; | |
4359 DotVarExp *de; | |
4360 Declaration *d; | |
4361 | |
4362 #if LOGDOTEXP | |
4363 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); | |
4364 #endif | |
4365 if (!sym->members) | |
4366 { | |
4367 error(e->loc, "struct %s is forward referenced", sym->toChars()); | |
4368 return new IntegerExp(e->loc, 0, Type::tint32); | |
4369 } | |
4370 | |
4371 if (ident == Id::tupleof) | |
4372 { | |
4373 /* Create a TupleExp | |
4374 */ | |
336 | 4375 e = e->semantic(sc); // do this before turning on noaccesscheck |
159 | 4376 Expressions *exps = new Expressions; |
4377 exps->reserve(sym->fields.dim); | |
4378 for (size_t i = 0; i < sym->fields.dim; i++) | |
4379 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i]; | |
4380 Expression *fe = new DotVarExp(e->loc, e, v); | |
4381 exps->push(fe); | |
4382 } | |
4383 e = new TupleExp(e->loc, exps); | |
336 | 4384 sc = sc->push(); |
4385 sc->noaccesscheck = 1; | |
159 | 4386 e = e->semantic(sc); |
336 | 4387 sc->pop(); |
159 | 4388 return e; |
4389 } | |
4390 | |
4391 if (e->op == TOKdotexp) | |
4392 { DotExp *de = (DotExp *)e; | |
4393 | |
4394 if (de->e1->op == TOKimport) | |
4395 { | |
4396 ScopeExp *se = (ScopeExp *)de->e1; | |
4397 | |
4398 s = se->sds->search(e->loc, ident, 0); | |
4399 e = de->e1; | |
4400 goto L1; | |
4401 } | |
4402 } | |
4403 | |
4404 s = sym->search(e->loc, ident, 0); | |
4405 L1: | |
4406 if (!s) | |
4407 { | |
4408 //return getProperty(e->loc, ident); | |
4409 return Type::dotExp(sc, e, ident); | |
4410 } | |
336 | 4411 if (!s->isFuncDeclaration()) // because of overloading |
4412 s->checkDeprecated(e->loc, sc); | |
159 | 4413 s = s->toAlias(); |
4414 | |
4415 v = s->isVarDeclaration(); | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
4416 if (v && v->isConst() && v->type->toBasetype()->ty != Tsarray) |
159 | 4417 { ExpInitializer *ei = v->getExpInitializer(); |
4418 | |
4419 if (ei) | |
4420 { e = ei->exp->copy(); // need to copy it if it's a StringExp | |
4421 e = e->semantic(sc); | |
4422 return e; | |
4423 } | |
4424 } | |
4425 | |
4426 if (s->getType()) | |
4427 { | |
4428 //return new DotTypeExp(e->loc, e, s); | |
4429 return new TypeExp(e->loc, s->getType()); | |
4430 } | |
4431 | |
4432 EnumMember *em = s->isEnumMember(); | |
4433 if (em) | |
4434 { | |
4435 assert(em->value); | |
4436 return em->value->copy(); | |
4437 } | |
4438 | |
4439 TemplateMixin *tm = s->isTemplateMixin(); | |
4440 if (tm) | |
4441 { Expression *de; | |
4442 | |
4443 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); | |
4444 de->type = e->type; | |
4445 return de; | |
4446 } | |
4447 | |
4448 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
4449 if (td) | |
4450 { | |
4451 e = new DotTemplateExp(e->loc, e, td); | |
4452 e->semantic(sc); | |
4453 return e; | |
4454 } | |
4455 | |
4456 TemplateInstance *ti = s->isTemplateInstance(); | |
4457 if (ti) | |
4458 { if (!ti->semanticdone) | |
4459 ti->semantic(sc); | |
4460 s = ti->inst->toAlias(); | |
4461 if (!s->isTemplateInstance()) | |
4462 goto L1; | |
4463 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti)); | |
4464 de->type = e->type; | |
4465 return de; | |
4466 } | |
4467 | |
4468 d = s->isDeclaration(); | |
4469 #ifdef DEBUG | |
4470 if (!d) | |
4471 printf("d = %s '%s'\n", s->kind(), s->toChars()); | |
4472 #endif | |
4473 assert(d); | |
4474 | |
4475 if (e->op == TOKtype) | |
4476 { FuncDeclaration *fd = sc->func; | |
4477 | |
4478 if (d->needThis() && fd && fd->vthis) | |
4479 { | |
4480 e = new DotVarExp(e->loc, new ThisExp(e->loc), d); | |
4481 e = e->semantic(sc); | |
4482 return e; | |
4483 } | |
4484 if (d->isTupleDeclaration()) | |
4485 { | |
4486 e = new TupleExp(e->loc, d->isTupleDeclaration()); | |
4487 e = e->semantic(sc); | |
4488 return e; | |
4489 } | |
4490 return new VarExp(e->loc, d); | |
4491 } | |
4492 | |
4493 if (d->isDataseg()) | |
4494 { | |
4495 // (e, d) | |
4496 VarExp *ve; | |
4497 | |
4498 accessCheck(e->loc, sc, e, d); | |
4499 ve = new VarExp(e->loc, d); | |
4500 e = new CommaExp(e->loc, e, ve); | |
4501 e->type = d->type; | |
4502 return e; | |
4503 } | |
4504 | |
4505 if (v) | |
4506 { | |
4507 if (v->toParent() != sym) | |
4508 sym->error(e->loc, "'%s' is not a member", v->toChars()); | |
4509 | |
4510 // *(&e + offset) | |
4511 accessCheck(e->loc, sc, e, d); | |
585
fbb1a366cfbc
Complex number should now follow the D ABI on x86. They're also treated as first class values now. Big change.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
509
diff
changeset
|
4512 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
4513 // LDC we don't want dot exprs turned into pointer arithmetic. it complicates things for no apparent gain |
585
fbb1a366cfbc
Complex number should now follow the D ABI on x86. They're also treated as first class values now. Big change.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
509
diff
changeset
|
4514 #ifndef IN_LLVM |
159 | 4515 b = new AddrExp(e->loc, e); |
4516 b->type = e->type->pointerTo(); | |
4517 b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32)); | |
4518 b->type = v->type->pointerTo(); | |
4519 e = new PtrExp(e->loc, b); | |
4520 e->type = v->type; | |
4521 return e; | |
585
fbb1a366cfbc
Complex number should now follow the D ABI on x86. They're also treated as first class values now. Big change.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
509
diff
changeset
|
4522 #endif |
159 | 4523 } |
4524 | |
4525 de = new DotVarExp(e->loc, e, d); | |
4526 return de->semantic(sc); | |
4527 } | |
4528 | |
4529 unsigned TypeStruct::memalign(unsigned salign) | |
4530 { | |
4531 sym->size(0); // give error for forward references | |
4532 return sym->structalign; | |
4533 } | |
4534 | |
4535 Expression *TypeStruct::defaultInit(Loc loc) | |
4536 { Symbol *s; | |
4537 Declaration *d; | |
4538 | |
4539 #if LOGDEFAULTINIT | |
4540 printf("TypeStruct::defaultInit() '%s'\n", toChars()); | |
4541 #endif | |
4542 s = sym->toInitializer(); | |
4543 d = new SymbolDeclaration(sym->loc, s, sym); | |
4544 assert(d); | |
4545 d->type = this; | |
4546 return new VarExp(sym->loc, d); | |
4547 } | |
4548 | |
4549 int TypeStruct::isZeroInit() | |
4550 { | |
4551 return sym->zeroInit; | |
4552 } | |
4553 | |
4554 int TypeStruct::checkBoolean() | |
4555 { | |
4556 return FALSE; | |
4557 } | |
4558 | |
4559 int TypeStruct::hasPointers() | |
4560 { | |
4561 StructDeclaration *s = sym; | |
4562 | |
4563 sym->size(0); // give error for forward references | |
4564 if (s->members) | |
4565 { | |
4566 for (size_t i = 0; i < s->members->dim; i++) | |
4567 { | |
4568 Dsymbol *sm = (Dsymbol *)s->members->data[i]; | |
4569 if (sm->hasPointers()) | |
4570 return TRUE; | |
4571 } | |
4572 } | |
4573 return FALSE; | |
4574 } | |
4575 | |
4576 | |
4577 /***************************** TypeClass *****************************/ | |
4578 | |
4579 TypeClass::TypeClass(ClassDeclaration *sym) | |
4580 : Type(Tclass, NULL) | |
4581 { | |
4582 this->sym = sym; | |
4583 } | |
4584 | |
4585 char *TypeClass::toChars() | |
4586 { | |
4587 return sym->toPrettyChars(); | |
4588 } | |
4589 | |
4590 Type *TypeClass::syntaxCopy() | |
4591 { | |
4592 return this; | |
4593 } | |
4594 | |
4595 Type *TypeClass::semantic(Loc loc, Scope *sc) | |
4596 { | |
4597 //printf("TypeClass::semantic(%s)\n", sym->toChars()); | |
4598 if (sym->scope) | |
4599 sym->semantic(sym->scope); | |
4600 return merge(); | |
4601 } | |
4602 | |
4603 d_uns64 TypeClass::size(Loc loc) | |
4604 { | |
4605 return PTRSIZE; | |
4606 } | |
4607 | |
4608 Dsymbol *TypeClass::toDsymbol(Scope *sc) | |
4609 { | |
4610 return sym; | |
4611 } | |
4612 | |
4613 void TypeClass::toDecoBuffer(OutBuffer *buf) | |
4614 { unsigned len; | |
4615 char *name; | |
4616 | |
4617 name = sym->mangle(); | |
4618 // if (name[0] == '_' && name[1] == 'D') | |
4619 // name += 2; | |
4620 //printf("TypeClass::toDecoBuffer('%s') = '%s'\n", toChars(), name); | |
4621 //len = strlen(name); | |
4622 //buf->printf("%c%d%s", mangleChar[ty], len, name); | |
4623 buf->printf("%c%s", mangleChar[ty], name); | |
4624 } | |
4625 | |
4626 void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
4627 { | |
4628 if (mod != this->mod) | |
4629 { toCBuffer3(buf, hgs, mod); | |
4630 return; | |
4631 } | |
4632 buf->writestring(sym->toChars()); | |
4633 } | |
4634 | |
4635 Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) | |
4636 { unsigned offset; | |
4637 | |
4638 Expression *b; | |
4639 VarDeclaration *v; | |
4640 Dsymbol *s; | |
4641 DotVarExp *de; | |
4642 Declaration *d; | |
4643 | |
4644 #if LOGDOTEXP | |
4645 printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars()); | |
4646 #endif | |
4647 | |
4648 if (e->op == TOKdotexp) | |
4649 { DotExp *de = (DotExp *)e; | |
4650 | |
4651 if (de->e1->op == TOKimport) | |
4652 { | |
4653 ScopeExp *se = (ScopeExp *)de->e1; | |
4654 | |
4655 s = se->sds->search(e->loc, ident, 0); | |
4656 e = de->e1; | |
4657 goto L1; | |
4658 } | |
4659 } | |
4660 | |
4661 if (ident == Id::tupleof) | |
4662 { | |
4663 /* Create a TupleExp | |
4664 */ | |
336 | 4665 e = e->semantic(sc); // do this before turning on noaccesscheck |
159 | 4666 Expressions *exps = new Expressions; |
4667 exps->reserve(sym->fields.dim); | |
4668 for (size_t i = 0; i < sym->fields.dim; i++) | |
4669 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i]; | |
4670 Expression *fe = new DotVarExp(e->loc, e, v); | |
4671 exps->push(fe); | |
4672 } | |
4673 e = new TupleExp(e->loc, exps); | |
336 | 4674 sc = sc->push(); |
4675 sc->noaccesscheck = 1; | |
159 | 4676 e = e->semantic(sc); |
336 | 4677 sc->pop(); |
159 | 4678 return e; |
4679 } | |
4680 | |
4681 s = sym->search(e->loc, ident, 0); | |
4682 L1: | |
4683 if (!s) | |
4684 { | |
4685 // See if it's a base class | |
4686 ClassDeclaration *cbase; | |
4687 for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass) | |
4688 { | |
4689 if (cbase->ident->equals(ident)) | |
4690 { | |
4691 e = new DotTypeExp(0, e, cbase); | |
4692 return e; | |
4693 } | |
4694 } | |
4695 | |
4696 if (ident == Id::classinfo) | |
4697 { | |
4698 Type *t; | |
4699 | |
4700 assert(ClassDeclaration::classinfo); | |
4701 t = ClassDeclaration::classinfo->type; | |
4702 if (e->op == TOKtype || e->op == TOKdottype) | |
4703 { | |
4704 /* For type.classinfo, we know the classinfo | |
4705 * at compile time. | |
4706 */ | |
4707 if (!sym->vclassinfo) | |
4708 sym->vclassinfo = new ClassInfoDeclaration(sym); | |
4709 e = new VarExp(e->loc, sym->vclassinfo); | |
4710 e = e->addressOf(sc); | |
4711 e->type = t; // do this so we don't get redundant dereference | |
4712 } | |
4713 else | |
4714 { | |
4715 /* For class objects, the classinfo reference is the first | |
4716 * entry in the vtbl[] | |
4717 */ | |
4718 #if IN_LLVM | |
4719 | |
4720 Type* ct; | |
4721 if (sym->isInterfaceDeclaration()) { | |
4722 ct = t->pointerTo()->pointerTo()->pointerTo(); | |
4723 } | |
4724 else { | |
4725 ct = t->pointerTo()->pointerTo(); | |
4726 } | |
4727 | |
4728 e = e->castTo(sc, ct); | |
4729 e = new PtrExp(e->loc, e); | |
4730 e->type = ct->next; | |
4731 e = new PtrExp(e->loc, e); | |
4732 e->type = ct->next->next; | |
4733 | |
4734 if (sym->isInterfaceDeclaration()) | |
4735 { | |
4736 if (sym->isCOMinterface()) | |
4737 { /* COM interface vtbl[]s are different in that the | |
4738 * first entry is always pointer to QueryInterface(). | |
4739 * We can't get a .classinfo for it. | |
4740 */ | |
4741 error(e->loc, "no .classinfo for COM interface objects"); | |
4742 } | |
4743 /* For an interface, the first entry in the vtbl[] | |
4744 * is actually a pointer to an instance of struct Interface. | |
4745 * The first member of Interface is the .classinfo, | |
4746 * so add an extra pointer indirection. | |
4747 */ | |
4748 e = new PtrExp(e->loc, e); | |
4749 e->type = ct->next->next->next; | |
4750 } | |
336 | 4751 } |
159 | 4752 |
4753 #else | |
4754 | |
4755 e = new PtrExp(e->loc, e); | |
4756 e->type = t->pointerTo(); | |
4757 if (sym->isInterfaceDeclaration()) | |
4758 { | |
4759 if (sym->isCOMinterface()) | |
4760 { /* COM interface vtbl[]s are different in that the | |
4761 * first entry is always pointer to QueryInterface(). | |
4762 * We can't get a .classinfo for it. | |
4763 */ | |
4764 error(e->loc, "no .classinfo for COM interface objects"); | |
4765 } | |
4766 /* For an interface, the first entry in the vtbl[] | |
4767 * is actually a pointer to an instance of struct Interface. | |
4768 * The first member of Interface is the .classinfo, | |
4769 * so add an extra pointer indirection. | |
4770 */ | |
4771 e->type = e->type->pointerTo(); | |
4772 e = new PtrExp(e->loc, e); | |
4773 e->type = t->pointerTo(); | |
4774 } | |
4775 e = new PtrExp(e->loc, e, t); | |
336 | 4776 } |
4777 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
658
diff
changeset
|
4778 #endif // !LDC |
336 | 4779 |
4780 return e; | |
4781 } | |
4782 | |
4783 if (ident == Id::__vptr) | |
4784 { /* The pointer to the vtbl[] | |
4785 * *cast(void***)e | |
4786 */ | |
4787 e = e->castTo(sc, tvoidptr->pointerTo()->pointerTo()); | |
4788 e = new PtrExp(e->loc, e); | |
4789 e = e->semantic(sc); | |
4790 return e; | |
4791 } | |
4792 | |
4793 if (ident == Id::__monitor) | |
4794 { /* The handle to the monitor (call it a void*) | |
4795 * *(cast(void**)e + 1) | |
4796 */ | |
4797 e = e->castTo(sc, tvoidptr->pointerTo()); | |
4798 e = new AddExp(e->loc, e, new IntegerExp(1)); | |
4799 e = new PtrExp(e->loc, e); | |
4800 e = e->semantic(sc); | |
159 | 4801 return e; |
4802 } | |
4803 | |
4804 if (ident == Id::typeinfo) | |
4805 { | |
4806 if (!global.params.useDeprecated) | |
4807 error(e->loc, ".typeinfo deprecated, use typeid(type)"); | |
4808 return getTypeInfo(sc); | |
4809 } | |
4810 if (ident == Id::outer && sym->vthis) | |
4811 { | |
4812 s = sym->vthis; | |
4813 } | |
4814 else | |
4815 { | |
4816 //return getProperty(e->loc, ident); | |
4817 return Type::dotExp(sc, e, ident); | |
4818 } | |
4819 } | |
336 | 4820 if (!s->isFuncDeclaration()) // because of overloading |
4821 s->checkDeprecated(e->loc, sc); | |
159 | 4822 s = s->toAlias(); |
4823 v = s->isVarDeclaration(); | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
4824 if (v && v->isConst() && v->type->toBasetype()->ty != Tsarray) |
159 | 4825 { ExpInitializer *ei = v->getExpInitializer(); |
4826 | |
4827 if (ei) | |
4828 { e = ei->exp->copy(); // need to copy it if it's a StringExp | |
4829 e = e->semantic(sc); | |
4830 return e; | |
4831 } | |
4832 } | |
4833 | |
4834 if (s->getType()) | |
4835 { | |
4836 // if (e->op == TOKtype) | |
4837 return new TypeExp(e->loc, s->getType()); | |
4838 // return new DotTypeExp(e->loc, e, s); | |
4839 } | |
4840 | |
4841 EnumMember *em = s->isEnumMember(); | |
4842 if (em) | |
4843 { | |
4844 assert(em->value); | |
4845 return em->value->copy(); | |
4846 } | |
4847 | |
4848 TemplateMixin *tm = s->isTemplateMixin(); | |
4849 if (tm) | |
4850 { Expression *de; | |
4851 | |
4852 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); | |
4853 de->type = e->type; | |
4854 return de; | |
4855 } | |
4856 | |
4857 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
4858 if (td) | |
4859 { | |
4860 e = new DotTemplateExp(e->loc, e, td); | |
4861 e->semantic(sc); | |
4862 return e; | |
4863 } | |
4864 | |
4865 TemplateInstance *ti = s->isTemplateInstance(); | |
4866 if (ti) | |
4867 { if (!ti->semanticdone) | |
4868 ti->semantic(sc); | |
4869 s = ti->inst->toAlias(); | |
4870 if (!s->isTemplateInstance()) | |
4871 goto L1; | |
4872 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti)); | |
4873 de->type = e->type; | |
4874 return de; | |
4875 } | |
4876 | |
4877 d = s->isDeclaration(); | |
4878 if (!d) | |
4879 { | |
4880 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars()); | |
4881 return new IntegerExp(e->loc, 1, Type::tint32); | |
4882 } | |
4883 | |
4884 if (e->op == TOKtype) | |
4885 { | |
4886 VarExp *ve; | |
4887 | |
4888 if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration())) | |
4889 { | |
4890 if (sc->func) | |
4891 { | |
4892 ClassDeclaration *thiscd; | |
4893 thiscd = sc->func->toParent()->isClassDeclaration(); | |
4894 | |
4895 if (thiscd) | |
4896 { | |
4897 ClassDeclaration *cd = e->type->isClassHandle(); | |
4898 | |
4899 if (cd == thiscd) | |
4900 { | |
4901 e = new ThisExp(e->loc); | |
4902 e = new DotTypeExp(e->loc, e, cd); | |
4903 de = new DotVarExp(e->loc, e, d); | |
4904 e = de->semantic(sc); | |
4905 return e; | |
4906 } | |
4907 else if ((!cd || !cd->isBaseOf(thiscd, NULL)) && | |
4908 !d->isFuncDeclaration()) | |
4909 e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars()); | |
4910 } | |
4911 } | |
4912 | |
4913 de = new DotVarExp(e->loc, new ThisExp(e->loc), d); | |
4914 e = de->semantic(sc); | |
4915 return e; | |
4916 } | |
4917 else if (d->isTupleDeclaration()) | |
4918 { | |
4919 e = new TupleExp(e->loc, d->isTupleDeclaration()); | |
4920 e = e->semantic(sc); | |
4921 return e; | |
4922 } | |
4923 else | |
4924 ve = new VarExp(e->loc, d); | |
4925 return ve; | |
4926 } | |
4927 | |
4928 if (d->isDataseg()) | |
4929 { | |
4930 // (e, d) | |
4931 VarExp *ve; | |
4932 | |
4933 accessCheck(e->loc, sc, e, d); | |
4934 ve = new VarExp(e->loc, d); | |
4935 e = new CommaExp(e->loc, e, ve); | |
4936 e->type = d->type; | |
4937 return e; | |
4938 } | |
4939 | |
4940 if (d->parent && d->toParent()->isModule()) | |
4941 { | |
4942 // (e, d) | |
4943 VarExp *ve; | |
4944 | |
4945 ve = new VarExp(e->loc, d); | |
4946 e = new CommaExp(e->loc, e, ve); | |
4947 e->type = d->type; | |
4948 return e; | |
4949 } | |
4950 | |
4951 de = new DotVarExp(e->loc, e, d); | |
4952 return de->semantic(sc); | |
4953 } | |
4954 | |
4955 ClassDeclaration *TypeClass::isClassHandle() | |
4956 { | |
4957 return sym; | |
4958 } | |
4959 | |
4960 int TypeClass::isauto() | |
4961 { | |
4962 return sym->isauto; | |
4963 } | |
4964 | |
4965 int TypeClass::isBaseOf(Type *t, int *poffset) | |
4966 { | |
4967 if (t->ty == Tclass) | |
4968 { ClassDeclaration *cd; | |
4969 | |
4970 cd = ((TypeClass *)t)->sym; | |
4971 if (sym->isBaseOf(cd, poffset)) | |
4972 return 1; | |
4973 } | |
4974 return 0; | |
4975 } | |
4976 | |
4977 MATCH TypeClass::implicitConvTo(Type *to) | |
4978 { | |
4979 //printf("TypeClass::implicitConvTo('%s')\n", to->toChars()); | |
4980 if (this == to) | |
4981 return MATCHexact; | |
4982 | |
4983 ClassDeclaration *cdto = to->isClassHandle(); | |
4984 if (cdto && cdto->isBaseOf(sym, NULL)) | |
4985 { //printf("is base\n"); | |
4986 return MATCHconvert; | |
4987 } | |
4988 | |
4989 if (global.params.Dversion == 1) | |
4990 { | |
4991 // Allow conversion to (void *) | |
4992 if (to->ty == Tpointer && to->next->ty == Tvoid) | |
4993 return MATCHconvert; | |
4994 } | |
4995 | |
4996 return MATCHnomatch; | |
4997 } | |
4998 | |
4999 Expression *TypeClass::defaultInit(Loc loc) | |
5000 { | |
5001 #if LOGDEFAULTINIT | |
5002 printf("TypeClass::defaultInit() '%s'\n", toChars()); | |
5003 #endif | |
5004 Expression *e; | |
5005 e = new NullExp(loc); | |
5006 e->type = this; | |
5007 return e; | |
5008 } | |
5009 | |
5010 int TypeClass::isZeroInit() | |
5011 { | |
5012 return 1; | |
5013 } | |
5014 | |
5015 int TypeClass::checkBoolean() | |
5016 { | |
5017 return TRUE; | |
5018 } | |
5019 | |
5020 int TypeClass::hasPointers() | |
5021 { | |
5022 return TRUE; | |
5023 } | |
5024 | |
5025 /***************************** TypeTuple *****************************/ | |
5026 | |
5027 TypeTuple::TypeTuple(Arguments *arguments) | |
5028 : Type(Ttuple, NULL) | |
5029 { | |
5030 //printf("TypeTuple(this = %p)\n", this); | |
5031 this->arguments = arguments; | |
5032 #ifdef DEBUG | |
5033 if (arguments) | |
5034 { | |
5035 for (size_t i = 0; i < arguments->dim; i++) | |
5036 { | |
5037 Argument *arg = (Argument *)arguments->data[i]; | |
5038 assert(arg && arg->type); | |
5039 } | |
5040 } | |
5041 #endif | |
5042 } | |
5043 | |
5044 /**************** | |
5045 * Form TypeTuple from the types of the expressions. | |
5046 * Assume exps[] is already tuple expanded. | |
5047 */ | |
5048 | |
5049 TypeTuple::TypeTuple(Expressions *exps) | |
5050 : Type(Ttuple, NULL) | |
5051 { | |
5052 Arguments *arguments = new Arguments; | |
5053 if (exps) | |
5054 { | |
5055 arguments->setDim(exps->dim); | |
5056 for (size_t i = 0; i < exps->dim; i++) | |
5057 { Expression *e = (Expression *)exps->data[i]; | |
5058 if (e->type->ty == Ttuple) | |
5059 e->error("cannot form tuple of tuples"); | |
5060 Argument *arg = new Argument(STCin, e->type, NULL, NULL); | |
5061 arguments->data[i] = (void *)arg; | |
5062 } | |
5063 } | |
5064 this->arguments = arguments; | |
5065 } | |
5066 | |
5067 Type *TypeTuple::syntaxCopy() | |
5068 { | |
5069 Arguments *args = Argument::arraySyntaxCopy(arguments); | |
5070 Type *t = new TypeTuple(args); | |
5071 return t; | |
5072 } | |
5073 | |
5074 Type *TypeTuple::semantic(Loc loc, Scope *sc) | |
5075 { | |
5076 //printf("TypeTuple::semantic(this = %p)\n", this); | |
5077 if (!deco) | |
5078 deco = merge()->deco; | |
5079 | |
5080 /* Don't return merge(), because a tuple with one type has the | |
5081 * same deco as that type. | |
5082 */ | |
5083 return this; | |
5084 } | |
5085 | |
5086 int TypeTuple::equals(Object *o) | |
5087 { Type *t; | |
5088 | |
5089 t = (Type *)o; | |
5090 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars()); | |
5091 if (this == t) | |
5092 { | |
5093 return 1; | |
5094 } | |
5095 if (t->ty == Ttuple) | |
5096 { TypeTuple *tt = (TypeTuple *)t; | |
5097 | |
5098 if (arguments->dim == tt->arguments->dim) | |
5099 { | |
5100 for (size_t i = 0; i < tt->arguments->dim; i++) | |
5101 { Argument *arg1 = (Argument *)arguments->data[i]; | |
5102 Argument *arg2 = (Argument *)tt->arguments->data[i]; | |
5103 | |
5104 if (!arg1->type->equals(arg2->type)) | |
5105 return 0; | |
5106 } | |
5107 return 1; | |
5108 } | |
5109 } | |
5110 return 0; | |
5111 } | |
5112 | |
5113 Type *TypeTuple::reliesOnTident() | |
5114 { | |
5115 if (arguments) | |
5116 { | |
5117 for (size_t i = 0; i < arguments->dim; i++) | |
5118 { | |
5119 Argument *arg = (Argument *)arguments->data[i]; | |
5120 Type *t = arg->type->reliesOnTident(); | |
5121 if (t) | |
5122 return t; | |
5123 } | |
5124 } | |
5125 return NULL; | |
5126 } | |
5127 | |
5128 void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
5129 { | |
5130 Argument::argsToCBuffer(buf, hgs, arguments, 0); | |
5131 } | |
5132 | |
5133 void TypeTuple::toDecoBuffer(OutBuffer *buf) | |
5134 { | |
5135 //printf("TypeTuple::toDecoBuffer() this = %p\n", this); | |
5136 OutBuffer buf2; | |
5137 Argument::argsToDecoBuffer(&buf2, arguments); | |
5138 unsigned len = buf2.offset; | |
5139 buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData()); | |
5140 } | |
5141 | |
5142 Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) | |
5143 { Expression *e; | |
5144 | |
5145 #if LOGDOTEXP | |
5146 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars()); | |
5147 #endif | |
5148 if (ident == Id::length) | |
5149 { | |
5150 e = new IntegerExp(loc, arguments->dim, Type::tsize_t); | |
5151 } | |
5152 else | |
5153 { | |
5154 error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars()); | |
5155 e = new IntegerExp(loc, 1, Type::tint32); | |
5156 } | |
5157 return e; | |
5158 } | |
5159 | |
5160 /***************************** TypeSlice *****************************/ | |
5161 | |
5162 /* This is so we can slice a TypeTuple */ | |
5163 | |
5164 TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr) | |
5165 : Type(Tslice, next) | |
5166 { | |
5167 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars()); | |
5168 this->lwr = lwr; | |
5169 this->upr = upr; | |
5170 } | |
5171 | |
5172 Type *TypeSlice::syntaxCopy() | |
5173 { | |
5174 Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy()); | |
5175 return t; | |
5176 } | |
5177 | |
5178 Type *TypeSlice::semantic(Loc loc, Scope *sc) | |
5179 { | |
5180 //printf("TypeSlice::semantic() %s\n", toChars()); | |
5181 next = next->semantic(loc, sc); | |
5182 //printf("next: %s\n", next->toChars()); | |
5183 | |
5184 Type *tbn = next->toBasetype(); | |
5185 if (tbn->ty != Ttuple) | |
5186 { error(loc, "can only slice tuple types, not %s", tbn->toChars()); | |
5187 return Type::terror; | |
5188 } | |
5189 TypeTuple *tt = (TypeTuple *)tbn; | |
5190 | |
5191 lwr = semanticLength(sc, tbn, lwr); | |
5192 lwr = lwr->optimize(WANTvalue); | |
5193 uinteger_t i1 = lwr->toUInteger(); | |
5194 | |
5195 upr = semanticLength(sc, tbn, upr); | |
5196 upr = upr->optimize(WANTvalue); | |
5197 uinteger_t i2 = upr->toUInteger(); | |
5198 | |
5199 if (!(i1 <= i2 && i2 <= tt->arguments->dim)) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
5200 { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim); |
159 | 5201 return Type::terror; |
5202 } | |
5203 | |
5204 Arguments *args = new Arguments; | |
5205 args->reserve(i2 - i1); | |
5206 for (size_t i = i1; i < i2; i++) | |
5207 { Argument *arg = (Argument *)tt->arguments->data[i]; | |
5208 args->push(arg); | |
5209 } | |
5210 | |
5211 return new TypeTuple(args); | |
5212 } | |
5213 | |
5214 void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) | |
5215 { | |
5216 next->resolve(loc, sc, pe, pt, ps); | |
5217 if (*pe) | |
5218 { // It's really a slice expression | |
5219 Expression *e; | |
5220 e = new SliceExp(loc, *pe, lwr, upr); | |
5221 *pe = e; | |
5222 } | |
5223 else if (*ps) | |
5224 { Dsymbol *s = *ps; | |
5225 TupleDeclaration *td = s->isTupleDeclaration(); | |
5226 if (td) | |
5227 { | |
5228 /* It's a slice of a TupleDeclaration | |
5229 */ | |
5230 ScopeDsymbol *sym = new ArrayScopeSymbol(td); | |
5231 sym->parent = sc->scopesym; | |
5232 sc = sc->push(sym); | |
5233 | |
5234 lwr = lwr->semantic(sc); | |
5235 lwr = lwr->optimize(WANTvalue); | |
5236 uinteger_t i1 = lwr->toUInteger(); | |
5237 | |
5238 upr = upr->semantic(sc); | |
5239 upr = upr->optimize(WANTvalue); | |
5240 uinteger_t i2 = upr->toUInteger(); | |
5241 | |
5242 sc = sc->pop(); | |
5243 | |
5244 if (!(i1 <= i2 && i2 <= td->objects->dim)) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
5245 { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim); |
159 | 5246 goto Ldefault; |
5247 } | |
5248 | |
5249 if (i1 == 0 && i2 == td->objects->dim) | |
5250 { | |
5251 *ps = td; | |
5252 return; | |
5253 } | |
5254 | |
5255 /* Create a new TupleDeclaration which | |
5256 * is a slice [i1..i2] out of the old one. | |
5257 */ | |
5258 Objects *objects = new Objects; | |
5259 objects->setDim(i2 - i1); | |
5260 for (size_t i = 0; i < objects->dim; i++) | |
5261 { | |
5262 objects->data[i] = td->objects->data[(size_t)i1 + i]; | |
5263 } | |
5264 | |
5265 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects); | |
5266 *ps = tds; | |
5267 } | |
5268 else | |
5269 goto Ldefault; | |
5270 } | |
5271 else | |
5272 { | |
5273 Ldefault: | |
5274 Type::resolve(loc, sc, pe, pt, ps); | |
5275 } | |
5276 } | |
5277 | |
5278 void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) | |
5279 { | |
5280 if (mod != this->mod) | |
5281 { toCBuffer3(buf, hgs, mod); | |
5282 return; | |
5283 } | |
5284 next->toCBuffer2(buf, hgs, this->mod); | |
5285 | |
5286 buf->printf("[%s .. ", lwr->toChars()); | |
5287 buf->printf("%s]", upr->toChars()); | |
5288 } | |
5289 | |
5290 /***************************** Argument *****************************/ | |
5291 | |
5292 Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg) | |
5293 { | |
5294 this->type = type; | |
5295 this->ident = ident; | |
5296 this->storageClass = storageClass; | |
5297 this->defaultArg = defaultArg; | |
445
cc40db549aea
Changed the handling of variadic intrinsics a bit.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
5298 this->llvmAttrs = 0; |
159 | 5299 } |
5300 | |
5301 Argument *Argument::syntaxCopy() | |
5302 { | |
5303 Argument *a = new Argument(storageClass, | |
5304 type ? type->syntaxCopy() : NULL, | |
5305 ident, | |
5306 defaultArg ? defaultArg->syntaxCopy() : NULL); | |
445
cc40db549aea
Changed the handling of variadic intrinsics a bit.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
5307 a->llvmAttrs = llvmAttrs; |
159 | 5308 return a; |
5309 } | |
5310 | |
5311 Arguments *Argument::arraySyntaxCopy(Arguments *args) | |
5312 { Arguments *a = NULL; | |
5313 | |
5314 if (args) | |
5315 { | |
5316 a = new Arguments(); | |
5317 a->setDim(args->dim); | |
5318 for (size_t i = 0; i < a->dim; i++) | |
5319 { Argument *arg = (Argument *)args->data[i]; | |
5320 | |
5321 arg = arg->syntaxCopy(); | |
5322 a->data[i] = (void *)arg; | |
5323 } | |
5324 } | |
5325 return a; | |
5326 } | |
5327 | |
5328 char *Argument::argsTypesToChars(Arguments *args, int varargs) | |
5329 { OutBuffer *buf; | |
5330 | |
5331 buf = new OutBuffer(); | |
5332 | |
5333 buf->writeByte('('); | |
5334 if (args) | |
5335 { int i; | |
5336 OutBuffer argbuf; | |
5337 HdrGenState hgs; | |
5338 | |
5339 for (i = 0; i < args->dim; i++) | |
5340 { Argument *arg; | |
5341 | |
5342 if (i) | |
5343 buf->writeByte(','); | |
5344 arg = (Argument *)args->data[i]; | |
5345 argbuf.reset(); | |
5346 arg->type->toCBuffer2(&argbuf, &hgs, 0); | |
5347 buf->write(&argbuf); | |
5348 } | |
5349 if (varargs) | |
5350 { | |
5351 if (i && varargs == 1) | |
5352 buf->writeByte(','); | |
5353 buf->writestring("..."); | |
5354 } | |
5355 } | |
5356 buf->writeByte(')'); | |
5357 | |
5358 return buf->toChars(); | |
5359 } | |
5360 | |
5361 void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs) | |
5362 { | |
5363 buf->writeByte('('); | |
5364 if (arguments) | |
5365 { int i; | |
5366 OutBuffer argbuf; | |
5367 | |
5368 for (i = 0; i < arguments->dim; i++) | |
5369 { Argument *arg; | |
5370 | |
5371 if (i) | |
5372 buf->writestring(", "); | |
5373 arg = (Argument *)arguments->data[i]; | |
5374 if (arg->storageClass & STCout) | |
5375 buf->writestring("out "); | |
5376 else if (arg->storageClass & STCref) | |
5377 buf->writestring((global.params.Dversion == 1) | |
5378 ? (char *)"inout " : (char *)"ref "); | |
5379 else if (arg->storageClass & STClazy) | |
5380 buf->writestring("lazy "); | |
5381 argbuf.reset(); | |
5382 arg->type->toCBuffer(&argbuf, arg->ident, hgs); | |
5383 if (arg->defaultArg) | |
5384 { | |
5385 argbuf.writestring(" = "); | |
5386 arg->defaultArg->toCBuffer(&argbuf, hgs); | |
5387 } | |
5388 buf->write(&argbuf); | |
5389 } | |
5390 if (varargs) | |
5391 { | |
5392 if (i && varargs == 1) | |
5393 buf->writeByte(','); | |
5394 buf->writestring("..."); | |
5395 } | |
5396 } | |
5397 buf->writeByte(')'); | |
5398 } | |
5399 | |
5400 | |
5401 void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments) | |
5402 { | |
5403 //printf("Argument::argsToDecoBuffer()\n"); | |
5404 | |
5405 // Write argument types | |
5406 if (arguments) | |
5407 { | |
5408 size_t dim = Argument::dim(arguments); | |
5409 for (size_t i = 0; i < dim; i++) | |
5410 { | |
5411 Argument *arg = Argument::getNth(arguments, i); | |
5412 arg->toDecoBuffer(buf); | |
5413 } | |
5414 } | |
5415 } | |
5416 | |
5417 /**************************************************** | |
5418 * Determine if parameter is a lazy array of delegates. | |
5419 * If so, return the return type of those delegates. | |
5420 * If not, return NULL. | |
5421 */ | |
5422 | |
5423 Type *Argument::isLazyArray() | |
5424 { | |
5425 // if (inout == Lazy) | |
5426 { | |
5427 Type *tb = type->toBasetype(); | |
5428 if (tb->ty == Tsarray || tb->ty == Tarray) | |
5429 { | |
5430 Type *tel = tb->next->toBasetype(); | |
5431 if (tel->ty == Tdelegate) | |
5432 { | |
5433 TypeDelegate *td = (TypeDelegate *)tel; | |
5434 TypeFunction *tf = (TypeFunction *)td->next; | |
5435 | |
5436 if (!tf->varargs && Argument::dim(tf->parameters) == 0) | |
5437 { | |
5438 return tf->next; // return type of delegate | |
5439 } | |
5440 } | |
5441 } | |
5442 } | |
5443 return NULL; | |
5444 } | |
5445 | |
5446 void Argument::toDecoBuffer(OutBuffer *buf) | |
5447 { | |
5448 switch (storageClass & (STCin | STCout | STCref | STClazy)) | |
5449 { case 0: | |
5450 case STCin: | |
5451 break; | |
5452 case STCout: | |
5453 buf->writeByte('J'); | |
5454 break; | |
5455 case STCref: | |
5456 buf->writeByte('K'); | |
5457 break; | |
5458 case STClazy: | |
5459 buf->writeByte('L'); | |
5460 break; | |
5461 default: | |
5462 #ifdef DEBUG | |
5463 halt(); | |
5464 #endif | |
5465 assert(0); | |
5466 } | |
5467 type->toDecoBuffer(buf); | |
5468 } | |
5469 | |
5470 /*************************************** | |
5471 * Determine number of arguments, folding in tuples. | |
5472 */ | |
5473 | |
5474 size_t Argument::dim(Arguments *args) | |
5475 { | |
5476 size_t n = 0; | |
5477 if (args) | |
5478 { | |
5479 for (size_t i = 0; i < args->dim; i++) | |
5480 { Argument *arg = (Argument *)args->data[i]; | |
5481 Type *t = arg->type->toBasetype(); | |
5482 | |
5483 if (t->ty == Ttuple) | |
5484 { TypeTuple *tu = (TypeTuple *)t; | |
5485 n += dim(tu->arguments); | |
5486 } | |
5487 else | |
5488 n++; | |
5489 } | |
5490 } | |
5491 return n; | |
5492 } | |
5493 | |
5494 /*************************************** | |
5495 * Get nth Argument, folding in tuples. | |
5496 * Returns: | |
5497 * Argument* nth Argument | |
5498 * NULL not found, *pn gets incremented by the number | |
5499 * of Arguments | |
5500 */ | |
5501 | |
5502 Argument *Argument::getNth(Arguments *args, size_t nth, size_t *pn) | |
5503 { | |
5504 if (!args) | |
5505 return NULL; | |
5506 | |
5507 size_t n = 0; | |
5508 for (size_t i = 0; i < args->dim; i++) | |
5509 { Argument *arg = (Argument *)args->data[i]; | |
5510 Type *t = arg->type->toBasetype(); | |
5511 | |
5512 if (t->ty == Ttuple) | |
5513 { TypeTuple *tu = (TypeTuple *)t; | |
5514 arg = getNth(tu->arguments, nth - n, &n); | |
5515 if (arg) | |
5516 return arg; | |
5517 } | |
5518 else if (n == nth) | |
5519 return arg; | |
5520 else | |
5521 n++; | |
5522 } | |
5523 | |
5524 if (pn) | |
5525 *pn += n; | |
5526 return NULL; | |
5527 } |