The expression "x in dict" is now a maybe type
[delight/core.git] / dmd / toir.c
blob66fe5913d3afefc01a99549cf2614b81dbc0c0b9
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.
11 /* Code to help convert to the intermediate representation
12 * of the compiler back end.
15 #include <stdio.h>
16 #include <string.h>
17 #include <time.h>
18 #include <complex.h>
20 #include "lexer.h"
21 #include "expression.h"
22 #include "mtype.h"
23 #include "dsymbol.h"
24 #include "declaration.h"
25 #include "enum.h"
26 #include "aggregate.h"
27 #include "attrib.h"
28 #include "module.h"
29 #include "init.h"
30 #include "template.h"
32 #if _WIN32
33 #include "..\tk\mem.h" // for mem_malloc
34 #elif linux
35 #include "../tk/mem.h" // for mem_malloc
36 #endif
38 #include "cc.h"
39 #include "el.h"
40 #include "oper.h"
41 #include "global.h"
42 #include "code.h"
43 #include "type.h"
44 #include "dt.h"
45 #include "irstate.h"
46 #include "id.h"
47 #include "type.h"
48 #include "toir.h"
50 static char __file__[] = __FILE__; /* for tassert.h */
51 #include "tassert.h"
53 /*********************************************
54 * Produce elem which increments the usage count for a particular line.
55 * Used to implement -cov switch (coverage analysis).
58 elem *incUsageElem(IRState *irs, Loc loc)
60 unsigned linnum = loc.linnum;
62 if (!irs->blx->module->cov || !linnum ||
63 loc.filename != irs->blx->module->srcfile->toChars())
64 return NULL;
66 //printf("cov = %p, covb = %p, linnum = %u\n", irs->blx->module->cov, irs->blx->module->covb, p, linnum);
68 linnum--; // from 1-based to 0-based
70 /* Set bit in covb[] indicating this is a valid code line number
72 unsigned *p = irs->blx->module->covb;
73 if (p) // covb can be NULL if it has already been written out to its .obj file
75 p += linnum / (sizeof(*p) * 8);
76 *p |= 1 << (linnum & (sizeof(*p) * 8 - 1));
79 elem *e;
80 e = el_ptr(irs->blx->module->cov);
81 e = el_bin(OPadd, TYnptr, e, el_long(TYuint, linnum * 4));
82 e = el_una(OPind, TYuint, e);
83 e = el_bin(OPaddass, TYuint, e, el_long(TYuint, 1));
84 return e;
87 /******************************************
88 * Return elem that evaluates to the static frame pointer for function fd.
89 * If fd is a member function, the returned expression will compute the value
90 * of fd's 'this' variable.
91 * This routine is critical for implementing nested functions.
94 elem *getEthis(Loc loc, IRState *irs, Dsymbol *fd)
96 elem *ethis;
97 FuncDeclaration *thisfd = irs->getFunc();
98 Dsymbol *fdparent = fd->toParent2();
100 //printf("getEthis(thisfd = '%s', fd = '%s', fdparent = '%s')\n", thisfd->toChars(), fd->toChars(), fdparent->toChars());
101 if (fdparent == thisfd)
102 { /* Going down one nesting level, i.e. we're calling
103 * a nested function from its enclosing function.
105 #if V2
106 if (irs->sclosure)
107 ethis = el_var(irs->sclosure);
108 else
109 #endif
110 if (irs->sthis)
111 { // We have a 'this' pointer for the current function
112 ethis = el_var(irs->sthis);
114 /* If no variables in the current function's frame are
115 * referenced by nested functions, then we can 'skip'
116 * adding this frame into the linked list of stack
117 * frames.
119 #if V2
120 if (thisfd->closureVars.dim)
121 #else
122 if (thisfd->nestedFrameRef)
123 #endif
124 { /* Local variables are referenced, can't skip.
125 * Address of 'this' gives the 'this' for the nested
126 * function
128 ethis = el_una(OPaddr, TYnptr, ethis);
131 else
132 { /* No 'this' pointer for current function,
133 * use NULL if no references to the current function's frame
135 ethis = el_long(TYnptr, 0);
136 #if V2
137 if (thisfd->closureVars.dim)
138 #else
139 if (thisfd->nestedFrameRef)
140 #endif
141 { /* OPframeptr is an operator that gets the frame pointer
142 * for the current function, i.e. for the x86 it gets
143 * the value of EBP
145 ethis->Eoper = OPframeptr;
149 else
151 if (!irs->sthis) // if no frame pointer for this function
153 fd->error(loc, "is a nested function and cannot be accessed from %s", irs->getFunc()->toChars());
154 ethis = el_long(TYnptr, 0); // error recovery
156 else
158 ethis = el_var(irs->sthis);
159 Dsymbol *s = thisfd;
160 while (fd != s)
161 { /* Go up a nesting level, i.e. we need to find the 'this'
162 * of an enclosing function.
163 * Our 'enclosing function' may also be an inner class.
166 //printf("\ts = '%s'\n", s->toChars());
167 thisfd = s->isFuncDeclaration();
168 if (thisfd)
169 { /* Enclosing function is a function.
171 if (fdparent == s->toParent2())
172 break;
173 if (thisfd->isNested())
175 FuncDeclaration *p = s->toParent2()->isFuncDeclaration();
176 #if V2
177 if (!p || p->closureVars.dim)
178 #else
179 if (!p || p->nestedFrameRef)
180 #endif
181 ethis = el_una(OPind, TYnptr, ethis);
183 else if (thisfd->vthis)
186 else
187 assert(0);
189 else
190 { /* Enclosed by a class. That means the current
191 * function must be a member function of that class.
193 ClassDeclaration *cd = s->isClassDeclaration();
194 if (!cd)
195 goto Lnoframe;
196 if (//cd->baseClass == fd ||
197 fd->isClassDeclaration() &&
198 fd->isClassDeclaration()->isBaseOf(cd, NULL))
199 break;
200 if (!cd->isNested() || !cd->vthis)
202 Lnoframe:
203 irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars());
204 return el_long(TYnptr, 0); // error recovery
206 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, cd->vthis->offset));
207 ethis = el_una(OPind, TYnptr, ethis);
208 if (fdparent == s->toParent2())
209 break;
210 if (fd == s->toParent2())
212 /* Remember that frames for functions that have no
213 * nested references are skipped in the linked list
214 * of frames.
216 #if V2
217 if (s->toParent2()->isFuncDeclaration()->closureVars.dim)
218 #else
219 if (s->toParent2()->isFuncDeclaration()->nestedFrameRef)
220 #endif
221 ethis = el_una(OPind, TYnptr, ethis);
222 break;
224 if (s->toParent2()->isFuncDeclaration())
226 /* Remember that frames for functions that have no
227 * nested references are skipped in the linked list
228 * of frames.
230 #if V2
231 if (s->toParent2()->isFuncDeclaration()->closureVars.dim)
232 #else
233 if (s->toParent2()->isFuncDeclaration()->nestedFrameRef)
234 #endif
235 ethis = el_una(OPind, TYnptr, ethis);
238 s = s->toParent2();
239 assert(s);
243 #if 0
244 printf("ethis:\n");
245 elem_print(ethis);
246 printf("\n");
247 #endif
248 return ethis;
252 /*******************************************
253 * Convert intrinsic function to operator.
254 * Returns that operator, -1 if not an intrinsic function.
257 int intrinsic_op(char *name)
259 static const char *namearray[] =
261 "4math3cosFeZe",
262 "4math3sinFeZe",
263 "4math4fabsFeZe",
264 "4math4rintFeZe",
265 "4math4sqrtFdZd",
266 "4math4sqrtFeZe",
267 "4math4sqrtFfZf",
268 "4math5ldexpFeiZe",
269 "4math6rndtolFeZl",
271 "9intrinsic2btFPkkZi",
272 "9intrinsic3bsfFkZi",
273 "9intrinsic3bsrFkZi",
274 "9intrinsic3btcFPkkZi",
275 "9intrinsic3btrFPkkZi",
276 "9intrinsic3btsFPkkZi",
277 "9intrinsic3inpFkZh",
278 "9intrinsic4inplFkZk",
279 "9intrinsic4inpwFkZt",
280 "9intrinsic4outpFkhZh",
281 "9intrinsic5bswapFkZk",
282 "9intrinsic5outplFkkZk",
283 "9intrinsic5outpwFktZt",
285 static unsigned char ioptab[] =
287 OPcos,
288 OPsin,
289 OPabs,
290 OPrint,
291 OPsqrt,
292 OPsqrt,
293 OPsqrt,
294 OPscale,
295 OPrndtol,
297 OPbt,
298 OPbsf,
299 OPbsr,
300 OPbtc,
301 OPbtr,
302 OPbts,
303 OPinp,
304 OPinp,
305 OPinp,
306 OPoutp,
307 OPbswap,
308 OPoutp,
309 OPoutp,
312 int i;
313 size_t length;
315 #ifdef DEBUG
316 assert(sizeof(namearray) / sizeof(char *) == sizeof(ioptab));
317 for (i = 0; i < sizeof(namearray) / sizeof(char *) - 1; i++)
319 if (strcmp(namearray[i], namearray[i + 1]) >= 0)
321 printf("namearray[%d] = '%s'\n", i, namearray[i]);
322 assert(0);
325 #endif
327 length = strlen(name);
328 if (length < 11 || memcmp(name, "_D3std", 6) != 0)
329 return -1;
331 i = binary(name + 6, namearray, sizeof(namearray) / sizeof(char *));
332 return (i == -1) ? i : ioptab[i];
336 /**************************************
337 * Given an expression e that is an array,
338 * determine and set the 'length' variable.
339 * Input:
340 * lengthVar Symbol of 'length' variable
341 * &e expression that is the array
342 * t1 Type of the array
343 * Output:
344 * e is rewritten to avoid side effects
345 * Returns:
346 * expression that initializes 'length'
349 elem *resolveLengthVar(VarDeclaration *lengthVar, elem **pe, Type *t1)
351 //printf("resolveLengthVar()\n");
352 elem *einit = NULL;
354 if (lengthVar && !(lengthVar->storage_class & STCconst))
355 { elem *elength;
356 Symbol *slength;
358 if (t1->ty == Tsarray)
359 { TypeSArray *tsa = (TypeSArray *)t1;
360 integer_t length = tsa->dim->toInteger();
362 elength = el_long(TYuint, length);
363 goto L3;
365 else if (t1->ty == Tarray)
367 elength = *pe;
368 *pe = el_same(&elength);
369 elength = el_una(OP64_32, TYuint, elength);
372 slength = lengthVar->toSymbol();
373 //symbol_add(slength);
375 einit = el_bin(OPeq, TYuint, el_var(slength), elength);
378 return einit;
381 /*************************************
382 * Closures are implemented by taking the local variables that
383 * need to survive the scope of the function, and copying them
384 * into a gc allocated chuck of memory. That chunk, called the
385 * closure here, is inserted into the linked list of stack
386 * frames instead of the usual stack frame.
388 * buildClosure() inserts code just after the function prolog
389 * is complete. It allocates memory for the closure, allocates
390 * a local variable (sclosure) to point to it, inserts into it
391 * the link to the enclosing frame, and copies into it the parameters
392 * that are referred to in nested functions.
393 * In VarExp::toElem and SymOffExp::toElem, when referring to a
394 * variable that is in a closure, takes the offset from sclosure rather
395 * than from the frame pointer.
397 * getEthis() and NewExp::toElem need to use sclosure, if set, rather
398 * than the current frame pointer.
401 #if V2
403 void FuncDeclaration::buildClosure(IRState *irs)
405 if (needsClosure())
406 { // Generate closure on the heap
407 // BUG: doesn't capture variadic arguments passed to this function
409 Symbol *sclosure;
410 sclosure = symbol_name("__closptr",SCauto,Type::tvoidptr->toCtype());
411 sclosure->Sflags |= SFLtrue | SFLfree;
412 symbol_add(sclosure);
413 irs->sclosure = sclosure;
415 unsigned offset = PTRSIZE; // leave room for previous sthis
416 for (int i = 0; i < closureVars.dim; i++)
417 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
418 assert(v->isVarDeclaration());
420 /* Align and allocate space for v in the closure
421 * just like AggregateDeclaration::addField() does.
423 unsigned memsize = v->type->size();
424 unsigned memalignsize = v->type->alignsize();
425 unsigned xalign = v->type->memalign(global.structalign);
426 AggregateDeclaration::alignmember(xalign, memalignsize, &offset);
427 v->offset = offset;
428 offset += memsize;
430 /* Can't do nrvo if the variable is put in a closure, since
431 * what the shidden points to may no longer exist.
433 if (nrvo_can && nrvo_var == v)
435 nrvo_can = 0;
438 // offset is now the size of the closure
440 // Allocate memory for the closure
441 elem *e;
442 e = el_long(TYint, offset);
443 e = el_bin(OPcall, TYnptr, el_var(rtlsym[RTLSYM_ALLOCMEMORY]), e);
445 // Assign block of memory to sclosure
446 // sclosure = allocmemory(sz);
447 e = el_bin(OPeq, TYvoid, el_var(sclosure), e);
449 // Set the first element to sthis
450 // *(sclosure + 0) = sthis;
451 elem *ethis;
452 if (irs->sthis)
453 ethis = el_var(irs->sthis);
454 else
455 ethis = el_long(TYnptr, 0);
456 elem *ex = el_una(OPind, TYnptr, el_var(sclosure));
457 ex = el_bin(OPeq, TYnptr, ex, ethis);
458 e = el_combine(e, ex);
460 // Copy function parameters into closure
461 for (int i = 0; i < closureVars.dim; i++)
462 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
464 if (!v->isParameter())
465 continue;
466 tym_t tym = v->type->totym();
467 if (v->type->toBasetype()->ty == Tsarray || v->isOut() || v->isRef())
468 tym = TYnptr; // reference parameters are just pointers
469 ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYint, v->offset));
470 ex = el_una(OPind, tym, ex);
471 if (ex->Ety == TYstruct)
472 { ex->Enumbytes = v->type->size();
473 ex = el_bin(OPstreq, tym, ex, el_var(v->toSymbol()));
474 ex->Enumbytes = v->type->size();
476 else
477 ex = el_bin(OPeq, tym, ex, el_var(v->toSymbol()));
479 e = el_combine(e, ex);
482 block_appendexp(irs->blx->curblock, e);
486 #endif