mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-06-01 17:12:15 +00:00
[qfcc] Give alias expressions their own type
While this was a pain to get working, that pain only went to prove the value of using proper "types" (even if only an enum) for different expression types: just finding all the places to edit was a chore, and easy to make mistakes (forgetting bits here and there). Strangely enough, this exposed a pile of *type* aliasing bugs (next commit).
This commit is contained in:
parent
420d55406f
commit
23c9a317f8
9 changed files with 118 additions and 81 deletions
|
@ -207,6 +207,12 @@ typedef struct ex_value_s {
|
||||||
} v;
|
} v;
|
||||||
} ex_value_t;
|
} ex_value_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct type_s *type; ///< type to view the expression
|
||||||
|
struct expr_s *expr; ///< the expression to alias
|
||||||
|
struct expr_s *offset; ///< offset for alias
|
||||||
|
} ex_alias_t;
|
||||||
|
|
||||||
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
||||||
|
|
||||||
typedef struct expr_s {
|
typedef struct expr_s {
|
||||||
|
@ -233,6 +239,7 @@ typedef struct expr_s {
|
||||||
ex_value_t *value; ///< constant value
|
ex_value_t *value; ///< constant value
|
||||||
element_chain_t compound; ///< compound initializer
|
element_chain_t compound; ///< compound initializer
|
||||||
ex_memset_t memset; ///< memset expr params
|
ex_memset_t memset; ///< memset expr params
|
||||||
|
ex_alias_t alias; ///< alias expr params
|
||||||
struct type_s *nil; ///< type for nil if known
|
struct type_s *nil; ///< type for nil if known
|
||||||
} e;
|
} e;
|
||||||
} expr_t;
|
} expr_t;
|
||||||
|
|
|
@ -54,5 +54,6 @@ EX_EXPR(nil) ///< umm, nil, null. nuff said (0 of any type)
|
||||||
EX_EXPR(value) ///< constant value (::ex_value_t)
|
EX_EXPR(value) ///< constant value (::ex_value_t)
|
||||||
EX_EXPR(compound) ///< compound initializer
|
EX_EXPR(compound) ///< compound initializer
|
||||||
EX_EXPR(memset) ///< memset needs three params...
|
EX_EXPR(memset) ///< memset needs three params...
|
||||||
|
EX_EXPR(alias) ///< view expression as different type (::ex_alias_t)
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
|
@ -1718,7 +1718,7 @@ fold_constants (expr_t *e)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
op = e->e.expr.op;
|
op = e->e.expr.op;
|
||||||
if (op == 'A' || op == 'g' || op == 'r')
|
if (op == 'g' || op == 'r')
|
||||||
return e;
|
return e;
|
||||||
t1 = extract_type (e1);
|
t1 = extract_type (e1);
|
||||||
if (t1 >= ev_type_count || !do_unary_op[t1]) {
|
if (t1 >= ev_type_count || !do_unary_op[t1]) {
|
||||||
|
@ -1734,7 +1734,7 @@ fold_constants (expr_t *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
op = e->e.expr.op;
|
op = e->e.expr.op;
|
||||||
if (op == 'A' || op == 'i' || op == 'n' || op == 'c' || op == 's') {
|
if (op == 'i' || op == 'n' || op == 'c' || op == 's') {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -608,12 +608,11 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
|
||||||
error (init, "non-constant initializier");
|
error (init, "non-constant initializier");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while ((init->type == ex_uexpr || init->type == ex_expr)
|
while (init->type == ex_alias) {
|
||||||
&& init->e.expr.op == 'A') {
|
if (init->e.alias.offset) {
|
||||||
if (init->type == ex_expr) {
|
offset += expr_integer (init->e.alias.offset);
|
||||||
offset += expr_integer (init->e.expr.e2);
|
|
||||||
}
|
}
|
||||||
init = init->e.expr.e1;
|
init = init->e.alias.expr;
|
||||||
}
|
}
|
||||||
if (init->type != ex_value) { //FIXME enum etc
|
if (init->type != ex_value) { //FIXME enum etc
|
||||||
internal_error (0, "initializier not a value");
|
internal_error (0, "initializier not a value");
|
||||||
|
|
|
@ -100,7 +100,6 @@ get_op_string (int op)
|
||||||
case 'r': return "<return>";
|
case 'r': return "<return>";
|
||||||
case 's': return "<state>";
|
case 's': return "<state>";
|
||||||
case 'c': return "<call>";
|
case 'c': return "<call>";
|
||||||
case 'A': return "<alias>";
|
|
||||||
case 'C': return "<cast>";
|
case 'C': return "<cast>";
|
||||||
case 'M': return "<move>";
|
case 'M': return "<move>";
|
||||||
case 'm': return "<move>";
|
case 'm': return "<move>";
|
||||||
|
@ -314,36 +313,43 @@ print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e,
|
dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e,
|
||||||
e->e.expr.e2);
|
e->e.expr.e2);
|
||||||
}
|
}
|
||||||
if (e->e.expr.op == 'A') {
|
dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e,
|
||||||
dstring_t *typestr = dstring_newstr();
|
get_op_string (e->e.expr.op), e->line);
|
||||||
print_type_str (typestr, e->e.expr.type);
|
}
|
||||||
dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e,
|
|
||||||
get_op_string (e->e.expr.op), typestr->str, e->line);
|
static void
|
||||||
dstring_delete (typestr);
|
print_alias (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
} else {
|
{
|
||||||
dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e,
|
int indent = level * 2 + 2;
|
||||||
get_op_string (e->e.expr.op), e->line);
|
|
||||||
|
_print_expr (dstr, e->e.alias.expr, level, id, next);
|
||||||
|
dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"a\"];\n", indent, "", e,
|
||||||
|
e->e.alias.expr);
|
||||||
|
if (e->e.alias.offset) {
|
||||||
|
_print_expr (dstr, e->e.alias.offset, level, id, next);
|
||||||
|
dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"o\"];\n", indent, "", e,
|
||||||
|
e->e.alias.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dstring_t *typestr = dstring_newstr();
|
||||||
|
print_type_str (typestr, e->e.alias.type);
|
||||||
|
dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e,
|
||||||
|
"<alias>", typestr->str, e->line);
|
||||||
|
dstring_delete (typestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
{
|
{
|
||||||
int indent = level * 2 + 2;
|
int indent = level * 2 + 2;
|
||||||
dstring_t *typestr = dstring_newstr();
|
|
||||||
|
|
||||||
if (e->e.expr.op != 'g' && e->e.expr.e1)
|
if (e->e.expr.op != 'g' && e->e.expr.e1)
|
||||||
_print_expr (dstr, e->e.expr.e1, level, id, next);
|
_print_expr (dstr, e->e.expr.e1, level, id, next);
|
||||||
if (e->e.expr.op == 'A') {
|
|
||||||
dstring_copystr (typestr, "\\n");
|
|
||||||
print_type_str (typestr, e->e.expr.type);
|
|
||||||
}
|
|
||||||
if (e->e.expr.op != 'r' || e->e.expr.e1)
|
if (e->e.expr.op != 'r' || e->e.expr.e1)
|
||||||
dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e,
|
dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e,
|
||||||
e->e.expr.e1);
|
e->e.expr.e1);
|
||||||
dasprintf (dstr, "%*se_%p [label=\"%s%s\\n%d\"];\n", indent, "", e,
|
dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e,
|
||||||
get_op_string (e->e.expr.op), typestr->str, e->line);
|
get_op_string (e->e.expr.op), e->line);
|
||||||
dstring_delete (typestr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -574,6 +580,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
[ex_value] = print_value,
|
[ex_value] = print_value,
|
||||||
[ex_compound] = print_compound,
|
[ex_compound] = print_compound,
|
||||||
[ex_memset] = print_memset,
|
[ex_memset] = print_memset,
|
||||||
|
[ex_alias] = print_alias,
|
||||||
};
|
};
|
||||||
int indent = level * 2 + 2;
|
int indent = level * 2 + 2;
|
||||||
|
|
||||||
|
@ -585,7 +592,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
return;
|
return;
|
||||||
e->printid = id;
|
e->printid = id;
|
||||||
|
|
||||||
if ((int) e->type < 0 || e->type > ex_memset || !print_funcs[e->type]) {
|
if ((int) e->type < 0 || e->type >= ex_count || !print_funcs[e->type]) {
|
||||||
dasprintf (dstr, "%*se_%p [label=\"(bad expr type)\\n%d\"];\n",
|
dasprintf (dstr, "%*se_%p [label=\"(bad expr type)\\n%d\"];\n",
|
||||||
indent, "", e, e->line);
|
indent, "", e, e->line);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -258,6 +258,8 @@ get_type (expr_t *e)
|
||||||
return e->e.vector.type;
|
return e->e.vector.type;
|
||||||
case ex_selector:
|
case ex_selector:
|
||||||
return &type_SEL;
|
return &type_SEL;
|
||||||
|
case ex_alias:
|
||||||
|
return e->e.alias.type;
|
||||||
case ex_count:
|
case ex_count:
|
||||||
internal_error (e, "invalid expression");
|
internal_error (e, "invalid expression");
|
||||||
}
|
}
|
||||||
|
@ -315,7 +317,7 @@ cast_error (expr_t *e, type_t *t1, type_t *t2)
|
||||||
print_type_str (s1, t1);
|
print_type_str (s1, t1);
|
||||||
print_type_str (s2, t2);
|
print_type_str (s2, t2);
|
||||||
|
|
||||||
e = error (e, "cannot cast from %s to %s", s1->str, s2->str);
|
e = error (e, "cannot cast from %s to %s", s1->str, s2->str);
|
||||||
dstring_delete (s1);
|
dstring_delete (s1);
|
||||||
dstring_delete (s2);
|
dstring_delete (s2);
|
||||||
return e;
|
return e;
|
||||||
|
@ -469,6 +471,12 @@ copy_expr (expr_t *e)
|
||||||
n->e.memset.val = copy_expr (e->e.memset.val);
|
n->e.memset.val = copy_expr (e->e.memset.val);
|
||||||
n->e.memset.count = copy_expr (e->e.memset.count);
|
n->e.memset.count = copy_expr (e->e.memset.count);
|
||||||
return n;
|
return n;
|
||||||
|
case ex_alias:
|
||||||
|
n = new_expr ();
|
||||||
|
*n = *e;
|
||||||
|
n->e.alias.expr = copy_expr (e->e.alias.expr);
|
||||||
|
n->e.alias.offset = copy_expr (e->e.alias.offset);
|
||||||
|
return n;
|
||||||
case ex_count:
|
case ex_count:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -875,9 +883,8 @@ new_short_expr (short short_val)
|
||||||
int
|
int
|
||||||
is_constant (expr_t *e)
|
is_constant (expr_t *e)
|
||||||
{
|
{
|
||||||
while ((e->type == ex_uexpr || e->type == ex_expr)
|
while (e->type == ex_alias) {
|
||||||
&& e->e.expr.op == 'A') {
|
e = e->e.alias.expr;
|
||||||
e = e->e.expr.e1;
|
|
||||||
}
|
}
|
||||||
if (e->type == ex_nil || e->type == ex_value || e->type == ex_labelref
|
if (e->type == ex_nil || e->type == ex_value || e->type == ex_labelref
|
||||||
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_const)
|
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_const)
|
||||||
|
@ -1231,15 +1238,14 @@ is_pointer_val (expr_t *e)
|
||||||
expr_t *
|
expr_t *
|
||||||
new_alias_expr (type_t *type, expr_t *expr)
|
new_alias_expr (type_t *type, expr_t *expr)
|
||||||
{
|
{
|
||||||
expr_t *alias;
|
if (expr->type == ex_alias) {
|
||||||
|
|
||||||
alias = new_unary_expr ('A', expr);
|
|
||||||
alias->e.expr.type = type;
|
|
||||||
//if (expr->type == ex_uexpr && expr->e.expr.op == 'A')
|
|
||||||
// bug (alias, "aliasing an alias expression");
|
|
||||||
if (expr->type == ex_expr && expr->e.expr.op == 'A') {
|
|
||||||
return new_offset_alias_expr (type, expr, 0);
|
return new_offset_alias_expr (type, expr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_t *alias = new_expr ();
|
||||||
|
alias->type = ex_alias;
|
||||||
|
alias->e.alias.type = type;
|
||||||
|
alias->e.alias.expr = expr;
|
||||||
alias->file = expr->file;
|
alias->file = expr->file;
|
||||||
alias->line = expr->line;
|
alias->line = expr->line;
|
||||||
return alias;
|
return alias;
|
||||||
|
@ -1248,18 +1254,24 @@ new_alias_expr (type_t *type, expr_t *expr)
|
||||||
expr_t *
|
expr_t *
|
||||||
new_offset_alias_expr (type_t *type, expr_t *expr, int offset)
|
new_offset_alias_expr (type_t *type, expr_t *expr, int offset)
|
||||||
{
|
{
|
||||||
expr_t *alias;
|
if (expr->type == ex_alias && expr->e.alias.offset) {
|
||||||
|
expr_t *ofs_expr = expr->e.alias.offset;
|
||||||
if (expr->type == ex_expr && expr->e.expr.op == 'A') {
|
|
||||||
expr_t *ofs_expr = expr->e.expr.e2;
|
|
||||||
expr = expr->e.expr.e1;
|
|
||||||
if (!is_constant (ofs_expr)) {
|
if (!is_constant (ofs_expr)) {
|
||||||
internal_error (ofs_expr, "non-constant offset for alias expr");
|
internal_error (ofs_expr, "non-constant offset for alias expr");
|
||||||
}
|
}
|
||||||
offset += expr_integer (ofs_expr);
|
offset += expr_integer (ofs_expr);
|
||||||
|
|
||||||
|
if (expr->e.alias.expr->type == ex_alias) {
|
||||||
|
internal_error (expr, "alias expr of alias expr");
|
||||||
|
}
|
||||||
|
expr = expr->e.alias.expr;
|
||||||
}
|
}
|
||||||
alias = new_binary_expr ('A', expr, new_integer_expr (offset));
|
|
||||||
alias->e.expr.type = type;
|
expr_t *alias = new_expr ();
|
||||||
|
alias->type = ex_alias;
|
||||||
|
alias->e.alias.type = type;
|
||||||
|
alias->e.alias.expr = expr;
|
||||||
|
alias->e.alias.offset = new_integer_expr (offset);
|
||||||
alias->file = expr->file;
|
alias->file = expr->file;
|
||||||
alias->line = expr->line;
|
alias->line = expr->line;
|
||||||
return alias;
|
return alias;
|
||||||
|
@ -1576,9 +1588,27 @@ has_function_call (expr_t *e)
|
||||||
case ex_uexpr:
|
case ex_uexpr:
|
||||||
if (e->e.expr.op != 'g')
|
if (e->e.expr.op != 'g')
|
||||||
return has_function_call (e->e.expr.e1);
|
return has_function_call (e->e.expr.e1);
|
||||||
default:
|
|
||||||
return 0;
|
return 0;
|
||||||
|
case ex_alias:
|
||||||
|
return has_function_call (e->e.alias.expr);
|
||||||
|
case ex_error:
|
||||||
|
case ex_state:
|
||||||
|
case ex_label:
|
||||||
|
case ex_labelref:
|
||||||
|
case ex_def:
|
||||||
|
case ex_symbol:
|
||||||
|
case ex_temp:
|
||||||
|
case ex_vector:
|
||||||
|
case ex_selector:
|
||||||
|
case ex_nil:
|
||||||
|
case ex_value:
|
||||||
|
case ex_compound:
|
||||||
|
case ex_memset:
|
||||||
|
return 0;
|
||||||
|
case ex_count:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
internal_error (e, "invalid expression type");
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t *
|
expr_t *
|
||||||
|
@ -1683,6 +1713,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ex_bool:
|
case ex_bool:
|
||||||
case ex_temp:
|
case ex_temp:
|
||||||
case ex_vector:
|
case ex_vector:
|
||||||
|
case ex_alias:
|
||||||
{
|
{
|
||||||
expr_t *n = new_unary_expr (op, e);
|
expr_t *n = new_unary_expr (op, e);
|
||||||
|
|
||||||
|
@ -1766,6 +1797,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ex_symbol:
|
case ex_symbol:
|
||||||
case ex_temp:
|
case ex_temp:
|
||||||
case ex_vector:
|
case ex_vector:
|
||||||
|
case ex_alias:
|
||||||
{
|
{
|
||||||
expr_t *n = new_unary_expr (op, e);
|
expr_t *n = new_unary_expr (op, e);
|
||||||
|
|
||||||
|
@ -1842,6 +1874,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ex_symbol:
|
case ex_symbol:
|
||||||
case ex_temp:
|
case ex_temp:
|
||||||
case ex_vector:
|
case ex_vector:
|
||||||
|
case ex_alias:
|
||||||
bitnot_expr:
|
bitnot_expr:
|
||||||
if (options.code.progsversion == PROG_ID_VERSION) {
|
if (options.code.progsversion == PROG_ID_VERSION) {
|
||||||
expr_t *n1 = new_integer_expr (-1);
|
expr_t *n1 = new_integer_expr (-1);
|
||||||
|
@ -2364,16 +2397,6 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
e = e1->e.expr.e2;
|
e = e1->e.expr.e2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e1->e.expr.op == 'A') {
|
|
||||||
if (!t)
|
|
||||||
t = e1->e.expr.type;
|
|
||||||
if (e2) {
|
|
||||||
e2 = binary_expr ('+', e1->e.expr.e2, e2);
|
|
||||||
} else {
|
|
||||||
e2 = e1->e.expr.e2;
|
|
||||||
}
|
|
||||||
return address_expr (e1->e.expr.e1, e2, t);
|
|
||||||
}
|
|
||||||
return error (e1, "invalid type for unary &");
|
return error (e1, "invalid type for unary &");
|
||||||
case ex_uexpr:
|
case ex_uexpr:
|
||||||
if (e1->e.expr.op == '.') {
|
if (e1->e.expr.op == '.') {
|
||||||
|
@ -2384,11 +2407,6 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e1->e.expr.op == 'A') {
|
|
||||||
if (!t)
|
|
||||||
t = e1->e.expr.type;
|
|
||||||
return address_expr (e1->e.expr.e1, e2, t);
|
|
||||||
}
|
|
||||||
return error (e1, "invalid type for unary &");
|
return error (e1, "invalid type for unary &");
|
||||||
case ex_label:
|
case ex_label:
|
||||||
return new_label_ref (&e1->e.label);
|
return new_label_ref (&e1->e.label);
|
||||||
|
@ -2396,6 +2414,18 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
e = new_unary_expr ('&', e1);
|
e = new_unary_expr ('&', e1);
|
||||||
e->e.expr.type = pointer_type (t);
|
e->e.expr.type = pointer_type (t);
|
||||||
break;
|
break;
|
||||||
|
case ex_alias:
|
||||||
|
if (!t) {
|
||||||
|
t = e1->e.alias.type;
|
||||||
|
}
|
||||||
|
if (e1->e.alias.offset) {
|
||||||
|
if (e2) {
|
||||||
|
e2 = binary_expr ('+', e1->e.alias.offset, e2);
|
||||||
|
} else {
|
||||||
|
e2 = e1->e.alias.offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return address_expr (e1->e.alias.expr, e2, t);
|
||||||
default:
|
default:
|
||||||
return error (e1, "invalid type for unary &");
|
return error (e1, "invalid type for unary &");
|
||||||
}
|
}
|
||||||
|
@ -2416,8 +2446,11 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
e = new_binary_expr ('&', e, e2);
|
e = new_binary_expr ('&', e, e2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e->type == ex_expr || e->type == ex_uexpr)
|
if (e->type == ex_expr || e->type == ex_uexpr) {
|
||||||
e->e.expr.type = pointer_type (t);
|
e->e.expr.type = pointer_type (t);
|
||||||
|
} else if (e->type == ex_alias) {
|
||||||
|
e->e.alias.type = pointer_type (t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
|
|
|
@ -112,17 +112,13 @@ is_lvalue (const expr_t *expr)
|
||||||
if (expr->e.expr.op == '.') {
|
if (expr->e.expr.op == '.') {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (expr->e.expr.op == 'A') {
|
|
||||||
return is_lvalue (expr->e.expr.e1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
case ex_alias:
|
||||||
|
return is_lvalue (expr->e.alias.expr);
|
||||||
case ex_uexpr:
|
case ex_uexpr:
|
||||||
if (expr->e.expr.op == '.') {
|
if (expr->e.expr.op == '.') {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (expr->e.expr.op == 'A') {
|
|
||||||
return is_lvalue (expr->e.expr.e1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ex_memset:
|
case ex_memset:
|
||||||
case ex_compound:
|
case ex_compound:
|
||||||
|
|
|
@ -970,12 +970,11 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
e1 = convert_vector (e1);
|
e1 = convert_vector (e1);
|
||||||
// FIXME this is target-specific info and should not be in the
|
// FIXME this is target-specific info and should not be in the
|
||||||
// expression tree
|
// expression tree
|
||||||
if ((e1->type == ex_expr || e1->type == ex_uexpr) && e1->e.expr.op == 'A'
|
if (e1->type == ex_alias && is_call (e1->e.alias.expr)) {
|
||||||
&& is_call (e1->e.expr.e1)) {
|
|
||||||
// move the alias expression inside the block so the following check
|
// move the alias expression inside the block so the following check
|
||||||
// can detect the call and move the temp assignment into the block
|
// can detect the call and move the temp assignment into the block
|
||||||
expr_t *block = e1->e.expr.e1;
|
expr_t *block = e1->e.alias.expr;
|
||||||
e1->e.expr.e1 = block->e.block.result;
|
e1->e.alias.expr = block->e.block.result;
|
||||||
block->e.block.result = e1;
|
block->e.block.result = e1;
|
||||||
e1 = block;
|
e1 = block;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1202,11 +1202,11 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
def_t *def;
|
def_t *def;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
if (e->type == ex_expr) {
|
if (e->e.alias.offset) {
|
||||||
offset = expr_integer (e->e.expr.e2);
|
offset = expr_integer (e->e.alias.offset);
|
||||||
}
|
}
|
||||||
type = e->e.expr.type;
|
type = e->e.alias.type;
|
||||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &aop);
|
sblock = statement_subexpr (sblock, e->e.alias.expr, &aop);
|
||||||
if (type_compatible (aop->type, type)) {
|
if (type_compatible (aop->type, type)) {
|
||||||
//FIXME type_compatible??? shouldn't that be type_size ==?
|
//FIXME type_compatible??? shouldn't that be type_size ==?
|
||||||
if (offset) {
|
if (offset) {
|
||||||
|
@ -1268,9 +1268,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
case 'M':
|
case 'M':
|
||||||
sblock = expr_move (sblock, e, op);
|
sblock = expr_move (sblock, e, op);
|
||||||
break;
|
break;
|
||||||
case 'A':
|
|
||||||
sblock = expr_alias (sblock, e, op);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
opcode = convert_op (e->e.expr.op);
|
opcode = convert_op (e->e.expr.op);
|
||||||
if (!opcode)
|
if (!opcode)
|
||||||
|
@ -1338,9 +1335,6 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
case '.':
|
case '.':
|
||||||
sblock = expr_deref (sblock, e, op);
|
sblock = expr_deref (sblock, e, op);
|
||||||
break;
|
break;
|
||||||
case 'A':
|
|
||||||
sblock = expr_alias (sblock, e, op);
|
|
||||||
break;
|
|
||||||
case 'C':
|
case 'C':
|
||||||
sblock = expr_cast (sblock, e, op);
|
sblock = expr_cast (sblock, e, op);
|
||||||
break;
|
break;
|
||||||
|
@ -1529,6 +1523,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
[ex_nil] = expr_nil,
|
[ex_nil] = expr_nil,
|
||||||
[ex_value] = expr_value,
|
[ex_value] = expr_value,
|
||||||
[ex_selector] = expr_selector,
|
[ex_selector] = expr_selector,
|
||||||
|
[ex_alias] = expr_alias,
|
||||||
};
|
};
|
||||||
if (!e) {
|
if (!e) {
|
||||||
*op = 0;
|
*op = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue