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