15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28
29 #include "lib.h"
30 #include "allocate.h"
31 #include "token.h"
32 #include "parse.h"
33 #include "symbol.h"
34 #include "expression.h"
35
36 static struct expression * dup_expression(struct expression *expr)
37 {
38 struct expression *dup = alloc_expression(expr->pos, expr->type);
39 *dup = *expr;
40 return dup;
41 }
42
43 static struct statement * dup_statement(struct statement *stmt)
44 {
45 struct statement *dup = alloc_statement(stmt->pos, stmt->type);
46 *dup = *stmt;
47 return dup;
48 }
49
50 static struct symbol *copy_symbol(struct position pos, struct symbol *sym)
51 {
52 if (!sym)
53 return sym;
54 if (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN | MOD_TOPLEVEL | MOD_INLINE))
55 return sym;
161 *expr->cast_type = *sym;
162 break;
163 }
164 case EXPR_FORCE_CAST:
165 case EXPR_IMPLIED_CAST:
166 case EXPR_SIZEOF:
167 case EXPR_PTRSIZEOF:
168 case EXPR_ALIGNOF: {
169 struct expression *cast = copy_expression(expr->cast_expression);
170 if (cast == expr->cast_expression)
171 break;
172 expr = dup_expression(expr);
173 expr->cast_expression = cast;
174 break;
175 }
176
177 /* Conditional expression */
178 case EXPR_SELECT:
179 case EXPR_CONDITIONAL: {
180 struct expression *cond = copy_expression(expr->conditional);
181 struct expression *true = copy_expression(expr->cond_true);
182 struct expression *false = copy_expression(expr->cond_false);
183 if (cond == expr->conditional && true == expr->cond_true && false == expr->cond_false)
184 break;
185 expr = dup_expression(expr);
186 expr->conditional = cond;
187 expr->cond_true = true;
188 expr->cond_false = false;
189 break;
190 }
191
192 /* Statement expression */
193 case EXPR_STATEMENT: {
194 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
195 copy_statement(expr->statement, stmt);
196 expr = dup_expression(expr);
197 expr->statement = stmt;
198 break;
199 }
200
201 /* Call expression */
202 case EXPR_CALL: {
203 struct expression *fn = copy_expression(expr->fn);
204 struct expression_list *list = expr->args;
205 struct expression *arg;
206
207 expr = dup_expression(expr);
208 expr->fn = fn;
254 expr->init_expr = val;
255 break;
256 }
257 case EXPR_OFFSETOF: {
258 struct expression *val = copy_expression(expr->down);
259 if (expr->op == '.') {
260 if (expr->down != val) {
261 expr = dup_expression(expr);
262 expr->down = val;
263 }
264 } else {
265 struct expression *idx = copy_expression(expr->index);
266 if (expr->down != val || expr->index != idx) {
267 expr = dup_expression(expr);
268 expr->down = val;
269 expr->index = idx;
270 }
271 }
272 break;
273 }
274 default:
275 warning(expr->pos, "trying to copy expression type %d", expr->type);
276 }
277 return expr;
278 }
279
280 static struct expression_list *copy_asm_constraints(struct expression_list *in)
281 {
282 struct expression_list *out = NULL;
283 struct expression *expr;
284 int state = 0;
285
286 FOR_EACH_PTR(in, expr) {
287 switch (state) {
288 case 0: /* identifier */
289 case 1: /* constraint */
290 state++;
291 add_expression(&out, expr);
292 continue;
293 case 2: /* expression */
294 state = 0;
295 add_expression(&out, copy_expression(expr));
296 continue;
297 }
298 } END_FOR_EACH_PTR(expr);
299 return out;
300 }
301
302 static void set_replace(struct symbol *old, struct symbol *new)
303 {
304 new->replace = old;
305 old->replace = new;
306 }
307
308 static void unset_replace(struct symbol *sym)
309 {
310 struct symbol *r = sym->replace;
311 if (!r) {
312 warning(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
313 return;
314 }
315 r->replace = NULL;
316 sym->replace = NULL;
317 }
352 stmt = dup_statement(stmt);
353 stmt->expression = expr;
354 break;
355 }
356 case STMT_RANGE: {
357 struct expression *expr = copy_expression(stmt->range_expression);
358 if (expr == stmt->expression)
359 break;
360 stmt = dup_statement(stmt);
361 stmt->range_expression = expr;
362 break;
363 }
364 case STMT_COMPOUND: {
365 struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
366 copy_statement(stmt, new);
367 stmt = new;
368 break;
369 }
370 case STMT_IF: {
371 struct expression *cond = stmt->if_conditional;
372 struct statement *true = stmt->if_true;
373 struct statement *false = stmt->if_false;
374
375 cond = copy_expression(cond);
376 true = copy_one_statement(true);
377 false = copy_one_statement(false);
378 if (stmt->if_conditional == cond &&
379 stmt->if_true == true &&
380 stmt->if_false == false)
381 break;
382 stmt = dup_statement(stmt);
383 stmt->if_conditional = cond;
384 stmt->if_true = true;
385 stmt->if_false = false;
386 break;
387 }
388 case STMT_RETURN: {
389 struct expression *retval = copy_expression(stmt->ret_value);
390 struct symbol *sym = copy_symbol(stmt->pos, stmt->ret_target);
391
392 stmt = dup_statement(stmt);
393 stmt->ret_value = retval;
394 stmt->ret_target = sym;
395 break;
396 }
397 case STMT_CASE: {
398 stmt = dup_statement(stmt);
399 stmt->case_label = copy_symbol(stmt->pos, stmt->case_label);
400 stmt->case_label->stmt = stmt;
401 stmt->case_expression = copy_expression(stmt->case_expression);
402 stmt->case_to = copy_expression(stmt->case_to);
403 stmt->case_statement = copy_one_statement(stmt->case_statement);
404 break;
405 }
451 stmt->asm_outputs = copy_asm_constraints(stmt->asm_outputs);
452 /* no need to dup "clobbers", since they are all constant strings */
453 break;
454 }
455 default:
456 warning(stmt->pos, "trying to copy statement type %d", stmt->type);
457 break;
458 }
459 return stmt;
460 }
461
462 /*
463 * Copy a statement tree from 'src' to 'dst', where both
464 * source and destination are of type STMT_COMPOUND.
465 *
466 * We do this for the tree-level inliner.
467 *
468 * This doesn't do the symbol replacement right: it's not
469 * re-entrant.
470 */
471 void copy_statement(struct statement *src, struct statement *dst)
472 {
473 struct statement *stmt;
474
475 FOR_EACH_PTR(src->stmts, stmt) {
476 add_statement(&dst->stmts, copy_one_statement(stmt));
477 } END_FOR_EACH_PTR(stmt);
478 dst->args = copy_one_statement(src->args);
479 dst->ret = copy_symbol(src->pos, src->ret);
480 dst->inline_fn = src->inline_fn;
481 }
482
483 static struct symbol *create_copy_symbol(struct symbol *orig)
484 {
485 struct symbol *sym = orig;
486 if (orig) {
487 sym = alloc_symbol(orig->pos, orig->type);
488 *sym = *orig;
489 sym->bb_target = NULL;
490 sym->pseudo = NULL;
491 set_replace(orig, sym);
|
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28
29 #include "lib.h"
30 #include "allocate.h"
31 #include "token.h"
32 #include "parse.h"
33 #include "symbol.h"
34 #include "expression.h"
35 #include "evaluate.h"
36
37 static void copy_statement(struct statement *src, struct statement *dst);
38
39 static struct expression * dup_expression(struct expression *expr)
40 {
41 struct expression *dup = alloc_expression(expr->pos, expr->type);
42 *dup = *expr;
43 return dup;
44 }
45
46 static struct statement * dup_statement(struct statement *stmt)
47 {
48 struct statement *dup = alloc_statement(stmt->pos, stmt->type);
49 *dup = *stmt;
50 return dup;
51 }
52
53 static struct symbol *copy_symbol(struct position pos, struct symbol *sym)
54 {
55 if (!sym)
56 return sym;
57 if (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN | MOD_TOPLEVEL | MOD_INLINE))
58 return sym;
164 *expr->cast_type = *sym;
165 break;
166 }
167 case EXPR_FORCE_CAST:
168 case EXPR_IMPLIED_CAST:
169 case EXPR_SIZEOF:
170 case EXPR_PTRSIZEOF:
171 case EXPR_ALIGNOF: {
172 struct expression *cast = copy_expression(expr->cast_expression);
173 if (cast == expr->cast_expression)
174 break;
175 expr = dup_expression(expr);
176 expr->cast_expression = cast;
177 break;
178 }
179
180 /* Conditional expression */
181 case EXPR_SELECT:
182 case EXPR_CONDITIONAL: {
183 struct expression *cond = copy_expression(expr->conditional);
184 struct expression *valt = copy_expression(expr->cond_true);
185 struct expression *valf = copy_expression(expr->cond_false);
186 if (cond == expr->conditional && valt == expr->cond_true && valf == expr->cond_false)
187 break;
188 expr = dup_expression(expr);
189 expr->conditional = cond;
190 expr->cond_true = valt;
191 expr->cond_false = valf;
192 break;
193 }
194
195 /* Statement expression */
196 case EXPR_STATEMENT: {
197 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
198 copy_statement(expr->statement, stmt);
199 expr = dup_expression(expr);
200 expr->statement = stmt;
201 break;
202 }
203
204 /* Call expression */
205 case EXPR_CALL: {
206 struct expression *fn = copy_expression(expr->fn);
207 struct expression_list *list = expr->args;
208 struct expression *arg;
209
210 expr = dup_expression(expr);
211 expr->fn = fn;
257 expr->init_expr = val;
258 break;
259 }
260 case EXPR_OFFSETOF: {
261 struct expression *val = copy_expression(expr->down);
262 if (expr->op == '.') {
263 if (expr->down != val) {
264 expr = dup_expression(expr);
265 expr->down = val;
266 }
267 } else {
268 struct expression *idx = copy_expression(expr->index);
269 if (expr->down != val || expr->index != idx) {
270 expr = dup_expression(expr);
271 expr->down = val;
272 expr->index = idx;
273 }
274 }
275 break;
276 }
277 case EXPR_ASM_OPERAND: {
278 expr = dup_expression(expr);
279 expr->constraint = copy_expression(expr->constraint);
280 expr->expr = copy_expression(expr->expr);
281 break;
282 }
283 default:
284 warning(expr->pos, "trying to copy expression type %d", expr->type);
285 }
286 return expr;
287 }
288
289 static struct expression_list *copy_asm_constraints(struct expression_list *in)
290 {
291 struct expression_list *out = NULL;
292 struct expression *expr;
293
294 FOR_EACH_PTR(in, expr) {
295 add_expression(&out, copy_expression(expr));
296 } END_FOR_EACH_PTR(expr);
297 return out;
298 }
299
300 static void set_replace(struct symbol *old, struct symbol *new)
301 {
302 new->replace = old;
303 old->replace = new;
304 }
305
306 static void unset_replace(struct symbol *sym)
307 {
308 struct symbol *r = sym->replace;
309 if (!r) {
310 warning(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
311 return;
312 }
313 r->replace = NULL;
314 sym->replace = NULL;
315 }
350 stmt = dup_statement(stmt);
351 stmt->expression = expr;
352 break;
353 }
354 case STMT_RANGE: {
355 struct expression *expr = copy_expression(stmt->range_expression);
356 if (expr == stmt->expression)
357 break;
358 stmt = dup_statement(stmt);
359 stmt->range_expression = expr;
360 break;
361 }
362 case STMT_COMPOUND: {
363 struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
364 copy_statement(stmt, new);
365 stmt = new;
366 break;
367 }
368 case STMT_IF: {
369 struct expression *cond = stmt->if_conditional;
370 struct statement *valt = stmt->if_true;
371 struct statement *valf = stmt->if_false;
372
373 cond = copy_expression(cond);
374 valt = copy_one_statement(valt);
375 valf = copy_one_statement(valf);
376 if (stmt->if_conditional == cond &&
377 stmt->if_true == valt &&
378 stmt->if_false == valf)
379 break;
380 stmt = dup_statement(stmt);
381 stmt->if_conditional = cond;
382 stmt->if_true = valt;
383 stmt->if_false = valf;
384 break;
385 }
386 case STMT_RETURN: {
387 struct expression *retval = copy_expression(stmt->ret_value);
388 struct symbol *sym = copy_symbol(stmt->pos, stmt->ret_target);
389
390 stmt = dup_statement(stmt);
391 stmt->ret_value = retval;
392 stmt->ret_target = sym;
393 break;
394 }
395 case STMT_CASE: {
396 stmt = dup_statement(stmt);
397 stmt->case_label = copy_symbol(stmt->pos, stmt->case_label);
398 stmt->case_label->stmt = stmt;
399 stmt->case_expression = copy_expression(stmt->case_expression);
400 stmt->case_to = copy_expression(stmt->case_to);
401 stmt->case_statement = copy_one_statement(stmt->case_statement);
402 break;
403 }
449 stmt->asm_outputs = copy_asm_constraints(stmt->asm_outputs);
450 /* no need to dup "clobbers", since they are all constant strings */
451 break;
452 }
453 default:
454 warning(stmt->pos, "trying to copy statement type %d", stmt->type);
455 break;
456 }
457 return stmt;
458 }
459
460 /*
461 * Copy a statement tree from 'src' to 'dst', where both
462 * source and destination are of type STMT_COMPOUND.
463 *
464 * We do this for the tree-level inliner.
465 *
466 * This doesn't do the symbol replacement right: it's not
467 * re-entrant.
468 */
469 static void copy_statement(struct statement *src, struct statement *dst)
470 {
471 struct statement *stmt;
472
473 FOR_EACH_PTR(src->stmts, stmt) {
474 add_statement(&dst->stmts, copy_one_statement(stmt));
475 } END_FOR_EACH_PTR(stmt);
476 dst->args = copy_one_statement(src->args);
477 dst->ret = copy_symbol(src->pos, src->ret);
478 dst->inline_fn = src->inline_fn;
479 }
480
481 static struct symbol *create_copy_symbol(struct symbol *orig)
482 {
483 struct symbol *sym = orig;
484 if (orig) {
485 sym = alloc_symbol(orig->pos, orig->type);
486 *sym = *orig;
487 sym->bb_target = NULL;
488 sym->pseudo = NULL;
489 set_replace(orig, sym);
|