mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-19 07:51:08 +00:00
[qfcc] Use non-invasive lists for block expressions
They will be used for other expression types too. Invasive lists make it difficult to do expression dags.
This commit is contained in:
parent
345eba45d5
commit
cc67e69923
11 changed files with 200 additions and 106 deletions
|
@ -93,12 +93,25 @@ typedef struct element_chain_s {
|
|||
element_t **tail;
|
||||
} element_chain_t;
|
||||
|
||||
typedef struct {
|
||||
struct expr_s *head; ///< the first expression in the block
|
||||
struct expr_s **tail; ///< last expression in the block, for appending
|
||||
struct expr_s *result; ///< the result of this block if non-void
|
||||
int is_call; ///< this block exprssion forms a function call
|
||||
void *return_addr;///< who allocated this
|
||||
typedef struct ex_listitem_s {
|
||||
struct ex_listitem_s *next;
|
||||
struct expr_s *expr;
|
||||
} ex_listitem_t;
|
||||
|
||||
typedef struct ex_list_s {
|
||||
ex_listitem_t *head;
|
||||
ex_listitem_t **tail;
|
||||
} ex_list_t;
|
||||
|
||||
typedef union {
|
||||
ex_list_t list;
|
||||
struct {
|
||||
ex_listitem_t *head;
|
||||
ex_listitem_t **tail;
|
||||
struct expr_s *result; ///< the result of this block if non-void
|
||||
int is_call; ///< this block exprssion forms a function call
|
||||
void *return_addr;///< who allocated this
|
||||
};
|
||||
} ex_block_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -304,6 +317,7 @@ typedef struct expr_s {
|
|||
ex_labelref_t labelref; ///< label reference expression (&)
|
||||
ex_state_t state; ///< state expression
|
||||
ex_bool_t boolean; ///< boolean logic expression
|
||||
ex_list_t list; ///< noninvasive expression list
|
||||
ex_block_t block; ///< statement block expression
|
||||
ex_expr_t expr; ///< binary or unary expression
|
||||
struct def_s *def; ///< def reference expression
|
||||
|
@ -364,6 +378,11 @@ struct type_s *get_type (expr_t *e);
|
|||
*/
|
||||
etype_t extract_type (expr_t *e);
|
||||
|
||||
ex_listitem_t *new_listitem (expr_t *e);
|
||||
int list_count (ex_list_t *list) __attribute__((pure));
|
||||
void list_scatter (ex_list_t *list, expr_t **exprs);
|
||||
void list_gather (ex_list_t *dst, expr_t **exprs, int count);
|
||||
|
||||
/** Create a new expression node.
|
||||
|
||||
Sets the source file and line number information. The expression node is
|
||||
|
|
|
@ -66,5 +66,6 @@ EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t)
|
|||
EX_EXPR(swizzle) ///< vector swizzle operation (::ex_swizzle_t)
|
||||
EX_EXPR(extend) ///< vector extend operation (::ex_extend_t)
|
||||
EX_EXPR(multivec) ///< geometric algebra multivector (::ex_multivec_t)
|
||||
EX_EXPR(list) ///< non-invasive list of expressions (::ex_list_t)
|
||||
|
||||
///@}
|
||||
|
|
|
@ -175,7 +175,8 @@ sblock_t *statement_get_target (statement_t *s) __attribute__((pure));
|
|||
sblock_t **statement_get_targetlist (statement_t *s);
|
||||
void sblock_add_statement (sblock_t *sblock, statement_t *statement);
|
||||
sblock_t *make_statements (struct expr_s *expr);
|
||||
sblock_t *statement_slist (sblock_t *sblock, struct expr_s *e);
|
||||
struct ex_list_s;
|
||||
sblock_t *statement_slist (sblock_t *sblock, struct ex_list_s *slist);
|
||||
void statements_count_temps (sblock_t *sblock);
|
||||
|
||||
void print_operand (operand_t *op);
|
||||
|
|
|
@ -547,7 +547,7 @@ static int
|
|||
num_elements (expr_t *e)
|
||||
{
|
||||
int count = 0;
|
||||
for (e = e->block.head; e; e = e->next) {
|
||||
for (auto ele = e->compound.head; ele; ele = ele->next) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
|
|
|
@ -221,21 +221,32 @@ static void
|
|||
print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||
{
|
||||
int indent = level * 2 + 2;
|
||||
int i;
|
||||
expr_t *se;
|
||||
int num_exprs = list_count (&e->block.list);
|
||||
expr_t *exprs[num_exprs + 1];
|
||||
|
||||
list_scatter (&e->block.list, exprs);
|
||||
exprs[num_exprs] = 0;
|
||||
|
||||
dasprintf (dstr, "%*se_%p [shape=none,label=<\n", indent, "", e);
|
||||
dasprintf (dstr, "%*s<table border=\"0\" cellborder=\"1\" "
|
||||
"cellspacing=\"0\">\n", indent + 2, "");
|
||||
dasprintf (dstr, "%*s<tr><td colspan=\"2\"><block>(%d)%s</td>"
|
||||
"</tr>\n", indent + 4, "", e->line,
|
||||
dasprintf (dstr, "%*s<tr><td colspan=\"%d\"><block>(%d)%s</td>"
|
||||
"</tr>\n", indent + 4, "", num_exprs, e->line,
|
||||
e->block.is_call ? "c" : "");
|
||||
if (e->block.result)
|
||||
dasprintf (dstr, "%*s<tr><td colspan=\"2\" port=\"result\">=</td>"
|
||||
"</tr>\n", indent + 4, "");
|
||||
for (se = e->block.head, i = 0; se; se = se->next, i++)
|
||||
dasprintf (dstr, "%*s<tr><td>%d</td><td port=\"b%d\">%s</td></tr>\n",
|
||||
indent + 4, "", se->line, i, expr_names[se->type]);
|
||||
dasprintf (dstr, "%*s<tr><td colspan=\"%d\" port=\"result\">=</td>"
|
||||
"</tr>\n", indent + 4, "", num_exprs);
|
||||
dasprintf (dstr, "%*s<tr>\n", indent + 4, "");
|
||||
for (int i = 0; i < num_exprs; i++) {
|
||||
dasprintf (dstr, "%*s<td>%d</td>\n", indent + 8, "", exprs[i]->line);
|
||||
}
|
||||
dasprintf (dstr, "%*s</tr>\n", indent + 4, "");
|
||||
dasprintf (dstr, "%*s<tr>\n", indent + 4, "");
|
||||
for (int i = 0; i < num_exprs; i++) {
|
||||
dasprintf (dstr, "%*s<td port=\"b%d\">%s</td>\n", indent + 8, "",
|
||||
i, expr_names[exprs[i]->type]);
|
||||
}
|
||||
dasprintf (dstr, "%*s</tr>\n", indent + 4, "");
|
||||
dasprintf (dstr, "%*s</table>\n", indent + 2, "");
|
||||
dasprintf (dstr, "%*s>];\n", indent, "");
|
||||
|
||||
|
@ -244,12 +255,10 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
|||
dasprintf (dstr, "%*se_%p:result -> e_%p;\n", indent, "", e,
|
||||
e->block.result);
|
||||
}
|
||||
if (e->next)
|
||||
next = e->next;
|
||||
for (se = e->block.head, i = 0; se; se = se->next, i++) {
|
||||
_print_expr (dstr, se, level + 1, id, next);
|
||||
for (int i = 0; i < num_exprs; i++) {
|
||||
_print_expr (dstr, exprs[i], level + 1, id, exprs[i + 1]);
|
||||
dasprintf (dstr, "%*se_%p:b%d -> e_%p;\n", indent, "", e,
|
||||
i, se);
|
||||
i, exprs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -245,7 +245,9 @@ evaluate_constexpr (expr_t *e)
|
|||
sblock_t sblock = {
|
||||
.tail = &sblock.statements,
|
||||
};
|
||||
auto sb = statement_slist (&sblock, new_return_expr (e));
|
||||
ex_listitem_t return_expr = { .expr = new_return_expr (e) };
|
||||
ex_list_t return_st = { .head = &return_expr, .tail = &return_expr.next };
|
||||
auto sb = statement_slist (&sblock, &return_st);
|
||||
if (sblock.next != sb && sb->statements) {
|
||||
internal_error (e, "statement_slist did too much");
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "tools/qfcc/source/qc-parse.h"
|
||||
|
||||
ALLOC_STATE (expr_t, exprs);
|
||||
ALLOC_STATE (ex_listitem_t, listitems);
|
||||
|
||||
expr_t *
|
||||
convert_name (expr_t *e)
|
||||
|
@ -201,6 +202,11 @@ get_type (expr_t *e)
|
|||
return e->extend.type;
|
||||
case ex_multivec:
|
||||
return e->multivec.type;
|
||||
case ex_list:
|
||||
if (e->list.head) {
|
||||
return get_type ((*e->list.tail)->expr);
|
||||
}
|
||||
return 0;
|
||||
case ex_count:
|
||||
internal_error (e, "invalid expression");
|
||||
}
|
||||
|
@ -258,6 +264,46 @@ new_expr (void)
|
|||
return e;
|
||||
}
|
||||
|
||||
ex_listitem_t *
|
||||
new_listitem (expr_t *e)
|
||||
{
|
||||
ex_listitem_t *li;
|
||||
ALLOC (16384, ex_listitem_t, listitems, li);
|
||||
li->expr = e;
|
||||
return li;
|
||||
}
|
||||
|
||||
int
|
||||
list_count (ex_list_t *list)
|
||||
{
|
||||
int count = 0;
|
||||
for (auto li = list->head; li; li = li->next) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
list_scatter (ex_list_t *list, expr_t **exprs)
|
||||
{
|
||||
for (auto li = list->head; li; li = li->next) {
|
||||
*exprs++ = li->expr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
list_gather (ex_list_t *list, expr_t **exprs, int count)
|
||||
{
|
||||
if (!list->tail) {
|
||||
list->tail = &list->head;
|
||||
}
|
||||
while (count-- > 0) {
|
||||
auto li = new_listitem (*exprs++);
|
||||
*list->tail = li;
|
||||
list->tail = &li->next;
|
||||
}
|
||||
}
|
||||
|
||||
expr_t *
|
||||
copy_expr (expr_t *e)
|
||||
{
|
||||
|
@ -318,12 +364,12 @@ copy_expr (expr_t *e)
|
|||
n->block.head = 0;
|
||||
n->block.tail = &n->block.head;
|
||||
n->block.result = 0;
|
||||
for (t = e->block.head; t; t = t->next) {
|
||||
if (t == e->block.result) {
|
||||
n->block.result = copy_expr (t);
|
||||
for (auto t = e->block.head; t; t = t->next) {
|
||||
if (t->expr == e->block.result) {
|
||||
n->block.result = copy_expr (t->expr);
|
||||
append_expr (n, n->block.result);
|
||||
} else {
|
||||
append_expr (n, copy_expr (t));
|
||||
append_expr (n, copy_expr (t->expr));
|
||||
}
|
||||
}
|
||||
if (e->block.result && !n->block.result)
|
||||
|
@ -453,6 +499,8 @@ copy_expr (expr_t *e)
|
|||
t = t->next;
|
||||
}
|
||||
return n;
|
||||
case ex_list:
|
||||
break;//FIXME
|
||||
case ex_count:
|
||||
break;
|
||||
}
|
||||
|
@ -1434,8 +1482,9 @@ append_expr (expr_t *block, expr_t *e)
|
|||
if (e->next)
|
||||
internal_error (e, "append_expr: expr loop detected");
|
||||
|
||||
*block->block.tail = e;
|
||||
block->block.tail = &e->next;
|
||||
auto li = new_listitem (e);
|
||||
*block->block.tail = li;
|
||||
block->block.tail = &li->next;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
@ -1452,11 +1501,12 @@ prepend_expr (expr_t *block, expr_t *e)
|
|||
if (e->next)
|
||||
internal_error (e, "append_expr: expr loop detected");
|
||||
|
||||
e->next = block->block.head;
|
||||
block->block.head = e;
|
||||
auto li = new_listitem (e);
|
||||
li->next = block->block.head;
|
||||
block->block.head = li;
|
||||
|
||||
if (block->block.tail == &block->block.head) {
|
||||
block->block.tail = &e->next;
|
||||
block->block.tail = &li->next;
|
||||
}
|
||||
|
||||
return block;
|
||||
|
@ -1674,8 +1724,9 @@ has_function_call (expr_t *e)
|
|||
case ex_block:
|
||||
if (e->block.is_call)
|
||||
return 1;
|
||||
for (e = e->block.head; e; e = e->next)
|
||||
if (has_function_call (e))
|
||||
case ex_list:
|
||||
for (auto li = e->block.head; li; li = li->next)
|
||||
if (has_function_call (li->expr))
|
||||
return 1;
|
||||
return 0;
|
||||
case ex_expr:
|
||||
|
@ -1831,6 +1882,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_adjstk:
|
||||
case ex_with:
|
||||
case ex_args:
|
||||
case ex_list:
|
||||
internal_error (e, "unexpected expression type");
|
||||
case ex_uexpr:
|
||||
if (e->expr.op == '-') {
|
||||
|
@ -1944,6 +1996,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_adjstk:
|
||||
case ex_with:
|
||||
case ex_args:
|
||||
case ex_list:
|
||||
internal_error (e, "unexpected expression type");
|
||||
case ex_bool:
|
||||
return new_bool_expr (e->boolean.false_list,
|
||||
|
@ -2037,6 +2090,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_adjstk:
|
||||
case ex_with:
|
||||
case ex_args:
|
||||
case ex_list:
|
||||
internal_error (e, "unexpected expression type");
|
||||
case ex_uexpr:
|
||||
if (e->expr.op == '~')
|
||||
|
|
|
@ -146,6 +146,7 @@ is_lvalue (const expr_t *expr)
|
|||
case ex_swizzle:
|
||||
case ex_extend:
|
||||
case ex_multivec:
|
||||
case ex_list:
|
||||
break;
|
||||
case ex_count:
|
||||
internal_error (expr, "invalid expression");
|
||||
|
|
|
@ -284,12 +284,7 @@ convert_bool (expr_t *e, int block)
|
|||
if (b->type == ex_error)
|
||||
return b;
|
||||
// insert the assignment into the boolean's block
|
||||
e->next = b->boolean.e->block.head;
|
||||
b->boolean.e->block.head = e;
|
||||
if (b->boolean.e->block.tail == &b->boolean.e->block.head) {
|
||||
// shouldn't happen, but just in case
|
||||
b->boolean.e->block.tail = &e->next;
|
||||
}
|
||||
prepend_expr (b->boolean.e, e);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
@ -321,8 +316,8 @@ convert_bool (expr_t *e, int block)
|
|||
b = new_block_expr ();
|
||||
append_expr (b, branch_expr (NE, e, 0));
|
||||
append_expr (b, goto_expr (0));
|
||||
e = new_bool_expr (make_list (b->block.head),
|
||||
make_list (b->block.head->next), b);
|
||||
e = new_bool_expr (make_list (b->block.head->expr),
|
||||
make_list (b->block.head->next->expr), b);
|
||||
}
|
||||
}
|
||||
if (block && e->boolean.e->type != ex_block) {
|
||||
|
|
|
@ -1870,8 +1870,8 @@ identifier_list
|
|||
classdecl
|
||||
: CLASS identifier_list ';'
|
||||
{
|
||||
expr_t *e;
|
||||
for (e = $2->block.head; e; e = e->next) {
|
||||
for (auto li = $2->block.head; li; li = li->next) {
|
||||
auto e = li->expr;
|
||||
get_class (e->symbol, 1);
|
||||
if (!e->symbol->table)
|
||||
symtab_addsymbol (current_symtab, e->symbol);
|
||||
|
|
|
@ -725,6 +725,7 @@ static sblock_t *statement_subexpr (sblock_t *sblock, expr_t *e,
|
|||
operand_t **op);
|
||||
static sblock_t *expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op);
|
||||
static sblock_t *expr_def (sblock_t *sblock, expr_t *e, operand_t **op);
|
||||
static sblock_t *statement_single (sblock_t *sblock, expr_t *e);
|
||||
|
||||
static sblock_t *
|
||||
expr_address (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
|
@ -1056,7 +1057,7 @@ vector_call (sblock_t *sblock, expr_t *earg, expr_t *param, int ind,
|
|||
param = new_param_expr (get_type (earg), ind);
|
||||
a->line = earg->line;
|
||||
a->file = earg->file;
|
||||
sblock = statement_slist (sblock, a);
|
||||
sblock = statement_single (sblock, a);
|
||||
}
|
||||
sblock = statement_subexpr (sblock, param, op);
|
||||
return sblock;
|
||||
|
@ -1111,7 +1112,7 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op)
|
|||
expr_t *mov = assign_expr (param, a);
|
||||
mov->line = a->line;
|
||||
mov->file = a->file;
|
||||
sblock = statement_slist (sblock, mov);
|
||||
sblock = statement_single (sblock, mov);
|
||||
} else {
|
||||
operand_t *p = 0;
|
||||
sblock = statement_subexpr (sblock, param, &p);
|
||||
|
@ -1204,7 +1205,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op)
|
|||
}
|
||||
expr_t *assign = assign_expr (def_expr, a);
|
||||
expr_file_line (assign, call);
|
||||
sblock = statement_slist (sblock, assign);
|
||||
sblock = statement_single (sblock, assign);
|
||||
}
|
||||
|
||||
// The call both uses and kills the arguments: use is obvious, but kill
|
||||
|
@ -1232,7 +1233,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op)
|
|||
count = new_short_expr (num_params);
|
||||
assign = assign_expr (args_count, count);
|
||||
expr_file_line (assign, call);
|
||||
sblock = statement_slist (sblock, assign);
|
||||
sblock = statement_single (sblock, assign);
|
||||
|
||||
if (args_params) {
|
||||
list = address_expr (args_params, &type_param);
|
||||
|
@ -1242,7 +1243,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op)
|
|||
expr_file_line (list, call);
|
||||
assign = assign_expr (args_list, list);
|
||||
expr_file_line (assign, call);
|
||||
sblock = statement_slist (sblock, assign);
|
||||
sblock = statement_single (sblock, assign);
|
||||
}
|
||||
statement_t *s = new_statement (st_func, "call", call);
|
||||
sblock = statement_subexpr (sblock, func, &s->opa);
|
||||
|
@ -1513,7 +1514,7 @@ statement_return (sblock_t *sblock, expr_t *e)
|
|||
operand_t *ret_op = def_operand (ret_ptr, &type_void, e);
|
||||
ret_ptr->reg = REG;
|
||||
expr_file_line (with, e);
|
||||
sblock = statement_slist (sblock, with);
|
||||
sblock = statement_single (sblock, with);
|
||||
sblock = statement_subexpr (sblock, call, &ret_op);
|
||||
}
|
||||
s->opa = short_operand (0, e);
|
||||
|
@ -1635,7 +1636,7 @@ expr_block (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
{
|
||||
if (!e->block.result)
|
||||
internal_error (e, "block sub-expression without result");
|
||||
sblock = statement_slist (sblock, e->block.head);
|
||||
sblock = statement_slist (sblock, &e->block.list);
|
||||
sblock = statement_subexpr (sblock, e->block.result, op);
|
||||
return sblock;
|
||||
}
|
||||
|
@ -1932,7 +1933,7 @@ statement_copy_elements (sblock_t **sblock, expr_t *dst, expr_t *src, int base)
|
|||
expr_t *dst_ele = new_offset_alias_expr (src_type, dst,
|
||||
size * (index + base));
|
||||
index += type_width (src_type);
|
||||
*sblock = statement_slist (*sblock, assign_expr (dst_ele, e));
|
||||
*sblock = statement_single (*sblock, assign_expr (dst_ele, e));
|
||||
}
|
||||
}
|
||||
return index;
|
||||
|
@ -2094,10 +2095,8 @@ build_bool_block (expr_t *block, expr_t *e)
|
|||
break;
|
||||
case ex_block:
|
||||
if (!e->block.result) {
|
||||
expr_t *t;
|
||||
for (e = e->block.head; e; e = t) {
|
||||
t = e->next;
|
||||
build_bool_block (block, e);
|
||||
for (auto t = e->block.head; t; t = t->next) {
|
||||
build_bool_block (block, t->expr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2118,69 +2117,69 @@ is_goto_expr (expr_t *e)
|
|||
static int
|
||||
is_if_expr (expr_t *e)
|
||||
{
|
||||
return e && e->type == ex_branch && e->branch.type == pr_branch_ne;
|
||||
return e && e->type == ex_branch && e->branch.type != pr_branch_jump
|
||||
&& e->branch.type != pr_branch_call;;
|
||||
}
|
||||
|
||||
static int
|
||||
is_ifnot_expr (expr_t *e)
|
||||
is_label_expr (expr_t *e)
|
||||
{
|
||||
return e && e->type == ex_branch && e->branch.type == pr_branch_eq;
|
||||
return e && e->type == ex_label;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
statement_bool (sblock_t *sblock, expr_t *e)
|
||||
{
|
||||
expr_t **s;
|
||||
expr_t *l;
|
||||
expr_t *block = new_block_expr ();
|
||||
|
||||
build_bool_block (block, e);
|
||||
|
||||
s = &block->block.head;
|
||||
while (*s) {
|
||||
if (is_if_expr (*s) && is_goto_expr ((*s)->next)) {
|
||||
l = (*s)->branch.target;
|
||||
for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) {
|
||||
if (e == l) {
|
||||
int num_expr = list_count (&block->block.list);
|
||||
expr_t *exprs[num_expr + 1];
|
||||
list_scatter (&block->block.list, exprs);
|
||||
exprs[num_expr] = 0; // mark end of list
|
||||
expr_t **d = exprs;
|
||||
expr_t **s = exprs;
|
||||
while (s[0]) {
|
||||
if (is_if_expr (s[0]) && is_goto_expr (s[1])) {
|
||||
l = s[0]->branch.target;
|
||||
for (auto e = s + 2; is_label_expr (e[0]); e++) {
|
||||
if (e[0] == l) {
|
||||
l->label.used--;
|
||||
e = *s;
|
||||
e->branch.type = pr_branch_eq;
|
||||
e->branch.target = e->next->branch.target;
|
||||
e->next = e->next->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s = &(*s)->next;
|
||||
} else if (is_ifnot_expr (*s) && is_goto_expr ((*s)->next)) {
|
||||
l = (*s)->branch.target;
|
||||
for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) {
|
||||
if (e == l) {
|
||||
l->label.used--;
|
||||
e = *s;
|
||||
e->branch.type = pr_branch_ne;
|
||||
e->branch.target = e->next->branch.target;
|
||||
e->next = e->next->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s = &(*s)->next;
|
||||
} else if (is_goto_expr (*s)) {
|
||||
l = (*s)->branch.target;
|
||||
for (e = (*s)->next; e && e->type == ex_label; e = e->next) {
|
||||
if (e == l) {
|
||||
l->label.used--;
|
||||
*s = (*s)->next;
|
||||
// invert logic of if
|
||||
s[0]->branch.type ^= pr_branch_ne;
|
||||
// use goto's label in if
|
||||
s[0]->branch.target = s[1]->branch.target;
|
||||
l = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l)
|
||||
s = &(*s)->next;
|
||||
*d++ = *s++; // copy if
|
||||
if (!l) {
|
||||
s++; // skip over goto
|
||||
}
|
||||
} else if (is_goto_expr (*s)) {
|
||||
l = s[0]->branch.target;
|
||||
for (auto e = s + 1; is_label_expr (e[0]); e++) {
|
||||
if (e[0] == l) {
|
||||
l->label.used--;
|
||||
l = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l) {
|
||||
*d++ = *s++; // label survived, copy goto
|
||||
} else {
|
||||
s++; // skip over goto
|
||||
}
|
||||
} else {
|
||||
s = &(*s)->next;
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
sblock = statement_slist (sblock, block->block.head);
|
||||
block->block.list = (ex_list_t) {};
|
||||
list_gather (&block->block.list, exprs, d - exprs);
|
||||
sblock = statement_slist (sblock, &block->block.list);
|
||||
return sblock;
|
||||
}
|
||||
|
||||
|
@ -2212,11 +2211,11 @@ statement_block (sblock_t *sblock, expr_t *e)
|
|||
sblock->next = new_sblock ();
|
||||
sblock = sblock->next;
|
||||
}
|
||||
sblock = statement_slist (sblock, e->block.head);
|
||||
sblock = statement_slist (sblock, &e->block.list);
|
||||
if (e->block.is_call) {
|
||||
// for a fuction call, the call expresion is in only the result, not
|
||||
// the actual block
|
||||
sblock = statement_slist (sblock, e->block.result);
|
||||
sblock = statement_single (sblock, e->block.result);
|
||||
}
|
||||
return sblock;
|
||||
}
|
||||
|
@ -2282,8 +2281,8 @@ statement_nonexec (sblock_t *sblock, expr_t *e)
|
|||
return sblock;
|
||||
}
|
||||
|
||||
sblock_t *
|
||||
statement_slist (sblock_t *sblock, expr_t *e)
|
||||
static sblock_t *
|
||||
statement_single (sblock_t *sblock, expr_t *e)
|
||||
{
|
||||
static statement_f sfuncs[ex_count] = {
|
||||
[ex_error] = statement_ignore,
|
||||
|
@ -2307,10 +2306,19 @@ statement_slist (sblock_t *sblock, expr_t *e)
|
|||
[ex_with] = statement_with,
|
||||
};
|
||||
|
||||
for (/**/; e; e = e->next) {
|
||||
if (e->type >= ex_count || !sfuncs[e->type])
|
||||
internal_error (e, "bad expression type");
|
||||
sblock = sfuncs[e->type] (sblock, e);
|
||||
if (e->type >= ex_count || !sfuncs[e->type]) {
|
||||
internal_error (e, "bad expression type");
|
||||
}
|
||||
sblock = sfuncs[e->type] (sblock, e);
|
||||
return sblock;
|
||||
}
|
||||
|
||||
sblock_t *
|
||||
statement_slist (sblock_t *sblock, ex_list_t *slist)
|
||||
{
|
||||
|
||||
for (auto s = slist->head; s; s = s->next) {
|
||||
sblock = statement_single (sblock, s->expr);
|
||||
}
|
||||
return sblock;
|
||||
}
|
||||
|
@ -2657,7 +2665,11 @@ make_statements (expr_t *e)
|
|||
|
||||
if (options.block_dot.expr)
|
||||
dump_dot ("expr", e, dump_dot_expr);
|
||||
statement_slist (sblock, e);
|
||||
if (e->type != ex_block) {
|
||||
statement_single (sblock, e);
|
||||
} else {
|
||||
statement_slist (sblock, &e->block.list);
|
||||
}
|
||||
if (options.block_dot.initial)
|
||||
dump_dot ("initial", sblock, dump_dot_sblock);
|
||||
do {
|
||||
|
|
Loading…
Reference in a new issue