From bc271d8a02b47a5c9a02f58ffdc09303df226d7f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 16:52:49 +0900 Subject: [PATCH] Add tempop_visit_all Works the same as def_visit_all, but for temp operands. --- tools/qfcc/include/statements.h | 3 ++ tools/qfcc/source/statements.c | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index eeb3bfdbf..e0e3dca98 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -117,7 +117,10 @@ const char *optype_str (op_type_e type) __attribute__((const)); operand_t *def_operand (struct def_s *def, struct type_s *type); operand_t *value_operand (struct ex_value_s *value); +int tempop_overlap (tempop_t *t1, tempop_t *t2); operand_t *temp_operand (struct type_s *type); +int tempop_visit_all (tempop_t *tempop, int overlap, + int (*visit) (tempop_t *, void *), void *data); operand_t *alias_operand (etype_t type, operand_t *op); void free_operand (operand_t *op); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e0500aab6..d476aeeaf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -334,6 +334,55 @@ temp_operand (type_t *type) return op; } +int +tempop_overlap (tempop_t *t1, tempop_t *t2) +{ + int offs1 = t1->offset; + int offs2 = t2->offset; + int size1 = type_size (t1->type); + int size2 = type_size (t2->type); + + if (offs1 <= offs2 && offs1 + size1 >= offs2 + size2) + return 2; // t1 fully overlaps t2 + if (offs1 < offs2 + size2 && offs2 < offs1 + size1) + return 1; // t1 and t2 at least partially overlap + return 0; +} + +int +tempop_visit_all (tempop_t *tempop, int overlap, + int (*visit) (tempop_t *, void *), void *data) +{ + tempop_t *start_tempop = tempop; + operand_t *top; + int ret; + + if ((ret = visit (tempop, data))) + return ret; + if (tempop->alias) { + top = tempop->alias; + if (top->op_type != op_temp) { + internal_error (0, "temp alias of non-temp operand"); + } + tempop = &top->o.tempop; + if ((ret = visit (tempop, data))) + return ret; + } + for (top = tempop->alias_ops; top; top = top->next) { + if (top->op_type != op_temp) { + internal_error (0, "temp alias of non-temp operand"); + } + tempop = &top->o.tempop; + if (tempop == start_tempop) + continue; + if (overlap && tempop_overlap (tempop, start_tempop) < overlap) + continue; + if ((ret = visit (tempop, data))) + return ret; + } + return 0; +} + operand_t * alias_operand (etype_t type, operand_t *op) {