mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-05 17:01:25 +00:00
[qfcc] Give address expressions their own type
Definitely a pain to get working after the switch, but definitely worth the effort. Still exposing type aliasing bugs.
This commit is contained in:
parent
cf8061c4d3
commit
fa482e8ee5
8 changed files with 99 additions and 45 deletions
|
@ -213,6 +213,12 @@ typedef struct {
|
||||||
struct expr_s *offset; ///< offset for alias
|
struct expr_s *offset; ///< offset for alias
|
||||||
} ex_alias_t;
|
} ex_alias_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct type_s *type; ///< pointer type
|
||||||
|
struct expr_s *lvalue; ///< the lvalue being addressed
|
||||||
|
struct expr_s *offset; ///< offset from the address
|
||||||
|
} ex_address_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 {
|
||||||
|
@ -240,6 +246,7 @@ typedef struct expr_s {
|
||||||
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
|
ex_alias_t alias; ///< alias expr params
|
||||||
|
ex_address_t address; ///< 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;
|
||||||
|
@ -654,6 +661,9 @@ expr_t *new_ret_expr (struct type_s *type);
|
||||||
expr_t *new_alias_expr (struct type_s *type, expr_t *expr);
|
expr_t *new_alias_expr (struct type_s *type, expr_t *expr);
|
||||||
expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset);
|
expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset);
|
||||||
|
|
||||||
|
expr_t *new_address_expr (struct type_s *lvtype, expr_t *lvalue,
|
||||||
|
expr_t *offset);
|
||||||
|
|
||||||
/** Create an expression of the correct type that references the specified
|
/** Create an expression of the correct type that references the specified
|
||||||
parameter slot.
|
parameter slot.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
expr.h
|
expr_names.h
|
||||||
|
|
||||||
expression construction and manipulations
|
expression construction and manipulations
|
||||||
|
|
||||||
|
@ -55,5 +55,6 @@ 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)
|
EX_EXPR(alias) ///< view expression as different type (::ex_alias_t)
|
||||||
|
EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t)
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
|
@ -568,7 +568,7 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
type_t *type = get_type (e2);
|
type_t *type = get_type (e2);
|
||||||
|
|
||||||
if ((op == '.' || op == '&') && type->type == ev_field) {
|
if (op == '.' && type->type == ev_field) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
if (op == EQ || op == NE) {
|
if (op == EQ || op == NE) {
|
||||||
|
@ -617,7 +617,7 @@ static expr_t *
|
||||||
do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
type_t *type;
|
type_t *type;
|
||||||
static int valid[] = {'=', '-', '&', 'M', '.', EQ, NE, 0};
|
static int valid[] = {'=', '-', 'M', '.', EQ, NE, 0};
|
||||||
|
|
||||||
if (is_integral (type = get_type (e2)) && (op == '-' || op == '+')) {
|
if (is_integral (type = get_type (e2)) && (op == '-' || op == '+')) {
|
||||||
// pointer arithmetic
|
// pointer arithmetic
|
||||||
|
@ -647,10 +647,10 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||||
else
|
else
|
||||||
e->e.expr.type = &type_float;
|
e->e.expr.type = &type_float;
|
||||||
}
|
}
|
||||||
if (op != '.' && op != '&' && op != 'M'
|
if (op != '.' && op != 'M'
|
||||||
&& extract_type (e1) != extract_type (e2))
|
&& extract_type (e1) != extract_type (e2))
|
||||||
return type_mismatch (e1, e2, op);
|
return type_mismatch (e1, e2, op);
|
||||||
if ((op == '.' || op == '&') && is_uinteger(get_type (e2)))
|
if (op == '.' && is_uinteger(get_type (e2)))
|
||||||
e->e.expr.e2 = cf_cast_expr (&type_integer, e2);
|
e->e.expr.e2 = cf_cast_expr (&type_integer, e2);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,6 +338,27 @@ print_alias (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
dstring_delete (typestr);
|
dstring_delete (typestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_address (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
|
{
|
||||||
|
int indent = level * 2 + 2;
|
||||||
|
|
||||||
|
_print_expr (dstr, e->e.alias.expr, level, id, next);
|
||||||
|
dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"&\"];\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=\"+\"];\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,
|
||||||
|
"&", 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)
|
||||||
{
|
{
|
||||||
|
@ -581,6 +602,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
||||||
[ex_compound] = print_compound,
|
[ex_compound] = print_compound,
|
||||||
[ex_memset] = print_memset,
|
[ex_memset] = print_memset,
|
||||||
[ex_alias] = print_alias,
|
[ex_alias] = print_alias,
|
||||||
|
[ex_address] = print_address,
|
||||||
};
|
};
|
||||||
int indent = level * 2 + 2;
|
int indent = level * 2 + 2;
|
||||||
|
|
||||||
|
|
|
@ -260,6 +260,8 @@ get_type (expr_t *e)
|
||||||
return &type_SEL;
|
return &type_SEL;
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
return e->e.alias.type;
|
return e->e.alias.type;
|
||||||
|
case ex_address:
|
||||||
|
return e->e.address.type;
|
||||||
case ex_count:
|
case ex_count:
|
||||||
internal_error (e, "invalid expression");
|
internal_error (e, "invalid expression");
|
||||||
}
|
}
|
||||||
|
@ -477,6 +479,12 @@ copy_expr (expr_t *e)
|
||||||
n->e.alias.expr = copy_expr (e->e.alias.expr);
|
n->e.alias.expr = copy_expr (e->e.alias.expr);
|
||||||
n->e.alias.offset = copy_expr (e->e.alias.offset);
|
n->e.alias.offset = copy_expr (e->e.alias.offset);
|
||||||
return n;
|
return n;
|
||||||
|
case ex_address:
|
||||||
|
n = new_expr ();
|
||||||
|
*n = *e;
|
||||||
|
n->e.address.lvalue = copy_expr (e->e.address.lvalue);
|
||||||
|
n->e.address.offset = copy_expr (e->e.address.offset);
|
||||||
|
return n;
|
||||||
case ex_count:
|
case ex_count:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1277,6 +1285,17 @@ new_offset_alias_expr (type_t *type, expr_t *expr, int offset)
|
||||||
return alias;
|
return alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_t *
|
||||||
|
new_address_expr (type_t *lvtype, expr_t *lvalue, expr_t *offset)
|
||||||
|
{
|
||||||
|
expr_t *addr = new_expr ();
|
||||||
|
addr->type = ex_address;
|
||||||
|
addr->e.address.type = pointer_type (lvtype);
|
||||||
|
addr->e.address.lvalue = lvalue;
|
||||||
|
addr->e.address.offset = offset;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
static expr_t *
|
static expr_t *
|
||||||
param_expr (const char *name, type_t *type)
|
param_expr (const char *name, type_t *type)
|
||||||
{
|
{
|
||||||
|
@ -1406,8 +1425,7 @@ field_expr (expr_t *e1, expr_t *e2)
|
||||||
|
|
||||||
e2->type = ex_value;
|
e2->type = ex_value;
|
||||||
e2->e.value = new_short_val (field->s.offset);
|
e2->e.value = new_short_val (field->s.offset);
|
||||||
e = new_binary_expr ('&', e1, e2);
|
e = new_address_expr (field->type, e1, e2);
|
||||||
e->e.expr.type = pointer_type (field->type);
|
|
||||||
return unary_expr ('.', e);
|
return unary_expr ('.', e);
|
||||||
} else if (is_class (t1->t.fldptr.type)) {
|
} else if (is_class (t1->t.fldptr.type)) {
|
||||||
class_t *class = t1->t.fldptr.type->t.class;
|
class_t *class = t1->t.fldptr.type->t.class;
|
||||||
|
@ -1420,8 +1438,7 @@ field_expr (expr_t *e1, expr_t *e2)
|
||||||
return new_error_expr ();
|
return new_error_expr ();
|
||||||
e2->type = ex_value;
|
e2->type = ex_value;
|
||||||
e2->e.value = new_short_val (ivar->s.offset);
|
e2->e.value = new_short_val (ivar->s.offset);
|
||||||
e = new_binary_expr ('&', e1, e2);
|
e = new_address_expr (ivar->type, e1, e2);
|
||||||
e->e.expr.type = pointer_type (ivar->type);
|
|
||||||
return unary_expr ('.', e);
|
return unary_expr ('.', e);
|
||||||
}
|
}
|
||||||
} else if (is_vector (t1) || is_quaternion(t1) || is_struct (t1)) {
|
} else if (is_vector (t1) || is_quaternion(t1) || is_struct (t1)) {
|
||||||
|
@ -1591,6 +1608,8 @@ has_function_call (expr_t *e)
|
||||||
return 0;
|
return 0;
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
return has_function_call (e->e.alias.expr);
|
return has_function_call (e->e.alias.expr);
|
||||||
|
case ex_address:
|
||||||
|
return has_function_call (e->e.address.lvalue);
|
||||||
case ex_error:
|
case ex_error:
|
||||||
case ex_state:
|
case ex_state:
|
||||||
case ex_label:
|
case ex_label:
|
||||||
|
@ -1735,6 +1754,7 @@ unary_expr (int op, expr_t *e)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
case ex_nil:
|
case ex_nil:
|
||||||
|
case ex_address:
|
||||||
return error (e, "invalid type for unary -");
|
return error (e, "invalid type for unary -");
|
||||||
case ex_count:
|
case ex_count:
|
||||||
internal_error (e, "invalid expression");
|
internal_error (e, "invalid expression");
|
||||||
|
@ -1798,6 +1818,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ex_temp:
|
case ex_temp:
|
||||||
case ex_vector:
|
case ex_vector:
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
|
case ex_address:
|
||||||
{
|
{
|
||||||
expr_t *n = new_unary_expr (op, e);
|
expr_t *n = new_unary_expr (op, e);
|
||||||
|
|
||||||
|
@ -1890,6 +1911,7 @@ bitnot_expr:
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
case ex_nil:
|
case ex_nil:
|
||||||
|
case ex_address:
|
||||||
return error (e, "invalid type for unary ~");
|
return error (e, "invalid type for unary ~");
|
||||||
case ex_count:
|
case ex_count:
|
||||||
internal_error (e, "invalid expression");
|
internal_error (e, "invalid expression");
|
||||||
|
@ -2312,9 +2334,7 @@ array_expr (expr_t *array, expr_t *index)
|
||||||
e = address_expr (array, index, array_type->t.array.type);
|
e = address_expr (array, index, array_type->t.array.type);
|
||||||
} else {
|
} else {
|
||||||
if (!is_short_val (index) || expr_short (index)) {
|
if (!is_short_val (index) || expr_short (index)) {
|
||||||
e = new_binary_expr ('&', array, index);
|
e = new_address_expr (array_type->t.array.type, array, index);
|
||||||
//e->e.expr.type = array_type->aux_type;
|
|
||||||
e->e.expr.type = array_type;
|
|
||||||
} else {
|
} else {
|
||||||
e = array;
|
e = array;
|
||||||
}
|
}
|
||||||
|
@ -2382,9 +2402,8 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
return error (e1, "invalid type for unary &");
|
return error (e1, "invalid type for unary &");
|
||||||
case ex_expr:
|
case ex_expr:
|
||||||
if (e1->e.expr.op == '.') {
|
if (e1->e.expr.op == '.') {
|
||||||
e = e1;
|
e = new_address_expr (e1->e.expr.type,
|
||||||
e->e.expr.op = '&';
|
e1->e.expr.e1, e1->e.expr.e2);
|
||||||
e->e.expr.type = pointer_type (e->e.expr.type);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e1->e.expr.op == 'm') {
|
if (e1->e.expr.op == 'm') {
|
||||||
|
@ -2402,8 +2421,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
if (e1->e.expr.op == '.') {
|
if (e1->e.expr.op == '.') {
|
||||||
e = e1->e.expr.e1;
|
e = e1->e.expr.e1;
|
||||||
if (e->type == ex_expr && e->e.expr.op == '.') {
|
if (e->type == ex_expr && e->e.expr.op == '.') {
|
||||||
e->e.expr.type = pointer_type (e->e.expr.type);
|
e = new_address_expr (e->e.expr.type, e->e.expr.e1, e->e.expr.e2);
|
||||||
e->e.expr.op = '&';
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2411,8 +2429,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
case ex_label:
|
case ex_label:
|
||||||
return new_label_ref (&e1->e.label);
|
return new_label_ref (&e1->e.label);
|
||||||
case ex_temp:
|
case ex_temp:
|
||||||
e = new_unary_expr ('&', e1);
|
e = new_address_expr (t, e1, 0);
|
||||||
e->e.expr.type = pointer_type (t);
|
|
||||||
break;
|
break;
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
if (!t) {
|
if (!t) {
|
||||||
|
@ -2438,19 +2455,17 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
||||||
def_t *def = e->e.value->v.pointer.def;
|
def_t *def = e->e.value->v.pointer.def;
|
||||||
e->e.value = new_pointer_val (base + offset, t, def, 0);
|
e->e.value = new_pointer_val (base + offset, t, def, 0);
|
||||||
} else {
|
} else {
|
||||||
if (!is_short_val (e2) || expr_short (e2)) {
|
expr_t *offset = 0;
|
||||||
if (e->type == ex_expr && e->e.expr.op == '&') {
|
if (e->type == ex_address) {
|
||||||
e = new_binary_expr ('&', e->e.expr.e1,
|
offset = e->e.address.offset;
|
||||||
binary_expr ('+', e->e.expr.e2, e2));
|
e1 = e->e.address.lvalue;
|
||||||
} else {
|
} else {
|
||||||
e = new_binary_expr ('&', e, e2);
|
e1 = e;
|
||||||
}
|
}
|
||||||
|
if (offset) {
|
||||||
|
e2 = binary_expr ('+', offset, e2);
|
||||||
}
|
}
|
||||||
if (e->type == ex_expr || e->type == ex_uexpr) {
|
e = new_address_expr (t, e1, e2);
|
||||||
e->e.expr.type = pointer_type (t);
|
|
||||||
} else if (e->type == ex_alias) {
|
|
||||||
e->e.alias.type = pointer_type (t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
|
|
|
@ -115,6 +115,8 @@ is_lvalue (const expr_t *expr)
|
||||||
break;
|
break;
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
return is_lvalue (expr->e.alias.expr);
|
return is_lvalue (expr->e.alias.expr);
|
||||||
|
case ex_address:
|
||||||
|
return 0;
|
||||||
case ex_uexpr:
|
case ex_uexpr:
|
||||||
if (expr->e.expr.op == '.') {
|
if (expr->e.expr.op == '.') {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -486,8 +486,8 @@ get_selector (expr_t *sel)
|
||||||
if (sel->type == ex_selector) {
|
if (sel->type == ex_selector) {
|
||||||
return sel->e.selector.sel;
|
return sel->e.selector.sel;
|
||||||
}
|
}
|
||||||
if (sel->type != ex_expr && sel->e.expr.op != '&'
|
if (sel->type != ex_address && !sel->e.address.offset
|
||||||
&& !is_SEL(sel->e.expr.type)) {
|
&& !is_SEL(sel->e.address.type)) {
|
||||||
error (sel, "not a selector");
|
error (sel, "not a selector");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -744,8 +744,11 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
{
|
{
|
||||||
statement_t *s;
|
statement_t *s;
|
||||||
s = new_statement (st_expr, "&", e);
|
s = new_statement (st_expr, "&", e);
|
||||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
|
sblock = statement_subexpr (sblock, e->e.address.lvalue, &s->opa);
|
||||||
s->opc = temp_operand (e->e.expr.type, e);
|
if (e->e.address.offset) {
|
||||||
|
sblock = statement_subexpr (sblock, e->e.address.offset, &s->opb);
|
||||||
|
}
|
||||||
|
s->opc = temp_operand (e->e.address.type, e);
|
||||||
sblock_add_statement (sblock, s);
|
sblock_add_statement (sblock, s);
|
||||||
*(op) = s->opc;
|
*(op) = s->opc;
|
||||||
return sblock;
|
return sblock;
|
||||||
|
@ -960,9 +963,12 @@ dereference_dst:
|
||||||
// to get the pointer and switch to storep instructions.
|
// to get the pointer and switch to storep instructions.
|
||||||
dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e);
|
dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e);
|
||||||
opcode = ".="; // FIXME find a nicer representation (lose strings?)
|
opcode = ".="; // FIXME find a nicer representation (lose strings?)
|
||||||
if (dst_expr->type == ex_expr && !is_const_ptr (dst_expr->e.expr.e1)) {
|
if (dst_expr->type == ex_address && dst_expr->e.address.offset
|
||||||
sblock = statement_subexpr (sblock, dst_expr->e.expr.e1, &dst);
|
&& !is_const_ptr (dst_expr->e.address.lvalue)) {
|
||||||
sblock = statement_subexpr (sblock, dst_expr->e.expr.e2, &ofs);
|
sblock = statement_subexpr (sblock,
|
||||||
|
dst_expr->e.address.lvalue, &dst);
|
||||||
|
sblock = statement_subexpr (sblock,
|
||||||
|
dst_expr->e.address.offset, &ofs);
|
||||||
} else {
|
} else {
|
||||||
sblock = statement_subexpr (sblock, dst_expr, &dst);
|
sblock = statement_subexpr (sblock, dst_expr, &dst);
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
|
@ -1127,17 +1133,17 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
|
||||||
expr_t *e;
|
expr_t *e;
|
||||||
|
|
||||||
e = deref->e.expr.e1;
|
e = deref->e.expr.e1;
|
||||||
if (e->type == ex_uexpr && e->e.expr.op == '&'
|
if (e->type == ex_address && !e->e.address.offset
|
||||||
&& e->e.expr.e1->type == ex_symbol) {
|
&& e->e.address.lvalue->type == ex_symbol) {
|
||||||
if (e->e.expr.e1->e.symbol->sy_type != sy_var)
|
if (e->e.expr.e1->e.symbol->sy_type != sy_var)
|
||||||
internal_error (e, "address of non-var");
|
internal_error (e, "address of non-var");
|
||||||
*op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e);
|
*op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e);
|
||||||
} else if (e->type == ex_expr && e->e.expr.op == '&') {
|
} else if (e->type == ex_address && e->e.address.offset) {
|
||||||
statement_t *s;
|
statement_t *s;
|
||||||
operand_t *ptr = 0;
|
operand_t *ptr = 0;
|
||||||
operand_t *offs = 0;
|
operand_t *offs = 0;
|
||||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr);
|
sblock = statement_subexpr (sblock, e->e.address.lvalue, &ptr);
|
||||||
sblock = statement_subexpr (sblock, e->e.expr.e2, &offs);
|
sblock = statement_subexpr (sblock, e->e.address.offset, &offs);
|
||||||
if (!*op)
|
if (!*op)
|
||||||
*op = temp_operand (type, e);
|
*op = temp_operand (type, e);
|
||||||
if (low_level_type (type) == ev_void) {
|
if (low_level_type (type) == ev_void) {
|
||||||
|
@ -1329,9 +1335,6 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
statement_t *s;
|
statement_t *s;
|
||||||
|
|
||||||
switch (e->e.expr.op) {
|
switch (e->e.expr.op) {
|
||||||
case '&':
|
|
||||||
sblock = expr_address (sblock, e, op);
|
|
||||||
break;
|
|
||||||
case '.':
|
case '.':
|
||||||
sblock = expr_deref (sblock, e, op);
|
sblock = expr_deref (sblock, e, op);
|
||||||
break;
|
break;
|
||||||
|
@ -1524,6 +1527,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
[ex_value] = expr_value,
|
[ex_value] = expr_value,
|
||||||
[ex_selector] = expr_selector,
|
[ex_selector] = expr_selector,
|
||||||
[ex_alias] = expr_alias,
|
[ex_alias] = expr_alias,
|
||||||
|
[ex_address] = expr_address,
|
||||||
};
|
};
|
||||||
if (!e) {
|
if (!e) {
|
||||||
*op = 0;
|
*op = 0;
|
||||||
|
|
Loading…
Reference in a new issue