Rune - Change regsave burden for syscalls
[rune.git] / librune / exp.c
1 /*
2  * EXP.C
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9
10 Exp *
11 _AllocExpDebug(token_t *tok, const char *file, int line)
12 {
13         fprintf(stderr, "allocate from %s:%d\n", file, line);
14         return(_AllocExp(tok));
15 }
16
17 Exp *
18 _AllocExp(token_t *tok)
19 {
20         Exp *exp = zalloc(sizeof(Exp));
21         exp->ex_Run = RunUnresolvedExp;
22         exp->ex_Run64 = Run64DefaultExp;
23         exp->ex_Gen = GenUnresolvedExp;
24         exp->ex_Visibility = SCOPE_ALL_VISIBLE | 0x80000000;
25         exp->ex_TmpOffset = -1;
26         if (tok)
27                 LexInitRef(&exp->ex_LexRef, tok);
28         return(exp);
29 }
30
31 void
32 FreeExp(Exp *next)
33 {
34         Exp *exp;
35
36         while ((exp = next) != NULL) {
37                 RelStrTable(&exp->ex_Id);
38                 FreeExp(exp->ex_Lhs);
39                 FreeExp(exp->ex_Rhs);
40                 exp->ex_Lhs = NULL;     /* safety */
41                 exp->ex_Rhs = NULL;     /* safety */
42                 /* XXX free type */
43                 next = exp->ex_Next;
44                 exp->ex_Next = NULL;
45                 LexDoneRef(&exp->ex_LexRef);
46                 zfree(exp, sizeof(Exp));
47         }
48 }
49
50 /*
51  * Wrap an expression (used for things like typeof()).  The
52  * passed expression may be NULL.
53  */
54 Exp *
55 WrapExp(token_t *tok, Exp *oexp, int t)
56 {
57         Exp *exp = AllocExp(NULL);
58
59         exp->ex_Lhs = oexp;
60         exp->ex_Token = t;
61         if (oexp) {
62                 LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
63                 exp->ex_Flags |= EXF_UNARY;
64                 exp->ex_ArgId = oexp->ex_ArgId;
65                 oexp->ex_ArgId = NULL;
66         } else {
67                 LexInitRef(&exp->ex_LexRef, tok);
68         }
69         return(exp);
70 }
71
72 /*
73  * Invert the sense of a boolean expression
74  */
75 Exp *
76 ExpToNotExp(Exp *oexp)
77 {
78         Exp *exp = AllocExp(NULL);
79
80         LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
81
82         exp->ex_Lhs = oexp;
83         exp->ex_Token = TOK_NOT;
84         exp->ex_Type = &BoolType;
85         exp->ex_Flags |= EXF_UNARY | EXF_PARSE_TYPE;
86         exp->ex_Flags |= oexp->ex_Flags & EXF_DUPEXP;
87         exp->ex_ArgId = oexp->ex_ArgId;
88         oexp->ex_ArgId = NULL;
89         return(exp);
90 }
91
92 /*
93  * General Cast
94  */
95 Exp *
96 ExpToCastExp(Exp *oexp, Type *type)
97 {
98         if (oexp->ex_Type != type) {
99                 Exp *exp = AllocExp(NULL);
100
101                 LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
102                 exp->ex_Lhs = oexp;
103                 exp->ex_Token = TOK_CAST;
104                 exp->ex_Type = type;
105                 exp->ex_Flags |= EXF_UNARY | EXF_PARSE_TYPE;
106                 exp->ex_Flags |= oexp->ex_Flags & EXF_DUPEXP;
107                 exp->ex_ArgId = oexp->ex_ArgId;
108                 oexp->ex_ArgId = NULL;
109                 oexp = exp;
110         }
111         return(oexp);
112 }
113
114 /*
115  * Convert a list of expressions linked by ex_Next to a compound expression.
116  * Note that a degenerate TOK_VOIDEXP converts to an empty compound
117  * expression (just as () was originally parsed as TOK_VOIDEXP).
118  *
119  * Since ex_Next is used for other purposes, such as the resolver's
120  * method call conversion code, we have to return a consolidated
121  * TOK_COMPOUND expression node whos Lhs bases a linked list of 
122  * expressions representing the compound expression.
123  *
124  * Compound expressions need a type hint to be evaluated properly (handled
125  * elsewhere).
126  *
127  * Note that we do not promote ex_ArgId to the compound element here.  This
128  * function is designed to create a compound expression out of a linked list,
129  * not really to convert a non-compound expression to a compound expression
130  * (though it does that too).
131  */
132 Exp *
133 ExpToCompoundExp(Exp *oexp, int t)
134 {
135         Exp *exp = AllocExp(NULL);
136
137         LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
138         if (oexp->ex_Token == TOK_VOIDEXP && oexp->ex_Next == NULL)
139                 exp->ex_Lhs = NULL;
140         else
141                 exp->ex_Lhs = oexp;
142         exp->ex_Token = t;
143         exp->ex_Flags |= EXF_COMPOUND;
144         exp->ex_Flags |= oexp->ex_Flags & EXF_DUPEXP;
145
146         return(exp);
147 }
148
149 Exp *
150 ExpToBracketedExp(Exp *oexp, int t)
151 {
152         Exp *exp = AllocExp(NULL);
153
154         LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
155         exp->ex_Lhs = oexp;
156         exp->ex_Token = t;
157         exp->ex_Flags |= EXF_COMPOUND;
158         exp->ex_Flags |= oexp->ex_Flags & EXF_DUPEXP;
159
160         return(exp);
161 }
162
163 Exp *
164 SetDupExp(SemGroup *sg, Exp *exp)
165 {
166         if (exp && (exp->ex_Flags & EXF_DUPEXP) == 0) {
167                 exp->ex_Flags |= EXF_DUPEXP;
168                 if (exp->ex_Lhs)
169                         SetDupExp(sg, exp->ex_Lhs);
170                 if (exp->ex_Rhs)
171                         SetDupExp(sg, exp->ex_Rhs);
172                 if (exp->ex_Next)
173                         SetDupExp(sg, exp->ex_Next);
174         }
175         return(exp);
176 }
177
178 /*
179  * DupExp() - duplicate an expression
180  *
181  *      This occurs during the superclass/subclass merge, before we
182  *      resolve any expression trees.
183  */
184 Exp *
185 DupExp(SemGroup *sg, Exp *oexp)
186 {
187         Exp *exp;
188
189         if (oexp) {
190                 exp = AllocExp(NULL);
191                 LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
192                 dassert_exp(exp, exp->ex_Decl == NULL);
193
194                 switch(oexp->ex_Flags & (EXF_COMPOUND|EXF_UNARY|EXF_BINARY)) {
195                 case EXF_COMPOUND:
196                         dassert_exp(oexp, oexp->ex_Rhs == NULL);
197                         if (oexp->ex_Lhs) {
198                                 Exp **pscan;
199                                 Exp *oscan;
200
201                                 pscan = &exp->ex_Lhs;
202                                 for (oscan = oexp->ex_Lhs;
203                                      oscan;
204                                      oscan = oscan->ex_Next) {
205                                         *pscan = DupExp(sg, oscan);
206                                         pscan = &(*pscan)->ex_Next;
207                                 }
208                         }
209                         break;
210                 case EXF_UNARY:
211                         /*
212                          * Duplicate a unary expression.  We do NOT duplicate
213                          * alias substitutions, that creates havoc.
214                          *
215                          * WARNING: Casts may store the original typeof
216                          * expression in ex_Rhs.
217                          */
218                         dassert_exp(oexp, oexp->ex_Lhs);
219                         if (oexp->ex_Flags & EXF_ALIAS)
220                                 exp->ex_Lhs = NULL;
221                         else
222                                 exp->ex_Lhs = DupExp(sg, oexp->ex_Lhs);
223
224                         if (oexp->ex_Token == TOK_CAST)
225                                 exp->ex_Rhs = DupExp(sg, oexp->ex_Rhs);
226                         else
227                                 dassert_exp(oexp, oexp->ex_Rhs == NULL);
228                         break;
229                 case EXF_BINARY:
230                         dassert_exp(oexp, oexp->ex_Lhs);
231                         dassert_exp(oexp, oexp->ex_Rhs);
232                         exp->ex_Lhs = DupExp(sg, oexp->ex_Lhs);
233                         exp->ex_Rhs = DupExp(sg, oexp->ex_Rhs);
234                         break;
235                 default:
236                         if (oexp->ex_Flags & (EXF_COMPOUND |
237                                               EXF_UNARY |
238                                               EXF_BINARY)) {
239                                 dassert_exp(oexp, 0);
240                         }
241                         dassert_exp(oexp, oexp->ex_Lhs == NULL);
242                         dassert_exp(oexp, oexp->ex_Rhs == NULL);
243                         break;
244                 }
245                 exp->ex_Prec = oexp->ex_Prec;
246                 exp->ex_Flags = oexp->ex_Flags;
247                 exp->ex_Flags2 = oexp->ex_Flags2;
248
249                 exp->ex_Flags &= ~(EXF_DUPEXP | EXF_RESOLVED | EXF_RESOLVING |
250                                    EXF_TMPRESOLVED);
251
252                 /*
253                  * NOTE!  Special case!  ex_Decl is only non-NULL when we do
254                  * a TypeToQualType() and have to dup an expression
255                  * post-resolve.  sg will be NULL in this case.
256                  *
257                  * XXX DupExp optimization invalidates this test, don't assert.
258                  * XXX add EXF_PARSE_DECL
259                  */
260 #if 0
261                 dassert_exp(exp, oexp->ex_Decl == NULL || sg == NULL);
262 #endif
263                 exp->ex_Decl = oexp->ex_Decl;
264                 exp->u = oexp->u;
265                 if (oexp->ex_Id)
266                         exp->ex_Id = StrTableDup(oexp->ex_Id);
267                 if (oexp->ex_ArgId)
268                         exp->ex_ArgId = StrTableDup(oexp->ex_ArgId);
269                 exp->ex_Token = oexp->ex_Token;
270
271                 /*
272                  * The type may be left over from the original resolution of
273                  * the expression prior to duplication.  We can inherit some
274                  * of these, but otherwise leave ex_Type NULL and re-resolve
275                  * it.
276                  */
277                 if ((oexp->ex_Flags & (EXF_PARSE_TYPE | EXF_RET_TYPE)) &&
278                     oexp->ex_Type) {
279                         exp->ex_Type = DupType(NULL, oexp->ex_Type);
280                 }
281
282                 if (exp->ex_Token == TOK_INLINE_CALL) {
283                         exp->ex_AuxStmt =
284                                 DupStmt(sg, NULL, oexp->ex_AuxStmt);
285                 } else {
286                         exp->ex_AuxExp = oexp->ex_AuxExp;       /* union */
287                 }
288         } else {
289                 exp = NULL;
290         }
291         return(exp);
292 }
293
294 void
295 ExpPrintError(Exp *exp, int type)
296 {
297         LexPrintRef(&exp->ex_LexRef, type);
298 }