Merge dmd upstream 6243fa6d2
[official-gcc.git] / gcc / d / dmd / ctfeexpr.c
blob430342dae54bee3b40904310c5104ede1bdc6559
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/ctfeexpr.c
9 */
11 #include "root/dsystem.h" // mem{cpy|set}()
12 #include "root/rmem.h"
14 #include "mars.h"
15 #include "expression.h"
16 #include "declaration.h"
17 #include "aggregate.h"
18 // for AssocArray
19 #include "id.h"
20 #include "utf.h"
21 #include "template.h"
22 #include "ctfe.h"
24 int RealEquals(real_t x1, real_t x2);
26 /************** ClassReferenceExp ********************************************/
28 ClassReferenceExp::ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type)
29 : Expression(loc, TOKclassreference, sizeof(ClassReferenceExp))
31 assert(lit && lit->sd && lit->sd->isClassDeclaration());
32 this->value = lit;
33 this->type = type;
36 ClassDeclaration *ClassReferenceExp::originalClass()
38 return value->sd->isClassDeclaration();
41 // Return index of the field, or -1 if not found
42 int ClassReferenceExp::getFieldIndex(Type *fieldtype, unsigned fieldoffset)
44 ClassDeclaration *cd = originalClass();
45 unsigned fieldsSoFar = 0;
46 for (size_t j = 0; j < value->elements->dim; j++)
48 while (j - fieldsSoFar >= cd->fields.dim)
50 fieldsSoFar += cd->fields.dim;
51 cd = cd->baseClass;
53 VarDeclaration *v2 = cd->fields[j - fieldsSoFar];
54 if (fieldoffset == v2->offset &&
55 fieldtype->size() == v2->type->size())
57 return (int)(value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar));
60 return -1;
63 // Return index of the field, or -1 if not found
64 // Same as getFieldIndex, but checks for a direct match with the VarDeclaration
65 int ClassReferenceExp::findFieldIndexByName(VarDeclaration *v)
67 ClassDeclaration *cd = originalClass();
68 size_t fieldsSoFar = 0;
69 for (size_t j = 0; j < value->elements->dim; j++)
71 while (j - fieldsSoFar >= cd->fields.dim)
73 fieldsSoFar += cd->fields.dim;
74 cd = cd->baseClass;
76 VarDeclaration *v2 = cd->fields[j - fieldsSoFar];
77 if (v == v2)
79 return (int)(value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar));
82 return -1;
85 /************** VoidInitExp ********************************************/
87 VoidInitExp::VoidInitExp(VarDeclaration *var, Type *)
88 : Expression(var->loc, TOKvoid, sizeof(VoidInitExp))
90 this->var = var;
91 this->type = var->type;
94 const char *VoidInitExp::toChars()
96 return "void";
99 // Return index of the field, or -1 if not found
100 // Same as getFieldIndex, but checks for a direct match with the VarDeclaration
101 int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
103 for (size_t i = 0; i < sd->fields.dim; ++i)
105 if (sd->fields[i] == v)
106 return (int)i;
108 return -1;
111 /************** ThrownExceptionExp ********************************************/
113 ThrownExceptionExp::ThrownExceptionExp(Loc loc, ClassReferenceExp *victim) : Expression(loc, TOKthrownexception, sizeof(ThrownExceptionExp))
115 this->thrown = victim;
116 this->type = victim->type;
119 const char *ThrownExceptionExp::toChars()
121 return "CTFE ThrownException";
124 // Generate an error message when this exception is not caught
125 void ThrownExceptionExp::generateUncaughtError()
127 UnionExp ue;
128 Expression *e = resolveSlice((*thrown->value->elements)[0], &ue);
129 StringExp *se = e->toStringExp();
130 thrown->error("uncaught CTFE exception %s(%s)", thrown->type->toChars(), se ? se->toChars() : e->toChars());
132 /* Also give the line where the throw statement was. We won't have it
133 * in the case where the ThrowStatement is generated internally
134 * (eg, in ScopeStatement)
136 if (loc.filename && !loc.equals(thrown->loc))
137 errorSupplemental(loc, "thrown from here");
140 // True if 'e' is CTFEExp::cantexp, or an exception
141 bool exceptionOrCantInterpret(Expression *e)
143 return e && (e->op == TOKcantexp || e->op == TOKthrownexception);
146 /********************** CTFEExp ******************************************/
148 CTFEExp *CTFEExp::cantexp;
149 CTFEExp *CTFEExp::voidexp;
150 CTFEExp *CTFEExp::breakexp;
151 CTFEExp *CTFEExp::continueexp;
152 CTFEExp *CTFEExp::gotoexp;
154 CTFEExp::CTFEExp(TOK tok)
155 : Expression(Loc(), tok, sizeof(CTFEExp))
157 type = Type::tvoid;
160 const char *CTFEExp::toChars()
162 switch (op)
164 case TOKcantexp: return "<cant>";
165 case TOKvoidexp: return "<void>";
166 case TOKbreak: return "<break>";
167 case TOKcontinue: return "<continue>";
168 case TOKgoto: return "<goto>";
169 default: assert(0); return NULL;
173 Expression *UnionExp::copy()
175 Expression *e = exp();
176 //if (e->size > sizeof(u)) printf("%s\n", Token::toChars(e->op));
177 assert(e->size <= sizeof(u));
178 if (e->op == TOKcantexp) return CTFEExp::cantexp;
179 if (e->op == TOKvoidexp) return CTFEExp::voidexp;
180 if (e->op == TOKbreak) return CTFEExp::breakexp;
181 if (e->op == TOKcontinue) return CTFEExp::continueexp;
182 if (e->op == TOKgoto) return CTFEExp::gotoexp;
183 return e->copy();
186 /************** Aggregate literals (AA/string/array/struct) ******************/
188 // Given expr, which evaluates to an array/AA/string literal,
189 // return true if it needs to be copied
190 bool needToCopyLiteral(Expression *expr)
192 for (;;)
194 switch (expr->op)
196 case TOKarrayliteral:
197 return ((ArrayLiteralExp *)expr)->ownedByCtfe == OWNEDcode;
198 case TOKassocarrayliteral:
199 return ((AssocArrayLiteralExp *)expr)->ownedByCtfe == OWNEDcode;
200 case TOKstructliteral:
201 return ((StructLiteralExp *)expr)->ownedByCtfe == OWNEDcode;
202 case TOKstring:
203 case TOKthis:
204 case TOKvar:
205 return false;
206 case TOKassign:
207 return false;
208 case TOKindex:
209 case TOKdotvar:
210 case TOKslice:
211 case TOKcast:
212 expr = ((UnaExp *)expr)->e1;
213 continue;
214 case TOKcat:
215 return needToCopyLiteral(((BinExp *)expr)->e1) ||
216 needToCopyLiteral(((BinExp *)expr)->e2);
217 case TOKcatass:
218 expr = ((BinExp *)expr)->e2;
219 continue;
220 default:
221 return false;
226 Expressions *copyLiteralArray(Expressions *oldelems, Expression *basis = NULL)
228 if (!oldelems)
229 return oldelems;
230 CtfeStatus::numArrayAllocs++;
231 Expressions *newelems = new Expressions();
232 newelems->setDim(oldelems->dim);
233 for (size_t i = 0; i < oldelems->dim; i++)
235 Expression *el = (*oldelems)[i];
236 if (!el)
237 el = basis;
238 (*newelems)[i] = copyLiteral(el).copy();
240 return newelems;
243 // Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral.
244 // This value will be used for in-place modification.
245 UnionExp copyLiteral(Expression *e)
247 UnionExp ue;
248 if (e->op == TOKstring) // syntaxCopy doesn't make a copy for StringExp!
250 StringExp *se = (StringExp *)e;
251 utf8_t *s = (utf8_t *)mem.xcalloc(se->len + 1, se->sz);
252 memcpy(s, se->string, se->len * se->sz);
253 new(&ue) StringExp(se->loc, s, se->len);
254 StringExp *se2 = (StringExp *)ue.exp();
255 se2->committed = se->committed;
256 se2->postfix = se->postfix;
257 se2->type = se->type;
258 se2->sz = se->sz;
259 se2->ownedByCtfe = OWNEDctfe;
260 return ue;
262 if (e->op == TOKarrayliteral)
264 ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
265 Expressions *elements = copyLiteralArray(ale->elements, ale->basis);
267 new(&ue) ArrayLiteralExp(e->loc, elements);
269 ArrayLiteralExp *r = (ArrayLiteralExp *)ue.exp();
270 r->type = e->type;
271 r->ownedByCtfe = OWNEDctfe;
272 return ue;
274 if (e->op == TOKassocarrayliteral)
276 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
277 new(&ue) AssocArrayLiteralExp(e->loc, copyLiteralArray(aae->keys), copyLiteralArray(aae->values));
278 AssocArrayLiteralExp *r = (AssocArrayLiteralExp *)ue.exp();
279 r->type = e->type;
280 r->ownedByCtfe = OWNEDctfe;
281 return ue;
283 if (e->op == TOKstructliteral)
285 /* syntaxCopy doesn't work for struct literals, because of a nasty special
286 * case: block assignment is permitted inside struct literals, eg,
287 * an int[4] array can be initialized with a single int.
289 StructLiteralExp *sle = (StructLiteralExp *)e;
290 Expressions *oldelems = sle->elements;
291 Expressions * newelems = new Expressions();
292 newelems->setDim(oldelems->dim);
293 for (size_t i = 0; i < newelems->dim; i++)
295 // We need the struct definition to detect block assignment
296 VarDeclaration *v = sle->sd->fields[i];
297 Expression *m = (*oldelems)[i];
299 // If it is a void assignment, use the default initializer
300 if (!m)
301 m = voidInitLiteral(v->type, v).copy();
303 if (v->type->ty == Tarray || v->type->ty == Taarray)
305 // Don't have to copy array references
307 else
309 // Buzilla 15681: Copy the source element always.
310 m = copyLiteral(m).copy();
312 // Block assignment from inside struct literals
313 if (v->type->ty != m->type->ty && v->type->ty == Tsarray)
315 TypeSArray *tsa = (TypeSArray *)v->type;
316 size_t len = (size_t)tsa->dim->toInteger();
317 m = createBlockDuplicatedArrayLiteral(e->loc, v->type, m, len);
320 (*newelems)[i] = m;
322 new(&ue) StructLiteralExp(e->loc, sle->sd, newelems, sle->stype);
323 StructLiteralExp *r = (StructLiteralExp *)ue.exp();
324 r->type = e->type;
325 r->ownedByCtfe = OWNEDctfe;
326 r->origin = ((StructLiteralExp *)e)->origin;
327 return ue;
329 if (e->op == TOKfunction || e->op == TOKdelegate ||
330 e->op == TOKsymoff || e->op == TOKnull ||
331 e->op == TOKvar || e->op == TOKdotvar ||
332 e->op == TOKint64 || e->op == TOKfloat64 ||
333 e->op == TOKchar || e->op == TOKcomplex80 ||
334 e->op == TOKvoid || e->op == TOKvector ||
335 e->op == TOKtypeid)
337 // Simple value types
338 // Keep e1 for DelegateExp and DotVarExp
339 new(&ue) UnionExp(e);
340 Expression *r = ue.exp();
341 r->type = e->type;
342 return ue;
344 if (e->op == TOKslice)
346 SliceExp *se = (SliceExp *)e;
347 if (se->type->toBasetype()->ty == Tsarray)
349 // same with resolveSlice()
350 if (se->e1->op == TOKnull)
352 new(&ue) NullExp(se->loc, se->type);
353 return ue;
355 ue = Slice(se->type, se->e1, se->lwr, se->upr);
356 assert(ue.exp()->op == TOKarrayliteral);
357 ArrayLiteralExp *r = (ArrayLiteralExp *)ue.exp();
358 r->elements = copyLiteralArray(r->elements);
359 r->ownedByCtfe = OWNEDctfe;
360 return ue;
362 else
364 // Array slices only do a shallow copy
365 new(&ue) SliceExp(e->loc, se->e1, se->lwr, se->upr);
366 Expression *r = ue.exp();
367 r->type = e->type;
368 return ue;
371 if (isPointer(e->type))
373 // For pointers, we only do a shallow copy.
374 if (e->op == TOKaddress)
375 new(&ue) AddrExp(e->loc, ((AddrExp *)e)->e1);
376 else if (e->op == TOKindex)
377 new(&ue) IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2);
378 else if (e->op == TOKdotvar)
380 new(&ue) DotVarExp(e->loc, ((DotVarExp *)e)->e1,
381 ((DotVarExp *)e)->var, ((DotVarExp *)e)->hasOverloads);
383 else
384 assert(0);
385 Expression *r = ue.exp();
386 r->type = e->type;
387 return ue;
389 if (e->op == TOKclassreference)
391 new(&ue) ClassReferenceExp(e->loc, ((ClassReferenceExp *)e)->value, e->type);
392 return ue;
394 if (e->op == TOKerror)
396 new(&ue) UnionExp(e);
397 return ue;
399 e->error("CTFE internal error: literal %s", e->toChars());
400 assert(0);
401 return ue;
404 /* Deal with type painting.
405 * Type painting is a major nuisance: we can't just set
406 * e->type = type, because that would change the original literal.
407 * But, we can't simply copy the literal either, because that would change
408 * the values of any pointers.
410 Expression *paintTypeOntoLiteral(Type *type, Expression *lit)
412 if (lit->type->equals(type))
413 return lit;
414 return paintTypeOntoLiteralCopy(type, lit).copy();
417 UnionExp paintTypeOntoLiteralCopy(Type *type, Expression *lit)
419 UnionExp ue;
421 if (lit->type->equals(type))
423 new(&ue) UnionExp(lit);
424 return ue;
427 // If it is a cast to inout, retain the original type of the referenced part.
428 if (type->hasWild() && type->hasPointers())
430 new(&ue) UnionExp(lit);
431 ue.exp()->type = type;
432 return ue;
435 if (lit->op == TOKslice)
437 SliceExp *se = (SliceExp *)lit;
438 new(&ue) SliceExp(lit->loc, se->e1, se->lwr, se->upr);
440 else if (lit->op == TOKindex)
442 IndexExp *ie = (IndexExp *)lit;
443 new(&ue) IndexExp(lit->loc, ie->e1, ie->e2);
445 else if (lit->op == TOKarrayliteral)
447 new(&ue) SliceExp(lit->loc, lit,
448 new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit).copy());
450 else if (lit->op == TOKstring)
452 // For strings, we need to introduce another level of indirection
453 new(&ue) SliceExp(lit->loc, lit,
454 new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit).copy());
456 else if (lit->op == TOKassocarrayliteral)
458 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)lit;
459 // TODO: we should be creating a reference to this AAExp, not
460 // just a ref to the keys and values.
461 OwnedBy wasOwned = aae->ownedByCtfe;
462 new(&ue) AssocArrayLiteralExp(lit->loc, aae->keys, aae->values);
463 aae = (AssocArrayLiteralExp *)ue.exp();
464 aae->ownedByCtfe = wasOwned;
466 else
468 // Can't type paint from struct to struct*; this needs another
469 // level of indirection
470 if (lit->op == TOKstructliteral && isPointer(type))
471 lit->error("CTFE internal error: painting %s", type->toChars());
472 ue = copyLiteral(lit);
474 ue.exp()->type = type;
475 return ue;
478 /*************************************
479 * If e is a SliceExp, constant fold it.
480 * Params:
481 * e = expression to resolve
482 * pue = if not null, store resulting expression here
483 * Returns:
484 * resulting expression
486 Expression *resolveSlice(Expression *e, UnionExp *pue)
488 if (e->op != TOKslice)
489 return e;
490 SliceExp *se = (SliceExp *)e;
491 if (se->e1->op == TOKnull)
492 return se->e1;
493 if (pue)
495 *pue = Slice(e->type, se->e1, se->lwr, se->upr);
496 return pue->exp();
498 else
499 return Slice(e->type, se->e1, se->lwr, se->upr).copy();
502 /* Determine the array length, without interpreting it.
503 * e must be an array literal, or a slice
504 * It's very wasteful to resolve the slice when we only
505 * need the length.
507 uinteger_t resolveArrayLength(Expression *e)
509 if (e->op == TOKvector)
510 e = ((VectorExp *)e)->e1;
512 if (e->op == TOKnull)
513 return 0;
514 if (e->op == TOKslice)
516 uinteger_t ilo = ((SliceExp *)e)->lwr->toInteger();
517 uinteger_t iup = ((SliceExp *)e)->upr->toInteger();
518 return iup - ilo;
520 if (e->op == TOKstring)
522 return ((StringExp *)e)->len;
524 if (e->op == TOKarrayliteral)
526 ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
527 return ale->elements ? ale->elements->dim : 0;
529 if (e->op == TOKassocarrayliteral)
531 AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e;
532 return ale->keys->dim;
534 assert(0);
535 return 0;
538 /******************************
539 * Helper for NewExp
540 * Create an array literal consisting of 'elem' duplicated 'dim' times.
541 * Params:
542 * loc = source location where the interpretation occurs
543 * type = target type of the result
544 * elem = the source of array element, it will be owned by the result
545 * dim = element number of the result
546 * Returns:
547 * Constructed ArrayLiteralExp
549 ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
550 Expression *elem, size_t dim)
552 if (type->ty == Tsarray && type->nextOf()->ty == Tsarray && elem->type->ty != Tsarray)
554 // If it is a multidimensional array literal, do it recursively
555 TypeSArray *tsa = (TypeSArray *)type->nextOf();
556 size_t len = (size_t)tsa->dim->toInteger();
557 elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem, len);
560 // Buzilla 15681
561 Type *tb = elem->type->toBasetype();
562 const bool mustCopy = tb->ty == Tstruct || tb->ty == Tsarray;
564 Expressions *elements = new Expressions();
565 elements->setDim(dim);
566 for (size_t i = 0; i < dim; i++)
568 (*elements)[i] = mustCopy ? copyLiteral(elem).copy() : elem;
570 ArrayLiteralExp *ale = new ArrayLiteralExp(loc, elements);
571 ale->type = type;
572 ale->ownedByCtfe = OWNEDctfe;
573 return ale;
576 /******************************
577 * Helper for NewExp
578 * Create a string literal consisting of 'value' duplicated 'dim' times.
580 StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
581 unsigned value, size_t dim, unsigned char sz)
583 utf8_t *s = (utf8_t *)mem.xcalloc(dim + 1, sz);
584 for (size_t elemi = 0; elemi < dim; ++elemi)
586 switch (sz)
588 case 1: s[elemi] = (utf8_t)value; break;
589 case 2: ((unsigned short *)s)[elemi] = (unsigned short)value; break;
590 case 4: ((unsigned *)s)[elemi] = value; break;
591 default: assert(0);
594 StringExp *se = new StringExp(loc, s, dim);
595 se->type = type;
596 se->sz = sz;
597 se->committed = true;
598 se->ownedByCtfe = OWNEDctfe;
599 return se;
602 // Return true if t is an AA
603 bool isAssocArray(Type *t)
605 t = t->toBasetype();
606 if (t->ty == Taarray)
607 return true;
608 return false;
611 // Given a template AA type, extract the corresponding built-in AA type
612 TypeAArray *toBuiltinAAType(Type *t)
614 t = t->toBasetype();
615 if (t->ty == Taarray)
616 return (TypeAArray *)t;
617 assert(0);
618 return NULL;
621 /************** TypeInfo operations ************************************/
623 // Return true if type is TypeInfo_Class
624 bool isTypeInfo_Class(Type *type)
626 return type->ty == Tclass &&
627 (Type::dtypeinfo == ((TypeClass *)type)->sym ||
628 Type::dtypeinfo->isBaseOf(((TypeClass *)type)->sym, NULL));
631 /************** Pointer operations ************************************/
633 // Return true if t is a pointer (not a function pointer)
634 bool isPointer(Type *t)
636 Type * tb = t->toBasetype();
637 return tb->ty == Tpointer && tb->nextOf()->ty != Tfunction;
640 // For CTFE only. Returns true if 'e' is true or a non-null pointer.
641 bool isTrueBool(Expression *e)
643 return e->isBool(true) ||
644 ((e->type->ty == Tpointer || e->type->ty == Tclass) && e->op != TOKnull);
647 /* Is it safe to convert from srcPointee* to destPointee* ?
648 * srcPointee is the genuine type (never void).
649 * destPointee may be void.
651 bool isSafePointerCast(Type *srcPointee, Type *destPointee)
653 // It's safe to cast S** to D** if it's OK to cast S* to D*
654 while (srcPointee->ty == Tpointer && destPointee->ty == Tpointer)
656 srcPointee = srcPointee->nextOf();
657 destPointee = destPointee->nextOf();
660 // It's OK if both are the same (modulo const)
661 if (srcPointee->constConv(destPointee))
662 return true;
664 // It's OK if function pointers differ only in safe/pure/nothrow
665 if (srcPointee->ty == Tfunction && destPointee->ty == Tfunction)
666 return srcPointee->covariant(destPointee) == 1;
668 // it's OK to cast to void*
669 if (destPointee->ty == Tvoid)
670 return true;
672 // It's OK to cast from V[K] to void*
673 if (srcPointee->ty == Taarray && destPointee == Type::tvoidptr)
674 return true;
676 // It's OK if they are the same size (static array of) integers, eg:
677 // int* --> uint*
678 // int[5][] --> uint[5][]
679 if (srcPointee->ty == Tsarray && destPointee->ty == Tsarray)
681 if (srcPointee->size() != destPointee->size())
682 return false;
683 srcPointee = srcPointee->baseElemOf();
684 destPointee = destPointee->baseElemOf();
686 return srcPointee->isintegral() &&
687 destPointee->isintegral() &&
688 srcPointee->size() == destPointee->size();
691 Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs)
693 *ofs = 0;
694 if (e->op == TOKaddress)
695 e = ((AddrExp *)e)->e1;
696 if (e->op == TOKsymoff)
697 *ofs = ((SymOffExp *)e)->offset;
698 if (e->op == TOKdotvar)
700 Expression *ex = ((DotVarExp *)e)->e1;
701 VarDeclaration *v = ((DotVarExp *)e)->var->isVarDeclaration();
702 assert(v);
703 StructLiteralExp *se = ex->op == TOKclassreference ? ((ClassReferenceExp *)ex)->value : (StructLiteralExp *)ex;
704 // We can't use getField, because it makes a copy
705 unsigned i;
706 if (ex->op == TOKclassreference)
707 i = ((ClassReferenceExp *)ex)->getFieldIndex(e->type, v->offset);
708 else
709 i = se->getFieldIndex(e->type, v->offset);
710 e = (*se->elements)[i];
712 if (e->op == TOKindex)
714 IndexExp *ie = (IndexExp *)e;
715 // Note that each AA element is part of its own memory block
716 if ((ie->e1->type->ty == Tarray ||
717 ie->e1->type->ty == Tsarray ||
718 ie->e1->op == TOKstring ||
719 ie->e1->op == TOKarrayliteral) &&
720 ie->e2->op == TOKint64)
722 *ofs = ie->e2->toInteger();
723 return ie->e1;
726 if (e->op == TOKslice && e->type->toBasetype()->ty == Tsarray)
728 SliceExp *se = (SliceExp *)e;
729 if ((se->e1->type->ty == Tarray ||
730 se->e1->type->ty == Tsarray ||
731 se->e1->op == TOKstring ||
732 se->e1->op == TOKarrayliteral) &&
733 se->lwr->op == TOKint64)
735 *ofs = se->lwr->toInteger();
736 return se->e1;
739 return e;
742 /** Return true if agg1 and agg2 are pointers to the same memory block
744 bool pointToSameMemoryBlock(Expression *agg1, Expression *agg2)
746 if (agg1 == agg2)
747 return true;
749 // For integers cast to pointers, we regard them as non-comparable
750 // unless they are identical. (This may be overly strict).
751 if (agg1->op == TOKint64 && agg2->op == TOKint64 &&
752 agg1->toInteger() == agg2->toInteger())
754 return true;
757 // Note that type painting can occur with VarExp, so we
758 // must compare the variables being pointed to.
759 if (agg1->op == TOKvar && agg2->op == TOKvar &&
760 ((VarExp *)agg1)->var == ((VarExp *)agg2)->var)
762 return true;
764 if (agg1->op == TOKsymoff && agg2->op == TOKsymoff &&
765 ((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var)
767 return true;
770 return false;
773 // return e1 - e2 as an integer, or error if not possible
774 UnionExp pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2)
776 UnionExp ue;
777 dinteger_t ofs1, ofs2;
778 Expression *agg1 = getAggregateFromPointer(e1, &ofs1);
779 Expression *agg2 = getAggregateFromPointer(e2, &ofs2);
780 if (agg1 == agg2)
782 Type *pointee = ((TypePointer *)agg1->type)->next;
783 dinteger_t sz = pointee->size();
784 new(&ue) IntegerExp(loc, (ofs1 - ofs2) * sz, type);
786 else if (agg1->op == TOKstring && agg2->op == TOKstring)
788 if (((StringExp *)agg1)->string == ((StringExp *)agg2)->string)
790 Type *pointee = ((TypePointer *)agg1->type)->next;
791 dinteger_t sz = pointee->size();
792 new(&ue) IntegerExp(loc, (ofs1 - ofs2) * sz, type);
795 else if (agg1->op == TOKsymoff && agg2->op == TOKsymoff &&
796 ((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var)
798 new(&ue) IntegerExp(loc, ofs1 - ofs2, type);
800 else
802 error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract "
803 "pointers to two different memory blocks",
804 e1->toChars(), e2->toChars());
805 new(&ue) CTFEExp(TOKcantexp);
807 return ue;
810 // Return eptr op e2, where eptr is a pointer, e2 is an integer,
811 // and op is TOKadd or TOKmin
812 UnionExp pointerArithmetic(Loc loc, TOK op, Type *type,
813 Expression *eptr, Expression *e2)
815 UnionExp ue;
817 if (eptr->type->nextOf()->ty == Tvoid)
819 error(loc, "cannot perform arithmetic on void* pointers at compile time");
820 Lcant:
821 new(&ue) CTFEExp(TOKcantexp);
822 return ue;
825 dinteger_t ofs1;
826 if (eptr->op == TOKaddress)
827 eptr = ((AddrExp *)eptr)->e1;
828 Expression *agg1 = getAggregateFromPointer(eptr, &ofs1);
829 if (agg1->op == TOKsymoff)
831 if (((SymOffExp *)agg1)->var->type->ty != Tsarray)
833 error(loc, "cannot perform pointer arithmetic on arrays of unknown length at compile time");
834 goto Lcant;
837 else if (agg1->op != TOKstring && agg1->op != TOKarrayliteral)
839 error(loc, "cannot perform pointer arithmetic on non-arrays at compile time");
840 goto Lcant;
842 dinteger_t ofs2 = e2->toInteger();
844 Type *pointee = ((TypeNext *)agg1->type->toBasetype())->next;
845 dinteger_t sz = pointee->size();
847 sinteger_t indx;
848 dinteger_t len;
849 if (agg1->op == TOKsymoff)
851 indx = ofs1 / sz;
852 len = ((TypeSArray *)((SymOffExp *)agg1)->var->type)->dim->toInteger();
854 else
856 Expression *dollar = ArrayLength(Type::tsize_t, agg1).copy();
857 assert(!CTFEExp::isCantExp(dollar));
858 indx = ofs1;
859 len = dollar->toInteger();
861 if (op == TOKadd || op == TOKaddass || op == TOKplusplus)
862 indx += ofs2 / sz;
863 else if (op == TOKmin || op == TOKminass || op == TOKminusminus)
864 indx -= ofs2 / sz;
865 else
867 error(loc, "CTFE internal error: bad pointer operation");
868 goto Lcant;
871 if (indx < 0 || len < (dinteger_t)indx)
873 error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", (ulonglong)indx, (ulonglong)len);
874 goto Lcant;
877 if (agg1->op == TOKsymoff)
879 new(&ue) SymOffExp(loc, ((SymOffExp *)agg1)->var, indx * sz);
880 SymOffExp *se = (SymOffExp *)ue.exp();
881 se->type = type;
882 return ue;
885 if (agg1->op != TOKarrayliteral && agg1->op != TOKstring)
887 error(loc, "CTFE internal error: pointer arithmetic %s", agg1->toChars());
888 goto Lcant;
891 if (eptr->type->toBasetype()->ty == Tsarray)
893 dinteger_t dim = ((TypeSArray *)eptr->type->toBasetype())->dim->toInteger();
895 // Create a CTFE pointer &agg1[indx .. indx+dim]
896 SliceExp *se = new SliceExp(loc, agg1,
897 new IntegerExp(loc, indx, Type::tsize_t),
898 new IntegerExp(loc, indx + dim, Type::tsize_t));
899 se->type = type->toBasetype()->nextOf();
900 new(&ue) AddrExp(loc, se);
901 ue.exp()->type = type;
902 return ue;
905 // Create a CTFE pointer &agg1[indx]
906 IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t);
907 Expression *ie = new IndexExp(loc, agg1, ofs);
908 ie->type = type->toBasetype()->nextOf(); // Bugzilla 13992
909 new(&ue) AddrExp(loc, ie);
910 ue.exp()->type = type;
911 return ue;
914 // Return 1 if true, 0 if false
915 // -1 if comparison is illegal because they point to non-comparable memory blocks
916 int comparePointers(TOK op, Expression *agg1, dinteger_t ofs1, Expression *agg2, dinteger_t ofs2)
918 if (pointToSameMemoryBlock(agg1, agg2))
920 int n;
921 switch (op)
923 case TOKlt: n = (ofs1 < ofs2); break;
924 case TOKle: n = (ofs1 <= ofs2); break;
925 case TOKgt: n = (ofs1 > ofs2); break;
926 case TOKge: n = (ofs1 >= ofs2); break;
927 case TOKidentity:
928 case TOKequal: n = (ofs1 == ofs2); break;
929 case TOKnotidentity:
930 case TOKnotequal: n = (ofs1 != ofs2); break;
931 default:
932 assert(0);
934 return n;
936 bool null1 = (agg1->op == TOKnull);
937 bool null2 = (agg2->op == TOKnull);
939 int cmp;
940 if (null1 || null2)
942 switch (op)
944 case TOKlt: cmp = null1 && !null2; break;
945 case TOKgt: cmp = !null1 && null2; break;
946 case TOKle: cmp = null1; break;
947 case TOKge: cmp = null2; break;
948 case TOKidentity:
949 case TOKequal:
950 case TOKnotidentity: // 'cmp' gets inverted below
951 case TOKnotequal:
952 cmp = (null1 == null2);
953 break;
954 default:
955 assert(0);
958 else
960 switch (op)
962 case TOKidentity:
963 case TOKequal:
964 case TOKnotidentity: // 'cmp' gets inverted below
965 case TOKnotequal:
966 cmp = 0;
967 break;
968 default:
969 return -1; // memory blocks are different
972 if (op == TOKnotidentity || op == TOKnotequal)
973 cmp ^= 1;
974 return cmp;
977 // True if conversion from type 'from' to 'to' involves a reinterpret_cast
978 // floating point -> integer or integer -> floating point
979 bool isFloatIntPaint(Type *to, Type *from)
981 return from->size() == to->size() &&
982 ((from->isintegral() && to->isfloating()) ||
983 (from->isfloating() && to->isintegral()));
986 // Reinterpret float/int value 'fromVal' as a float/integer of type 'to'.
987 Expression *paintFloatInt(Expression *fromVal, Type *to)
989 if (exceptionOrCantInterpret(fromVal))
990 return fromVal;
992 assert(to->size() == 4 || to->size() == 8);
993 return Compiler::paintAsType(fromVal, to);
996 /******** Constant folding, with support for CTFE ***************************/
998 /// Return true if non-pointer expression e can be compared
999 /// with >,is, ==, etc, using ctfeCmp, ctfeEqual, ctfeIdentity
1000 bool isCtfeComparable(Expression *e)
1002 if (e->op == TOKslice)
1003 e = ((SliceExp *)e)->e1;
1005 if (e->isConst() != 1)
1007 if (e->op == TOKnull ||
1008 e->op == TOKstring ||
1009 e->op == TOKfunction ||
1010 e->op == TOKdelegate ||
1011 e->op == TOKarrayliteral ||
1012 e->op == TOKstructliteral ||
1013 e->op == TOKassocarrayliteral ||
1014 e->op == TOKclassreference)
1016 return true;
1018 // Bugzilla 14123: TypeInfo object is comparable in CTFE
1019 if (e->op == TOKtypeid)
1020 return true;
1022 return false;
1024 return true;
1027 /// Map TOK comparison ops
1028 template <typename N>
1029 static bool numCmp(TOK op, N n1, N n2)
1031 switch (op)
1033 case TOKlt:
1034 return n1 < n2;
1035 case TOKle:
1036 return n1 <= n2;
1037 case TOKgt:
1038 return n1 > n2;
1039 case TOKge:
1040 return n1 >= n2;
1042 default:
1043 assert(0);
1047 /// Returns cmp OP 0; where OP is ==, !=, <, >=, etc. Result is 0 or 1
1048 int specificCmp(TOK op, int rawCmp)
1050 return numCmp<int>(op, rawCmp, 0);
1053 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
1054 int intUnsignedCmp(TOK op, dinteger_t n1, dinteger_t n2)
1056 return numCmp<dinteger_t>(op, n1, n2);
1059 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
1060 int intSignedCmp(TOK op, sinteger_t n1, sinteger_t n2)
1062 return numCmp<sinteger_t>(op, n1, n2);
1065 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
1066 int realCmp(TOK op, real_t r1, real_t r2)
1068 // Don't rely on compiler, handle NAN arguments separately
1069 if (CTFloat::isNaN(r1) || CTFloat::isNaN(r2)) // if unordered
1071 switch (op)
1073 case TOKlt:
1074 case TOKle:
1075 case TOKgt:
1076 case TOKge:
1077 return 0;
1079 default:
1080 assert(0);
1083 else
1085 return numCmp<real_t>(op, r1, r2);
1089 int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2);
1091 /* Conceptually the same as memcmp(e1, e2).
1092 * e1 and e2 may be strings, arrayliterals, or slices.
1093 * For string types, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2.
1094 * For all other types, return 0 if e1 == e2, !=0 if e1 != e2.
1096 int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len)
1098 // Resolve slices, if necessary
1099 uinteger_t lo1 = 0;
1100 uinteger_t lo2 = 0;
1102 Expression *x = e1;
1103 if (x->op == TOKslice)
1105 lo1 = ((SliceExp *)x)->lwr->toInteger();
1106 x = ((SliceExp *)x)->e1;
1108 StringExp *se1 = (x->op == TOKstring) ? (StringExp *)x : NULL;
1109 ArrayLiteralExp *ae1 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : NULL;
1111 x = e2;
1112 if (x->op == TOKslice)
1114 lo2 = ((SliceExp *)x)->lwr->toInteger();
1115 x = ((SliceExp *)x)->e1;
1117 StringExp *se2 = (x->op == TOKstring) ? (StringExp *)x : NULL;
1118 ArrayLiteralExp *ae2 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : NULL;
1120 // Now both must be either TOKarrayliteral or TOKstring
1121 if (se1 && se2)
1122 return sliceCmpStringWithString(se1, se2, (size_t)lo1, (size_t)lo2, (size_t)len);
1123 if (se1 && ae2)
1124 return sliceCmpStringWithArray(se1, ae2, (size_t)lo1, (size_t)lo2, (size_t)len);
1125 if (se2 && ae1)
1126 return -sliceCmpStringWithArray(se2, ae1, (size_t)lo2, (size_t)lo1, (size_t)len);
1128 assert (ae1 && ae2);
1129 // Comparing two array literals. This case is potentially recursive.
1130 // If they aren't strings, we just need an equality check rather than
1131 // a full cmp.
1132 bool needCmp = ae1->type->nextOf()->isintegral();
1133 for (size_t i = 0; i < (size_t)len; i++)
1135 Expression *ee1 = (*ae1->elements)[(size_t)(lo1 + i)];
1136 Expression *ee2 = (*ae2->elements)[(size_t)(lo2 + i)];
1137 if (needCmp)
1139 sinteger_t c = ee1->toInteger() - ee2->toInteger();
1140 if (c > 0)
1141 return 1;
1142 if (c < 0)
1143 return -1;
1145 else
1147 if (ctfeRawCmp(loc, ee1, ee2))
1148 return 1;
1151 return 0;
1154 /* Given a delegate expression e, return .funcptr.
1155 * If e is NullExp, return NULL.
1157 FuncDeclaration *funcptrOf(Expression *e)
1159 assert(e->type->ty == Tdelegate);
1161 if (e->op == TOKdelegate)
1162 return ((DelegateExp *)e)->func;
1163 if (e->op == TOKfunction)
1164 return ((FuncExp *)e)->fd;
1165 assert(e->op == TOKnull);
1166 return NULL;
1169 bool isArray(Expression *e)
1171 return e->op == TOKarrayliteral || e->op == TOKstring ||
1172 e->op == TOKslice || e->op == TOKnull;
1175 /* For strings, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2.
1176 * For all other types, return 0 if e1 == e2, !=0 if e1 != e2.
1178 int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
1180 if (e1->op == TOKclassreference || e2->op == TOKclassreference)
1182 if (e1->op == TOKclassreference && e2->op == TOKclassreference &&
1183 ((ClassReferenceExp *)e1)->value == ((ClassReferenceExp *)e2)->value)
1184 return 0;
1185 return 1;
1187 if (e1->op == TOKtypeid && e2->op == TOKtypeid)
1189 // printf("e1: %s\n", e1->toChars());
1190 // printf("e2: %s\n", e2->toChars());
1191 Type *t1 = isType(((TypeidExp *)e1)->obj);
1192 Type *t2 = isType(((TypeidExp *)e2)->obj);
1193 assert(t1);
1194 assert(t2);
1195 return t1 != t2;
1198 // null == null, regardless of type
1200 if (e1->op == TOKnull && e2->op == TOKnull)
1201 return 0;
1203 if (e1->type->ty == Tpointer && e2->type->ty == Tpointer)
1205 // Can only be an equality test.
1207 dinteger_t ofs1, ofs2;
1208 Expression *agg1 = getAggregateFromPointer(e1, &ofs1);
1209 Expression *agg2 = getAggregateFromPointer(e2, &ofs2);
1210 if ((agg1 == agg2) || (agg1->op == TOKvar && agg2->op == TOKvar &&
1211 ((VarExp *)agg1)->var == ((VarExp *)agg2)->var))
1213 if (ofs1 == ofs2)
1214 return 0;
1216 return 1;
1218 if (e1->type->ty == Tdelegate && e2->type->ty == Tdelegate)
1220 // If .funcptr isn't the same, they are not equal
1222 if (funcptrOf(e1) != funcptrOf(e2))
1223 return 1;
1225 // If both are delegate literals, assume they have the
1226 // same closure pointer. TODO: We don't support closures yet!
1227 if (e1->op == TOKfunction && e2->op == TOKfunction)
1228 return 0;
1229 assert(e1->op == TOKdelegate && e2->op == TOKdelegate);
1231 // Same .funcptr. Do they have the same .ptr?
1232 Expression * ptr1 = ((DelegateExp *)e1)->e1;
1233 Expression * ptr2 = ((DelegateExp *)e2)->e1;
1235 dinteger_t ofs1, ofs2;
1236 Expression *agg1 = getAggregateFromPointer(ptr1, &ofs1);
1237 Expression *agg2 = getAggregateFromPointer(ptr2, &ofs2);
1238 // If they are TOKvar, it means they are FuncDeclarations
1239 if ((agg1 == agg2 && ofs1 == ofs2) ||
1240 (agg1->op == TOKvar && agg2->op == TOKvar &&
1241 ((VarExp *)agg1)->var == ((VarExp *)agg2)->var))
1243 return 0;
1245 return 1;
1247 if (isArray(e1) && isArray(e2))
1249 uinteger_t len1 = resolveArrayLength(e1);
1250 uinteger_t len2 = resolveArrayLength(e2);
1251 // workaround for dmc optimizer bug calculating wrong len for
1252 // uinteger_t len = (len1 < len2 ? len1 : len2);
1253 // if (len == 0) ...
1254 if (len1 > 0 && len2 > 0)
1256 uinteger_t len = (len1 < len2 ? len1 : len2);
1257 int res = ctfeCmpArrays(loc, e1, e2, len);
1258 if (res != 0)
1259 return res;
1261 return (int)(len1 - len2);
1263 if (e1->type->isintegral())
1265 return e1->toInteger() != e2->toInteger();
1267 real_t r1;
1268 real_t r2;
1269 if (e1->type->isreal())
1271 r1 = e1->toReal();
1272 r2 = e2->toReal();
1273 goto L1;
1275 else if (e1->type->isimaginary())
1277 r1 = e1->toImaginary();
1278 r2 = e2->toImaginary();
1280 if (CTFloat::isNaN(r1) || CTFloat::isNaN(r2)) // if unordered
1282 return 1;
1284 else
1286 return (r1 != r2);
1289 else if (e1->type->iscomplex())
1291 return e1->toComplex() != e2->toComplex();
1294 if (e1->op == TOKstructliteral && e2->op == TOKstructliteral)
1296 StructLiteralExp *es1 = (StructLiteralExp *)e1;
1297 StructLiteralExp *es2 = (StructLiteralExp *)e2;
1298 // For structs, we only need to return 0 or 1 (< and > aren't legal).
1300 if (es1->sd != es2->sd)
1301 return 1;
1302 else if ((!es1->elements || !es1->elements->dim) &&
1303 (!es2->elements || !es2->elements->dim))
1304 return 0; // both arrays are empty
1305 else if (!es1->elements || !es2->elements)
1306 return 1;
1307 else if (es1->elements->dim != es2->elements->dim)
1308 return 1;
1309 else
1311 for (size_t i = 0; i < es1->elements->dim; i++)
1313 Expression *ee1 = (*es1->elements)[i];
1314 Expression *ee2 = (*es2->elements)[i];
1316 if (ee1 == ee2)
1317 continue;
1318 if (!ee1 || !ee2)
1319 return 1;
1320 int cmp = ctfeRawCmp(loc, ee1, ee2);
1321 if (cmp)
1322 return 1;
1324 return 0; // All elements are equal
1327 if (e1->op == TOKassocarrayliteral && e2->op == TOKassocarrayliteral)
1329 AssocArrayLiteralExp *es1 = (AssocArrayLiteralExp *)e1;
1330 AssocArrayLiteralExp *es2 = (AssocArrayLiteralExp *)e2;
1332 size_t dim = es1->keys->dim;
1333 if (es2->keys->dim != dim)
1334 return 1;
1336 bool *used = (bool *)mem.xmalloc(sizeof(bool) * dim);
1337 memset(used, 0, sizeof(bool) * dim);
1339 for (size_t i = 0; i < dim; ++i)
1341 Expression *k1 = (*es1->keys)[i];
1342 Expression *v1 = (*es1->values)[i];
1343 Expression *v2 = NULL;
1344 for (size_t j = 0; j < dim; ++j)
1346 if (used[j])
1347 continue;
1348 Expression *k2 = (*es2->keys)[j];
1350 if (ctfeRawCmp(loc, k1, k2))
1351 continue;
1352 used[j] = true;
1353 v2 = (*es2->values)[j];
1354 break;
1356 if (!v2 || ctfeRawCmp(loc, v1, v2))
1358 mem.xfree(used);
1359 return 1;
1362 mem.xfree(used);
1363 return 0;
1365 error(loc, "CTFE internal error: bad compare of `%s` and `%s`", e1->toChars(), e2->toChars());
1366 assert(0);
1367 return 0;
1370 /// Evaluate ==, !=. Resolves slices before comparing. Returns 0 or 1
1371 int ctfeEqual(Loc loc, TOK op, Expression *e1, Expression *e2)
1373 int cmp = !ctfeRawCmp(loc, e1, e2);
1374 if (op == TOKnotequal)
1375 cmp ^= 1;
1376 return cmp;
1379 /// Evaluate is, !is. Resolves slices before comparing. Returns 0 or 1
1380 int ctfeIdentity(Loc loc, TOK op, Expression *e1, Expression *e2)
1382 //printf("ctfeIdentity op = '%s', e1 = %s %s, e2 = %s %s\n", Token::toChars(op),
1383 // Token::toChars(e1->op), e1->toChars(), Token::toChars(e2->op), e1->toChars());
1384 int cmp;
1385 if (e1->op == TOKnull)
1387 cmp = (e2->op == TOKnull);
1389 else if (e2->op == TOKnull)
1391 cmp = 0;
1393 else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
1395 SymOffExp *es1 = (SymOffExp *)e1;
1396 SymOffExp *es2 = (SymOffExp *)e2;
1397 cmp = (es1->var == es2->var && es1->offset == es2->offset);
1399 else if (e1->type->isreal())
1400 cmp = RealEquals(e1->toReal(), e2->toReal());
1401 else if (e1->type->isimaginary())
1402 cmp = RealEquals(e1->toImaginary(), e2->toImaginary());
1403 else if (e1->type->iscomplex())
1405 complex_t v1 = e1->toComplex();
1406 complex_t v2 = e2->toComplex();
1407 cmp = RealEquals(creall(v1), creall(v2)) &&
1408 RealEquals(cimagl(v1), cimagl(v1));
1410 else
1411 cmp = !ctfeRawCmp(loc, e1, e2);
1413 if (op == TOKnotidentity || op == TOKnotequal)
1414 cmp ^= 1;
1415 return cmp;
1418 /// Evaluate >,<=, etc. Resolves slices before comparing. Returns 0 or 1
1419 int ctfeCmp(Loc loc, TOK op, Expression *e1, Expression *e2)
1421 Type *t1 = e1->type->toBasetype();
1422 Type *t2 = e2->type->toBasetype();
1424 if (t1->isString() && t2->isString())
1425 return specificCmp(op, ctfeRawCmp(loc, e1, e2));
1426 else if (t1->isreal())
1427 return realCmp(op, e1->toReal(), e2->toReal());
1428 else if (t1->isimaginary())
1429 return realCmp(op, e1->toImaginary(), e2->toImaginary());
1430 else if (t1->isunsigned() || t2->isunsigned())
1431 return intUnsignedCmp(op, e1->toInteger(), e2->toInteger());
1432 else
1433 return intSignedCmp(op, e1->toInteger(), e2->toInteger());
1436 UnionExp ctfeCat(Loc loc, Type *type, Expression *e1, Expression *e2)
1438 Type *t1 = e1->type->toBasetype();
1439 Type *t2 = e2->type->toBasetype();
1440 UnionExp ue;
1441 if (e2->op == TOKstring && e1->op == TOKarrayliteral &&
1442 t1->nextOf()->isintegral())
1444 // [chars] ~ string => string (only valid for CTFE)
1445 StringExp *es1 = (StringExp *)e2;
1446 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1;
1447 size_t len = es1->len + es2->elements->dim;
1448 unsigned char sz = es1->sz;
1450 void *s = mem.xmalloc((len + 1) * sz);
1451 memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz);
1452 for (size_t i = 0; i < es2->elements->dim; i++)
1454 Expression *es2e = (*es2->elements)[i];
1455 if (es2e->op != TOKint64)
1457 new(&ue) CTFEExp(TOKcantexp);
1458 return ue;
1460 dinteger_t v = es2e->toInteger();
1461 Port::valcpy((utf8_t *)s + i * sz, v, sz);
1464 // Add terminating 0
1465 memset((utf8_t *)s + len * sz, 0, sz);
1467 new(&ue) StringExp(loc, s, len);
1468 StringExp *es = (StringExp *)ue.exp();
1469 es->sz = sz;
1470 es->committed = 0;
1471 es->type = type;
1472 return ue;
1474 if (e1->op == TOKstring && e2->op == TOKarrayliteral &&
1475 t2->nextOf()->isintegral())
1477 // string ~ [chars] => string (only valid for CTFE)
1478 // Concatenate the strings
1479 StringExp *es1 = (StringExp *)e1;
1480 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
1481 size_t len = es1->len + es2->elements->dim;
1482 unsigned char sz = es1->sz;
1484 void *s = mem.xmalloc((len + 1) * sz);
1485 memcpy(s, es1->string, es1->len * sz);
1486 for (size_t i = 0; i < es2->elements->dim; i++)
1488 Expression *es2e = (*es2->elements)[i];
1489 if (es2e->op != TOKint64)
1491 new(&ue) CTFEExp(TOKcantexp);
1492 return ue;
1494 dinteger_t v = es2e->toInteger();
1495 Port::valcpy((utf8_t *)s + (es1->len + i) * sz, v, sz);
1498 // Add terminating 0
1499 memset((utf8_t *)s + len * sz, 0, sz);
1501 new(&ue) StringExp(loc, s, len);
1502 StringExp *es = (StringExp *)ue.exp();
1503 es->sz = sz;
1504 es->committed = 0; //es1->committed;
1505 es->type = type;
1506 return ue;
1508 if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
1509 t1->nextOf()->equals(t2->nextOf()))
1511 // [ e1 ] ~ [ e2 ] ---> [ e1, e2 ]
1512 ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
1513 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
1515 new(&ue) ArrayLiteralExp(es1->loc, copyLiteralArray(es1->elements));
1516 es1 = (ArrayLiteralExp *)ue.exp();
1517 es1->elements->insert(es1->elements->dim, copyLiteralArray(es2->elements));
1518 es1->type = type;
1519 return ue;
1521 if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
1522 t1->nextOf()->equals(t2->nextOf()))
1524 // [ e1 ] ~ null ----> [ e1 ].dup
1525 ue = paintTypeOntoLiteralCopy(type, copyLiteral(e1).copy());
1526 return ue;
1528 if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
1529 t1->nextOf()->equals(t2->nextOf()))
1531 // null ~ [ e2 ] ----> [ e2 ].dup
1532 ue = paintTypeOntoLiteralCopy(type, copyLiteral(e2).copy());
1533 return ue;
1535 ue = Cat(type, e1, e2);
1536 return ue;
1539 /* Given an AA literal 'ae', and a key 'e2':
1540 * Return ae[e2] if present, or NULL if not found.
1542 Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2)
1544 /* Search the keys backwards, in case there are duplicate keys
1546 for (size_t i = ae->keys->dim; i;)
1548 i--;
1549 Expression *ekey = (*ae->keys)[i];
1550 int eq = ctfeEqual(loc, TOKequal, ekey, e2);
1551 if (eq)
1553 return (*ae->values)[i];
1556 return NULL;
1559 /* Same as for constfold.Index, except that it only works for static arrays,
1560 * dynamic arrays, and strings. We know that e1 is an
1561 * interpreted CTFE expression, so it cannot have side-effects.
1563 Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx)
1565 //printf("ctfeIndex(e1 = %s)\n", e1->toChars());
1566 assert(e1->type);
1567 if (e1->op == TOKstring)
1569 StringExp *es1 = (StringExp *)e1;
1570 if (indx >= es1->len)
1572 error(loc, "string index %llu is out of bounds [0 .. %llu]", (ulonglong)indx, (ulonglong)es1->len);
1573 return CTFEExp::cantexp;
1575 return new IntegerExp(loc, es1->charAt(indx), type);
1577 assert(e1->op == TOKarrayliteral);
1579 ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1580 if (indx >= ale->elements->dim)
1582 error(loc, "array index %llu is out of bounds %s[0 .. %llu]", (ulonglong)indx, e1->toChars(), (ulonglong)ale->elements->dim);
1583 return CTFEExp::cantexp;
1585 Expression *e = (*ale->elements)[(size_t)indx];
1586 return paintTypeOntoLiteral(type, e);
1590 Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e)
1592 if (e->op == TOKnull)
1593 return paintTypeOntoLiteral(to, e);
1594 if (e->op == TOKclassreference)
1596 // Disallow reinterpreting class casts. Do this by ensuring that
1597 // the original class can implicitly convert to the target class
1598 ClassDeclaration *originalClass = ((ClassReferenceExp *)e)->originalClass();
1599 if (originalClass->type->implicitConvTo(to->mutableOf()))
1600 return paintTypeOntoLiteral(to, e);
1601 else
1602 return new NullExp(loc, to);
1604 // Allow TypeInfo type painting
1605 if (isTypeInfo_Class(e->type) && e->type->implicitConvTo(to))
1606 return paintTypeOntoLiteral(to, e);
1607 // Allow casting away const for struct literals
1608 if (e->op == TOKstructliteral &&
1609 e->type->toBasetype()->castMod(0) == to->toBasetype()->castMod(0))
1611 return paintTypeOntoLiteral(to, e);
1614 Expression *r;
1615 if (e->type->equals(type) && type->equals(to))
1617 // necessary not to change e's address for pointer comparisons
1618 r = e;
1620 else if (to->toBasetype()->ty == Tarray && type->toBasetype()->ty == Tarray &&
1621 to->toBasetype()->nextOf()->size() == type->toBasetype()->nextOf()->size())
1623 // Bugzilla 12495: Array reinterpret casts: eg. string to immutable(ubyte)[]
1624 return paintTypeOntoLiteral(to, e);
1626 else
1628 r = Cast(loc, type, to, e).copy();
1630 if (CTFEExp::isCantExp(r))
1631 error(loc, "cannot cast %s to %s at compile time", e->toChars(), to->toChars());
1632 if (e->op == TOKarrayliteral)
1633 ((ArrayLiteralExp *)e)->ownedByCtfe = OWNEDctfe;
1634 if (e->op == TOKstring)
1635 ((StringExp *)e)->ownedByCtfe = OWNEDctfe;
1636 return r;
1639 /******** Assignment helper functions ***************************/
1641 /* Set dest = src, where both dest and src are container value literals
1642 * (ie, struct literals, or static arrays (can be an array literal or a string))
1643 * Assignment is recursively in-place.
1644 * Purpose: any reference to a member of 'dest' will remain valid after the
1645 * assignment.
1647 void assignInPlace(Expression *dest, Expression *src)
1649 assert(dest->op == TOKstructliteral ||
1650 dest->op == TOKarrayliteral ||
1651 dest->op == TOKstring);
1652 Expressions *oldelems;
1653 Expressions *newelems;
1654 if (dest->op == TOKstructliteral)
1656 assert(dest->op == src->op);
1657 oldelems = ((StructLiteralExp *)dest)->elements;
1658 newelems = ((StructLiteralExp *)src)->elements;
1659 if (((StructLiteralExp *)dest)->sd->isNested() && oldelems->dim == newelems->dim - 1)
1660 oldelems->push(NULL);
1662 else if (dest->op == TOKarrayliteral && src->op==TOKarrayliteral)
1664 oldelems = ((ArrayLiteralExp *)dest)->elements;
1665 newelems = ((ArrayLiteralExp *)src)->elements;
1667 else if (dest->op == TOKstring && src->op == TOKstring)
1669 sliceAssignStringFromString((StringExp *)dest, (StringExp *)src, 0);
1670 return;
1672 else if (dest->op == TOKarrayliteral && src->op == TOKstring)
1674 sliceAssignArrayLiteralFromString((ArrayLiteralExp *)dest, (StringExp *)src, 0);
1675 return;
1677 else if (src->op == TOKarrayliteral && dest->op == TOKstring)
1679 sliceAssignStringFromArrayLiteral((StringExp *)dest, (ArrayLiteralExp *)src, 0);
1680 return;
1682 else
1683 assert(0);
1685 assert(oldelems->dim == newelems->dim);
1687 for (size_t i= 0; i < oldelems->dim; ++i)
1689 Expression *e = (*newelems)[i];
1690 Expression *o = (*oldelems)[i];
1691 if (e->op == TOKstructliteral)
1693 assert(o->op == e->op);
1694 assignInPlace(o, e);
1696 else if (e->type->ty == Tsarray && e->op != TOKvoid &&
1697 o->type->ty == Tsarray)
1699 assignInPlace(o, e);
1701 else
1703 (*oldelems)[i] = (*newelems)[i];
1708 // Duplicate the elements array, then set field 'indexToChange' = newelem.
1709 Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem)
1711 Expressions *expsx = new Expressions();
1712 ++CtfeStatus::numArrayAllocs;
1713 expsx->setDim(oldelems->dim);
1714 for (size_t j = 0; j < expsx->dim; j++)
1716 if (j == indexToChange)
1717 (*expsx)[j] = newelem;
1718 else
1719 (*expsx)[j] = (*oldelems)[j];
1721 return expsx;
1724 // Given an AA literal aae, set aae[index] = newval and return newval.
1725 Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae,
1726 Expression *index, Expression *newval)
1728 /* Create new associative array literal reflecting updated key/value
1730 Expressions *keysx = aae->keys;
1731 Expressions *valuesx = aae->values;
1732 int updated = 0;
1733 for (size_t j = valuesx->dim; j; )
1735 j--;
1736 Expression *ekey = (*aae->keys)[j];
1737 int eq = ctfeEqual(loc, TOKequal, ekey, index);
1738 if (eq)
1740 (*valuesx)[j] = newval;
1741 updated = 1;
1744 if (!updated)
1746 // Append index/newval to keysx[]/valuesx[]
1747 valuesx->push(newval);
1748 keysx->push(index);
1750 return newval;
1753 /// Given array literal oldval of type ArrayLiteralExp or StringExp, of length
1754 /// oldlen, change its length to newlen. If the newlen is longer than oldlen,
1755 /// all new elements will be set to the default initializer for the element type.
1756 UnionExp changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
1757 Expression *oldval, size_t oldlen, size_t newlen)
1759 UnionExp ue;
1760 Type *elemType = arrayType->next;
1761 assert(elemType);
1762 Expression *defaultElem = elemType->defaultInitLiteral(loc);
1763 Expressions *elements = new Expressions();
1764 elements->setDim(newlen);
1766 // Resolve slices
1767 size_t indxlo = 0;
1768 if (oldval->op == TOKslice)
1770 indxlo = (size_t)((SliceExp *)oldval)->lwr->toInteger();
1771 oldval = ((SliceExp *)oldval)->e1;
1773 size_t copylen = oldlen < newlen ? oldlen : newlen;
1774 if (oldval->op == TOKstring)
1776 StringExp *oldse = (StringExp *)oldval;
1777 void *s = mem.xcalloc(newlen + 1, oldse->sz);
1778 memcpy(s, oldse->string, copylen * oldse->sz);
1779 unsigned defaultValue = (unsigned)(defaultElem->toInteger());
1780 for (size_t elemi = copylen; elemi < newlen; ++elemi)
1782 switch (oldse->sz)
1784 case 1: (( utf8_t *)s)[(size_t)(indxlo + elemi)] = ( utf8_t)defaultValue; break;
1785 case 2: ((utf16_t *)s)[(size_t)(indxlo + elemi)] = (utf16_t)defaultValue; break;
1786 case 4: ((utf32_t *)s)[(size_t)(indxlo + elemi)] = (utf32_t)defaultValue; break;
1787 default: assert(0);
1790 new(&ue) StringExp(loc, s, newlen);
1791 StringExp *se = (StringExp *)ue.exp();
1792 se->type = arrayType;
1793 se->sz = oldse->sz;
1794 se->committed = oldse->committed;
1795 se->ownedByCtfe = OWNEDctfe;
1797 else
1799 if (oldlen != 0)
1801 assert(oldval->op == TOKarrayliteral);
1802 ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval;
1803 for (size_t i = 0; i < copylen; i++)
1804 (*elements)[i] = (*ae->elements)[indxlo + i];
1806 if (elemType->ty == Tstruct || elemType->ty == Tsarray)
1808 /* If it is an aggregate literal representing a value type,
1809 * we need to create a unique copy for each element
1811 for (size_t i = copylen; i < newlen; i++)
1812 (*elements)[i] = copyLiteral(defaultElem).copy();
1814 else
1816 for (size_t i = copylen; i < newlen; i++)
1817 (*elements)[i] = defaultElem;
1819 new(&ue) ArrayLiteralExp(loc, elements);
1820 ArrayLiteralExp *aae = (ArrayLiteralExp *)ue.exp();
1821 aae->type = arrayType;
1822 aae->ownedByCtfe = OWNEDctfe;
1824 return ue;
1827 /*************************** CTFE Sanity Checks ***************************/
1829 bool isCtfeValueValid(Expression *newval)
1831 Type *tb = newval->type->toBasetype();
1833 if (newval->op == TOKint64 ||
1834 newval->op == TOKfloat64 ||
1835 newval->op == TOKchar ||
1836 newval->op == TOKcomplex80)
1838 return tb->isscalar();
1840 if (newval->op == TOKnull)
1842 return tb->ty == Tnull ||
1843 tb->ty == Tpointer ||
1844 tb->ty == Tarray ||
1845 tb->ty == Taarray ||
1846 tb->ty == Tclass ||
1847 tb->ty == Tdelegate;
1850 if (newval->op == TOKstring)
1851 return true; // CTFE would directly use the StringExp in AST.
1852 if (newval->op == TOKarrayliteral)
1853 return true; //((ArrayLiteralExp *)newval)->ownedByCtfe;
1854 if (newval->op == TOKassocarrayliteral)
1855 return true; //((AssocArrayLiteralExp *)newval)->ownedByCtfe;
1856 if (newval->op == TOKstructliteral)
1857 return true; //((StructLiteralExp *)newval)->ownedByCtfe;
1858 if (newval->op == TOKclassreference)
1859 return true;
1861 if (newval->op == TOKvector)
1862 return true; // vector literal
1864 if (newval->op == TOKfunction)
1865 return true; // function literal or delegate literal
1866 if (newval->op == TOKdelegate)
1868 // &struct.func or &clasinst.func
1869 // &nestedfunc
1870 Expression *ethis = ((DelegateExp *)newval)->e1;
1871 return (ethis->op == TOKstructliteral ||
1872 ethis->op == TOKclassreference ||
1873 (ethis->op == TOKvar && ((VarExp *)ethis)->var == ((DelegateExp *)newval)->func));
1875 if (newval->op == TOKsymoff)
1877 // function pointer, or pointer to static variable
1878 Declaration *d = ((SymOffExp *)newval)->var;
1879 return d->isFuncDeclaration() || d->isDataseg();
1881 if (newval->op == TOKtypeid)
1883 // always valid
1884 return true;
1886 if (newval->op == TOKaddress)
1888 // e1 should be a CTFE reference
1889 Expression *e1 = ((AddrExp *)newval)->e1;
1890 return tb->ty == Tpointer &&
1891 ((e1->op == TOKstructliteral && isCtfeValueValid(e1)) ||
1892 (e1->op == TOKvar) ||
1893 (e1->op == TOKdotvar && isCtfeReferenceValid(e1)) ||
1894 (e1->op == TOKindex && isCtfeReferenceValid(e1)) ||
1895 (e1->op == TOKslice && e1->type->toBasetype()->ty == Tsarray));
1897 if (newval->op == TOKslice)
1899 // e1 should be an array aggregate
1900 SliceExp *se = (SliceExp *)newval;
1901 assert(se->lwr && se->lwr->op == TOKint64);
1902 assert(se->upr && se->upr->op == TOKint64);
1903 return (tb->ty == Tarray ||
1904 tb->ty == Tsarray) &&
1905 (se->e1->op == TOKstring ||
1906 se->e1->op == TOKarrayliteral);
1909 if (newval->op == TOKvoid)
1910 return true; // uninitialized value
1912 newval->error("CTFE internal error: illegal CTFE value %s", newval->toChars());
1913 return false;
1916 bool isCtfeReferenceValid(Expression *newval)
1918 if (newval->op == TOKthis)
1919 return true;
1920 if (newval->op == TOKvar)
1922 VarDeclaration *v = ((VarExp *)newval)->var->isVarDeclaration();
1923 assert(v);
1924 // Must not be a reference to a reference
1925 return true;
1927 if (newval->op == TOKindex)
1929 Expression *eagg = ((IndexExp *)newval)->e1;
1930 return eagg->op == TOKstring ||
1931 eagg->op == TOKarrayliteral ||
1932 eagg->op == TOKassocarrayliteral;
1934 if (newval->op == TOKdotvar)
1936 Expression *eagg = ((DotVarExp *)newval)->e1;
1937 return (eagg->op == TOKstructliteral || eagg->op == TOKclassreference) &&
1938 isCtfeValueValid(eagg);
1941 // Internally a ref variable may directly point a stack memory.
1942 // e.g. ref int v = 1;
1943 return isCtfeValueValid(newval);
1946 // Used for debugging only
1947 void showCtfeExpr(Expression *e, int level)
1949 for (int i = level; i > 0; --i) printf(" ");
1950 Expressions *elements = NULL;
1951 // We need the struct definition to detect block assignment
1952 StructDeclaration *sd = NULL;
1953 ClassDeclaration *cd = NULL;
1954 if (e->op == TOKstructliteral)
1956 elements = ((StructLiteralExp *)e)->elements;
1957 sd = ((StructLiteralExp *)e)->sd;
1958 printf("STRUCT type = %s %p:\n", e->type->toChars(),
1961 else if (e->op == TOKclassreference)
1963 elements = ((ClassReferenceExp *)e)->value->elements;
1964 cd = ((ClassReferenceExp *)e)->originalClass();
1965 printf("CLASS type = %s %p:\n", e->type->toChars(),
1966 ((ClassReferenceExp *)e)->value);
1968 else if (e->op == TOKarrayliteral)
1970 elements = ((ArrayLiteralExp *)e)->elements;
1971 printf("ARRAY LITERAL type=%s %p:\n", e->type->toChars(),
1974 else if (e->op == TOKassocarrayliteral)
1976 printf("AA LITERAL type=%s %p:\n", e->type->toChars(),
1979 else if (e->op == TOKstring)
1981 printf("STRING %s %p\n", e->toChars(),
1982 ((StringExp *)e)->string);
1984 else if (e->op == TOKslice)
1986 printf("SLICE %p: %s\n", e, e->toChars());
1987 showCtfeExpr(((SliceExp *)e)->e1, level + 1);
1989 else if (e->op == TOKvar)
1991 printf("VAR %p %s\n", e, e->toChars());
1992 VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
1993 if (v && getValue(v))
1994 showCtfeExpr(getValue(v), level + 1);
1996 else if (e->op == TOKaddress)
1998 // This is potentially recursive. We mustn't try to print the thing we're pointing to.
1999 printf("POINTER %p to %p: %s\n", e, ((AddrExp *)e)->e1, e->toChars());
2001 else
2002 printf("VALUE %p: %s\n", e, e->toChars());
2004 if (elements)
2006 size_t fieldsSoFar = 0;
2007 for (size_t i = 0; i < elements->dim; i++)
2009 Expression *z = NULL;
2010 VarDeclaration *v = NULL;
2011 if (i > 15)
2013 printf("...(total %d elements)\n", (int)elements->dim);
2014 return;
2016 if (sd)
2018 v = sd->fields[i];
2019 z = (*elements)[i];
2021 else if (cd)
2023 while (i - fieldsSoFar >= cd->fields.dim)
2025 fieldsSoFar += cd->fields.dim;
2026 cd = cd->baseClass;
2027 for (int j = level; j > 0; --j) printf(" ");
2028 printf(" BASE CLASS: %s\n", cd->toChars());
2030 v = cd->fields[i - fieldsSoFar];
2031 assert((elements->dim + i) >= (fieldsSoFar + cd->fields.dim));
2032 size_t indx = (elements->dim - fieldsSoFar)- cd->fields.dim + i;
2033 assert(indx < elements->dim);
2034 z = (*elements)[indx];
2036 if (!z)
2038 for (int j = level; j > 0; --j) printf(" ");
2039 printf(" void\n");
2040 continue;
2043 if (v)
2045 // If it is a void assignment, use the default initializer
2046 if ((v->type->ty != z->type->ty) && v->type->ty == Tsarray)
2048 for (int j = level; --j; ) printf(" ");
2049 printf(" field: block initalized static array\n");
2050 continue;
2053 showCtfeExpr(z, level + 1);
2058 /*************************** Void initialization ***************************/
2060 UnionExp voidInitLiteral(Type *t, VarDeclaration *var)
2062 UnionExp ue;
2063 if (t->ty == Tsarray)
2065 TypeSArray *tsa = (TypeSArray *)t;
2066 Expression *elem = voidInitLiteral(tsa->next, var).copy();
2068 // For aggregate value types (structs, static arrays) we must
2069 // create an a separate copy for each element.
2070 bool mustCopy = (elem->op == TOKarrayliteral || elem->op == TOKstructliteral);
2072 Expressions *elements = new Expressions();
2073 size_t d = (size_t)tsa->dim->toInteger();
2074 elements->setDim(d);
2075 for (size_t i = 0; i < d; i++)
2077 if (mustCopy && i > 0)
2078 elem = copyLiteral(elem).copy();
2079 (*elements)[i] = elem;
2081 new(&ue) ArrayLiteralExp(var->loc, elements);
2082 ArrayLiteralExp *ae = (ArrayLiteralExp *)ue.exp();
2083 ae->type = tsa;
2084 ae->ownedByCtfe = OWNEDctfe;
2086 else if (t->ty == Tstruct)
2088 TypeStruct *ts = (TypeStruct *)t;
2089 Expressions *exps = new Expressions();
2090 exps->setDim(ts->sym->fields.dim);
2091 for (size_t i = 0; i < ts->sym->fields.dim; i++)
2093 (*exps)[i] = voidInitLiteral(ts->sym->fields[i]->type, ts->sym->fields[i]).copy();
2095 new(&ue) StructLiteralExp(var->loc, ts->sym, exps);
2096 StructLiteralExp *se = (StructLiteralExp *)ue.exp();
2097 se->type = ts;
2098 se->ownedByCtfe = OWNEDctfe;
2100 else
2101 new(&ue) VoidInitExp(var, t);
2102 return ue;