]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
f3ed896c | 3 | * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved |
b4c522fa IB |
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/dlang/dmd/blob/master/src/ctfe.h | |
9 | */ | |
10 | ||
11 | #pragma once | |
12 | ||
13 | #include "arraytypes.h" | |
14 | #include "tokens.h" | |
15 | #include "expression.h" | |
16 | ||
17 | /** | |
18 | Global status of the CTFE engine. Mostly used for performance diagnostics | |
19 | */ | |
20 | struct CtfeStatus | |
21 | { | |
22 | static int callDepth; // current number of recursive calls | |
23 | /* When printing a stack trace, | |
24 | * suppress this number of calls | |
25 | */ | |
26 | static int stackTraceCallsToSuppress; | |
27 | static int maxCallDepth; // highest number of recursive calls | |
28 | static int numArrayAllocs; // Number of allocated arrays | |
29 | static int numAssignments; // total number of assignments executed | |
30 | }; | |
31 | ||
32 | /** | |
33 | A reference to a class, or an interface. We need this when we | |
34 | point to a base class (we must record what the type is). | |
35 | */ | |
36 | class ClassReferenceExp : public Expression | |
37 | { | |
38 | public: | |
39 | StructLiteralExp *value; | |
40 | ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type); | |
41 | ClassDeclaration *originalClass(); | |
42 | ||
43 | /// Return index of the field, or -1 if not found | |
44 | int getFieldIndex(Type *fieldtype, unsigned fieldoffset); | |
45 | /// Return index of the field, or -1 if not found | |
46 | /// Same as getFieldIndex, but checks for a direct match with the VarDeclaration | |
47 | int findFieldIndexByName(VarDeclaration *v); | |
48 | void accept(Visitor *v) { v->visit(this); } | |
49 | }; | |
50 | ||
51 | // The various functions are used only to detect compiler CTFE bugs | |
52 | Expression *getValue(VarDeclaration *vd); | |
53 | bool hasValue(VarDeclaration *vd); | |
54 | void setValueNull(VarDeclaration *vd); | |
55 | void setValueWithoutChecking(VarDeclaration *vd, Expression *newval); | |
56 | void setValue(VarDeclaration *vd, Expression *newval); | |
57 | ||
58 | /// Return index of the field, or -1 if not found | |
59 | /// Same as getFieldIndex, but checks for a direct match with the VarDeclaration | |
60 | int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v); | |
61 | ||
62 | ||
63 | /** An uninitialized value | |
64 | */ | |
65 | class VoidInitExp : public Expression | |
66 | { | |
67 | public: | |
68 | VarDeclaration *var; | |
69 | ||
70 | VoidInitExp(VarDeclaration *var, Type *type); | |
71 | const char *toChars(); | |
72 | void accept(Visitor *v) { v->visit(this); } | |
73 | }; | |
74 | ||
75 | // Create an appropriate void initializer | |
76 | UnionExp voidInitLiteral(Type *t, VarDeclaration *var); | |
77 | ||
78 | /** Fake class which holds the thrown exception. | |
79 | Used for implementing exception handling. | |
80 | */ | |
81 | class ThrownExceptionExp : public Expression | |
82 | { | |
83 | public: | |
84 | ClassReferenceExp *thrown; // the thing being tossed | |
85 | ThrownExceptionExp(Loc loc, ClassReferenceExp *victim); | |
86 | const char *toChars(); | |
87 | /// Generate an error message when this exception is not caught | |
88 | void generateUncaughtError(); | |
89 | void accept(Visitor *v) { v->visit(this); } | |
90 | }; | |
91 | ||
92 | /****************************************************************/ | |
93 | ||
94 | // This type is only used by the interpreter. | |
95 | ||
96 | class CTFEExp : public Expression | |
97 | { | |
98 | public: | |
99 | CTFEExp(TOK tok); | |
100 | ||
101 | const char *toChars(); | |
102 | ||
103 | // Handy instances to share | |
104 | static CTFEExp *cantexp; | |
105 | static CTFEExp *voidexp; | |
106 | static CTFEExp *breakexp; | |
107 | static CTFEExp *continueexp; | |
108 | static CTFEExp *gotoexp; | |
109 | ||
110 | static bool isCantExp(Expression *e) { return e && e->op == TOKcantexp; } | |
111 | static bool isGotoExp(Expression *e) { return e && e->op == TOKgoto; } | |
112 | }; | |
113 | ||
114 | /****************************************************************/ | |
115 | ||
116 | ||
117 | /// True if 'e' is TOKcantexp, or an exception | |
118 | bool exceptionOrCantInterpret(Expression *e); | |
119 | ||
120 | // Used for debugging only | |
121 | void showCtfeExpr(Expression *e, int level = 0); | |
122 | ||
123 | /// Return true if this is a valid CTFE expression | |
124 | bool isCtfeValueValid(Expression *newval); | |
125 | bool isCtfeReferenceValid(Expression *newval); | |
126 | ||
127 | /// Given expr, which evaluates to an array/AA/string literal, | |
128 | /// return true if it needs to be copied | |
129 | bool needToCopyLiteral(Expression *expr); | |
130 | ||
131 | /// Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral. | |
132 | /// This value will be used for in-place modification. | |
133 | UnionExp copyLiteral(Expression *e); | |
134 | ||
135 | /// Set this literal to the given type, copying it if necessary | |
136 | Expression *paintTypeOntoLiteral(Type *type, Expression *lit); | |
137 | UnionExp paintTypeOntoLiteralCopy(Type *type, Expression *lit); | |
138 | ||
139 | /// Convert from a CTFE-internal slice, into a normal Expression | |
140 | Expression *resolveSlice(Expression *e, UnionExp *pue = NULL); | |
141 | ||
142 | /// Determine the array length, without interpreting the expression. | |
143 | uinteger_t resolveArrayLength(Expression *e); | |
144 | ||
145 | /// Create an array literal consisting of 'elem' duplicated 'dim' times. | |
146 | ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type, | |
147 | Expression *elem, size_t dim); | |
148 | ||
149 | /// Create a string literal consisting of 'value' duplicated 'dim' times. | |
150 | StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type, | |
151 | unsigned value, size_t dim, unsigned char sz); | |
152 | ||
153 | ||
154 | /* Set dest = src, where both dest and src are container value literals | |
155 | * (ie, struct literals, or static arrays (can be an array literal or a string) | |
156 | * Assignment is recursively in-place. | |
157 | * Purpose: any reference to a member of 'dest' will remain valid after the | |
158 | * assignment. | |
159 | */ | |
160 | void assignInPlace(Expression *dest, Expression *src); | |
161 | ||
162 | /// Duplicate the elements array, then set field 'indexToChange' = newelem. | |
163 | Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem); | |
164 | ||
165 | /// Given an AA literal aae, set arr[index] = newval and return the new array. | |
166 | Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, | |
167 | Expression *index, Expression *newval); | |
168 | ||
169 | /// Given array literal oldval of type ArrayLiteralExp or StringExp, of length | |
170 | /// oldlen, change its length to newlen. If the newlen is longer than oldlen, | |
171 | /// all new elements will be set to the default initializer for the element type. | |
172 | UnionExp changeArrayLiteralLength(Loc loc, TypeArray *arrayType, | |
173 | Expression *oldval, size_t oldlen, size_t newlen); | |
174 | ||
175 | ||
176 | ||
177 | /// Return true if t is a pointer (not a function pointer) | |
178 | bool isPointer(Type *t); | |
179 | ||
180 | // For CTFE only. Returns true if 'e' is TRUE or a non-null pointer. | |
181 | bool isTrueBool(Expression *e); | |
182 | ||
183 | /// Is it safe to convert from srcPointee* to destPointee* ? | |
184 | /// srcPointee is the genuine type (never void). | |
185 | /// destPointee may be void. | |
186 | bool isSafePointerCast(Type *srcPointee, Type *destPointee); | |
187 | ||
188 | /// Given pointer e, return the memory block expression it points to, | |
189 | /// and set ofs to the offset within that memory block. | |
190 | Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs); | |
191 | ||
192 | /// Return true if agg1 and agg2 are pointers to the same memory block | |
193 | bool pointToSameMemoryBlock(Expression *agg1, Expression *agg2); | |
194 | ||
195 | // return e1 - e2 as an integer, or error if not possible | |
196 | UnionExp pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2); | |
197 | ||
198 | /// Return 1 if true, 0 if false | |
199 | /// -1 if comparison is illegal because they point to non-comparable memory blocks | |
200 | int comparePointers(TOK op, Expression *agg1, dinteger_t ofs1, Expression *agg2, dinteger_t ofs2); | |
201 | ||
202 | // Return eptr op e2, where eptr is a pointer, e2 is an integer, | |
203 | // and op is TOKadd or TOKmin | |
204 | UnionExp pointerArithmetic(Loc loc, TOK op, Type *type, | |
205 | Expression *eptr, Expression *e2); | |
206 | ||
207 | // True if conversion from type 'from' to 'to' involves a reinterpret_cast | |
208 | // floating point -> integer or integer -> floating point | |
209 | bool isFloatIntPaint(Type *to, Type *from); | |
210 | ||
211 | // Reinterpret float/int value 'fromVal' as a float/integer of type 'to'. | |
212 | Expression *paintFloatInt(Expression *fromVal, Type *to); | |
213 | ||
214 | /// Return true if t is an AA | |
215 | bool isAssocArray(Type *t); | |
216 | ||
217 | /// Given a template AA type, extract the corresponding built-in AA type | |
218 | TypeAArray *toBuiltinAAType(Type *t); | |
219 | ||
220 | /* Given an AA literal 'ae', and a key 'e2': | |
221 | * Return ae[e2] if present, or NULL if not found. | |
222 | * Return TOKcantexp on error. | |
223 | */ | |
224 | Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2); | |
225 | ||
226 | /// True if type is TypeInfo_Class | |
227 | bool isTypeInfo_Class(Type *type); | |
228 | ||
229 | ||
230 | /*********************************************** | |
231 | COW const-folding operations | |
232 | ***********************************************/ | |
233 | ||
234 | /// Return true if non-pointer expression e can be compared | |
235 | /// with >,is, ==, etc, using ctfeCmp, ctfeEquals, ctfeIdentity | |
236 | bool isCtfeComparable(Expression *e); | |
237 | ||
238 | /// Evaluate ==, !=. Resolves slices before comparing. Returns 0 or 1 | |
239 | int ctfeEqual(Loc loc, TOK op, Expression *e1, Expression *e2); | |
240 | ||
241 | /// Evaluate is, !is. Resolves slices before comparing. Returns 0 or 1 | |
242 | int ctfeIdentity(Loc loc, TOK op, Expression *e1, Expression *e2); | |
243 | ||
244 | /// Returns rawCmp OP 0; where OP is ==, !=, <, >=, etc. Result is 0 or 1 | |
245 | int specificCmp(TOK op, int rawCmp); | |
246 | ||
247 | /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 | |
248 | int intUnsignedCmp(TOK op, dinteger_t n1, dinteger_t n2); | |
249 | ||
250 | /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 | |
251 | int intSignedCmp(TOK op, sinteger_t n1, sinteger_t n2); | |
252 | ||
253 | /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 | |
254 | int realCmp(TOK op, real_t r1, real_t r2); | |
255 | ||
256 | /// Evaluate >,<=, etc. Resolves slices before comparing. Returns 0 or 1 | |
257 | int ctfeCmp(Loc loc, TOK op, Expression *e1, Expression *e2); | |
258 | ||
259 | /// Returns e1 ~ e2. Resolves slices before concatenation. | |
260 | UnionExp ctfeCat(Loc loc, Type *type, Expression *e1, Expression *e2); | |
261 | ||
262 | /// Same as for constfold.Index, except that it only works for static arrays, | |
263 | /// dynamic arrays, and strings. | |
264 | Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx); | |
265 | ||
266 | /// Cast 'e' of type 'type' to type 'to'. | |
267 | Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e); |