mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
Add support for binary alias expressions
Doesn't quite work yet.
This commit is contained in:
parent
913b9f52e0
commit
ee1f5f9478
4 changed files with 70 additions and 45 deletions
|
@ -42,6 +42,7 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
struct def_s *def;
|
||||
int offset;
|
||||
struct type_s *type;
|
||||
struct flowvar_s *flowvar;
|
||||
struct daglabel_s *daglabel;
|
||||
|
|
|
@ -320,8 +320,16 @@ 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,
|
||||
e->e.expr.e2);
|
||||
}
|
||||
dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e,
|
||||
get_op_string (e->e.expr.op), e->line);
|
||||
if (e->e.expr.op == 'A') {
|
||||
dstring_t *typestr = dstring_newstr();
|
||||
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);
|
||||
dstring_delete (typestr);
|
||||
} else {
|
||||
dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e,
|
||||
get_op_string (e->e.expr.op), e->line);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -109,6 +109,9 @@ check_valid_lvalue (expr_t *expr)
|
|||
if (expr->e.expr.op == '.') {
|
||||
return 0;
|
||||
}
|
||||
if (expr->e.expr.op == 'A') {
|
||||
return check_valid_lvalue (expr->e.expr.e1);
|
||||
}
|
||||
break;
|
||||
case ex_uexpr:
|
||||
if (expr->e.expr.op == '.') {
|
||||
|
|
|
@ -804,6 +804,59 @@ expr_block (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
operand_t *aop = 0;
|
||||
operand_t *top;
|
||||
etype_t type;
|
||||
def_t *def;
|
||||
int offset = 0;
|
||||
|
||||
if (e->type == ex_expr) {
|
||||
offset = expr_integer (e->e.expr.e2);
|
||||
}
|
||||
type = low_level_type (e->e.expr.type);
|
||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &aop);
|
||||
if (aop->type == type) {
|
||||
if (offset) {
|
||||
internal_error (e, "offset alias of same type");
|
||||
}
|
||||
*op = aop;
|
||||
return sblock;
|
||||
}
|
||||
if (aop->op_type == op_temp) {
|
||||
while (aop->o.tempop.alias) {
|
||||
aop = aop->o.tempop.alias;
|
||||
if (aop->op_type != op_temp)
|
||||
internal_error (e, "temp alias of non-temp var");
|
||||
}
|
||||
for (top = aop->o.tempop.alias_ops; top; top = top->next) {
|
||||
if (top->type == type && top->o.tempop.offset == offset) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!top) {
|
||||
top = new_operand (op_temp);
|
||||
top->type = type;
|
||||
top->o.tempop.alias = aop;
|
||||
top->o.tempop.offset = offset;
|
||||
top->next = aop->o.tempop.alias_ops;
|
||||
aop->o.tempop.alias_ops = top;
|
||||
}
|
||||
*op = top;
|
||||
} else if (aop->op_type == op_def) {
|
||||
def = aop->o.def;
|
||||
while (def->alias)
|
||||
def = def->alias;
|
||||
*op = def_operand (alias_def (def, ev_types[type], offset), 0);
|
||||
} else {
|
||||
internal_error (e, "invalid alias target: %s: %s",
|
||||
optype_str (aop->op_type), operand_string (aop));
|
||||
}
|
||||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
|
@ -822,6 +875,9 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
case 'M':
|
||||
sblock = expr_move (sblock, e, op);
|
||||
break;
|
||||
case 'A':
|
||||
sblock = expr_alias (sblock, e, op);
|
||||
break;
|
||||
default:
|
||||
opcode = convert_op (e->e.expr.op);
|
||||
if (!opcode)
|
||||
|
@ -838,49 +894,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
operand_t *aop = 0;
|
||||
operand_t *top;
|
||||
etype_t type;
|
||||
def_t *def;
|
||||
|
||||
type = low_level_type (e->e.expr.type);
|
||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &aop);
|
||||
if (aop->type == type) {
|
||||
*op = aop;
|
||||
return sblock;
|
||||
}
|
||||
if (aop->op_type == op_temp) {
|
||||
while (aop->o.tempop.alias) {
|
||||
aop = aop->o.tempop.alias;
|
||||
if (aop->op_type != op_temp)
|
||||
internal_error (e, "temp alias of non-temp var");
|
||||
}
|
||||
for (top = aop->o.tempop.alias_ops; top; top = top->next)
|
||||
if (top->type == type)
|
||||
break;
|
||||
if (!top) {
|
||||
top = new_operand (op_temp);
|
||||
top->type = type;
|
||||
top->o.tempop.alias = aop;
|
||||
top->next = aop->o.tempop.alias_ops;
|
||||
aop->o.tempop.alias_ops = top;
|
||||
}
|
||||
*op = top;
|
||||
} else if (aop->op_type == op_def) {
|
||||
def = aop->o.def;
|
||||
while (def->alias)
|
||||
def = def->alias;
|
||||
*op = def_operand (alias_def (def, ev_types[type], 0), 0);
|
||||
} else {
|
||||
internal_error (e, "invalid alias target: %s: %s",
|
||||
optype_str (aop->op_type), operand_string (aop));
|
||||
}
|
||||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue