mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 18:01:15 +00:00
Move flowvar/deflabel from symbol_t to def_t.
With the need to handle aliasing in the optimizer, it has become apparent that having the flow data attached to symbols is not nearly as useful as having it attached to defs (which are views of the actual variables). This also involves a bit of a cleanup of operand types: op_pointer and op_alias are gone (this seems to greatly simplify the optimizer) There is a bit of a problem with enums in switch statements, but this might actually be a sign that something is not quite right in the switch code (other than enums not being recognized as ints for jump table optimization).
This commit is contained in:
parent
3bb8b1b9d2
commit
3f3b501c58
7 changed files with 149 additions and 211 deletions
|
@ -65,6 +65,8 @@ typedef struct def_s {
|
|||
struct def_s *alias; ///< real def which this def aliases
|
||||
struct reloc_s *relocs; ///< for relocations
|
||||
struct expr_s *initializer;///< initialer expression
|
||||
struct daglabel_s *daglabel;///< daglabel for this def
|
||||
struct flowvar_s *flowvar; ///< flowvar for this def
|
||||
|
||||
unsigned offset_reloc:1; ///< use *_def_ofs relocs
|
||||
unsigned initialized:1; ///< the def has been initialized
|
||||
|
|
|
@ -33,12 +33,10 @@
|
|||
#include "QF/pr_comp.h"
|
||||
|
||||
typedef enum {
|
||||
op_symbol,
|
||||
op_def,
|
||||
op_value,
|
||||
op_label,
|
||||
op_temp,
|
||||
op_pointer,
|
||||
op_alias,
|
||||
} op_type_e;
|
||||
|
||||
typedef struct {
|
||||
|
@ -46,20 +44,20 @@ typedef struct {
|
|||
struct type_s *type;
|
||||
struct flowvar_s *flowvar;
|
||||
struct daglabel_s *daglabel;
|
||||
struct operand_s *alias;
|
||||
int users;
|
||||
} tempop_t;
|
||||
|
||||
typedef struct operand_s {
|
||||
struct operand_s *next;
|
||||
op_type_e op_type;
|
||||
etype_t type; ///< possibly override symbol's type
|
||||
etype_t type; ///< possibly override def's type
|
||||
int size; ///< for structures
|
||||
union {
|
||||
struct symbol_s *symbol;
|
||||
struct def_s *def;
|
||||
struct ex_value_s *value;
|
||||
struct ex_label_s *label;
|
||||
tempop_t tempop;
|
||||
struct operand_s *alias;
|
||||
} o;
|
||||
} operand_t;
|
||||
|
||||
|
@ -108,7 +106,8 @@ typedef struct sblock_s {
|
|||
struct expr_s;
|
||||
struct type_s;
|
||||
|
||||
operand_t *alias_operand (operand_t *op, etype_t type);
|
||||
const char *optype_str (op_type_e type);
|
||||
|
||||
operand_t *temp_operand (struct type_s *type);
|
||||
sblock_t *new_sblock (void);
|
||||
statement_t *new_statement (st_type_t type, const char *opcode,
|
||||
|
|
|
@ -64,8 +64,6 @@ typedef struct symbol_s {
|
|||
sy_type_e sy_type; ///< symbol type
|
||||
struct type_s *type; ///< type of object to which symbol refers
|
||||
struct param_s *params; ///< the parameters if a function
|
||||
struct flowvar_s *flowvar;
|
||||
struct daglabel_s *daglabel;///< dag label for this symbol
|
||||
union {
|
||||
int offset; ///< sy_var (in a struct/union)
|
||||
struct def_s *def; ///< sy_var
|
||||
|
|
|
@ -65,13 +65,11 @@ flush_daglabels (void)
|
|||
operand_t *op;
|
||||
|
||||
if ((op = daglabel_chain->op)) {
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (op->op_type == op_symbol)
|
||||
op->o.symbol->daglabel = 0;
|
||||
if (op->op_type == op_def)
|
||||
op->o.def->daglabel = 0;
|
||||
else if (op->op_type == op_temp)
|
||||
op->o.tempop.daglabel = 0;
|
||||
else if (op->op_type == op_value || op->op_type == op_pointer)
|
||||
else if (op->op_type == op_value)
|
||||
op->o.value->daglabel = 0;
|
||||
else if (op->op_type == op_label)
|
||||
op->o.label->daglabel = 0;
|
||||
|
@ -146,14 +144,12 @@ opcode_label (dag_t *dag, const char *opcode, expr_t *expr)
|
|||
static daglabel_t *
|
||||
operand_label (dag_t *dag, operand_t *op)
|
||||
{
|
||||
symbol_t *sym = 0;
|
||||
def_t *def = 0;
|
||||
ex_value_t *val = 0;
|
||||
daglabel_t *label;
|
||||
|
||||
if (!op)
|
||||
return 0;
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
|
||||
if (op->op_type == op_temp) {
|
||||
if (op->o.tempop.daglabel)
|
||||
|
@ -161,14 +157,14 @@ operand_label (dag_t *dag, operand_t *op)
|
|||
label = new_label (dag);
|
||||
label->op = op;
|
||||
op->o.tempop.daglabel = label;
|
||||
} else if (op->op_type == op_symbol) {
|
||||
sym = op->o.symbol;
|
||||
if (sym->daglabel)
|
||||
return sym->daglabel;
|
||||
} else if (op->op_type == op_def) {
|
||||
def = op->o.def;
|
||||
if (def->daglabel)
|
||||
return def->daglabel;
|
||||
label = new_label (dag);
|
||||
label->op = op;
|
||||
sym->daglabel = label;
|
||||
} else if (op->op_type == op_value || op->op_type == op_pointer) {
|
||||
def->daglabel = label;
|
||||
} else if (op->op_type == op_value) {
|
||||
val = op->o.value;
|
||||
if (val->daglabel)
|
||||
return val->daglabel;
|
||||
|
@ -207,23 +203,19 @@ leaf_node (dag_t *dag, operand_t *op, expr_t *expr)
|
|||
static dagnode_t *
|
||||
dag_node (operand_t *op)
|
||||
{
|
||||
symbol_t *sym;
|
||||
def_t *def;
|
||||
dagnode_t *node = 0;
|
||||
|
||||
if (!op)
|
||||
return 0;
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (op->op_type == op_symbol) {
|
||||
sym = op->o.symbol;
|
||||
//if (sym->sy_type == sy_const)
|
||||
// return 0;
|
||||
if (sym->daglabel)
|
||||
node = sym->daglabel->dagnode;
|
||||
if (op->op_type == op_def) {
|
||||
def = op->o.def;
|
||||
if (def->daglabel)
|
||||
node = def->daglabel->dagnode;
|
||||
} else if (op->op_type == op_temp) {
|
||||
if (op->o.tempop.daglabel)
|
||||
node = op->o.tempop.daglabel->dagnode;
|
||||
} else if (op->op_type == op_value || op->op_type == op_pointer) {
|
||||
} else if (op->op_type == op_value) {
|
||||
if (op->o.value->daglabel)
|
||||
node = op->o.value->daglabel->dagnode;
|
||||
} else if (op->op_type == op_label) {
|
||||
|
@ -337,19 +329,13 @@ dagnode_set_edges (dagnode_t *n)
|
|||
static int
|
||||
op_is_identifier (operand_t *op)
|
||||
{
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (op->op_type == op_label)
|
||||
return 0;
|
||||
if (op->op_type == op_value)
|
||||
return 0;
|
||||
if (op->op_type == op_pointer)
|
||||
return 1;
|
||||
if (op->op_type == op_temp)
|
||||
return 1;
|
||||
if (op->op_type != op_symbol)
|
||||
return 0;
|
||||
if (op->o.symbol->sy_type != sy_var)
|
||||
if (op->op_type != op_def)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -569,10 +555,11 @@ build_statement (const char *opcode, operand_t **operands, expr_t *expr)
|
|||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if ((op = operands[i])) {
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (op->op_type == op_temp)
|
||||
if (op->op_type == op_temp) {
|
||||
while (op->o.tempop.alias)
|
||||
op = op->o.tempop.alias;
|
||||
op->o.tempop.users++;
|
||||
}
|
||||
}
|
||||
}
|
||||
st->opa = operands[0];
|
||||
|
@ -614,13 +601,6 @@ dag_calc_node_costs (dagnode_t *dagnode)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
static operand_t *
|
||||
fix_op_type (operand_t *op, etype_t type)
|
||||
{
|
||||
if (op && op->op_type != op_label && op->type != type)
|
||||
op = alias_operand (op, type);
|
||||
return op;
|
||||
}
|
||||
|
||||
static operand_t *
|
||||
generate_assignments (dag_t *dag, sblock_t *block, operand_t *src,
|
||||
|
@ -631,15 +611,12 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src,
|
|||
operand_t *operands[3] = {0, 0, 0};
|
||||
daglabel_t *var;
|
||||
|
||||
operands[0] = fix_op_type (src, type);
|
||||
operands[0] = src;
|
||||
for ( ; var_iter; var_iter = set_next (var_iter)) {
|
||||
var = dag->labels[var_iter->member];
|
||||
operands[1] = fix_op_type (var->op, type);
|
||||
if (!dst) {
|
||||
operands[1] = var->op;
|
||||
if (!dst)
|
||||
dst = operands[1];
|
||||
while (dst->op_type == op_alias)
|
||||
dst = dst->o.alias;
|
||||
}
|
||||
|
||||
st = build_statement ("=", operands, var->expr);
|
||||
sblock_add_statement (block, st);
|
||||
|
@ -653,9 +630,6 @@ make_operand (dag_t *dag, sblock_t *block, const dagnode_t *dagnode, int index)
|
|||
operand_t *op;
|
||||
|
||||
op = dagnode->children[index]->value;
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
op = fix_op_type (op, dagnode->types[index]);
|
||||
return op;
|
||||
}
|
||||
|
||||
|
@ -676,9 +650,9 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
|
|||
dst = dagnode->label->op;
|
||||
if ((var_iter = set_first (dagnode->identifiers))) {
|
||||
type = dst->type;
|
||||
if (dst->op_type == op_symbol
|
||||
&& !strcmp (dst->o.symbol->name, ".return"))
|
||||
type = dag->flownode->return_type.in;
|
||||
//if (dst->op_type == op_def
|
||||
// && !strcmp (dst->o.def->name, ".return"))
|
||||
// type = dag->flownode->return_type.in;
|
||||
dst = generate_assignments (dag, block, dst, var_iter, type);
|
||||
}
|
||||
break;
|
||||
|
@ -692,7 +666,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
|
|||
} else {
|
||||
daglabel_t *var = dag->labels[var_iter->member];
|
||||
|
||||
operands[2] = fix_op_type (var->op, type);
|
||||
operands[2] = var->op;
|
||||
var_iter = set_next (var_iter);
|
||||
}
|
||||
dst = operands[2];
|
||||
|
|
|
@ -79,28 +79,11 @@ get_value_def (ex_value_t *value, etype_t type)
|
|||
static def_t *
|
||||
get_operand_def (expr_t *expr, operand_t *op)
|
||||
{
|
||||
def_t *def;
|
||||
|
||||
if (!op)
|
||||
return 0;
|
||||
switch (op->op_type) {
|
||||
case op_symbol:
|
||||
switch (op->o.symbol->sy_type) {
|
||||
case sy_var:
|
||||
if (op->type != op->o.symbol->type->type)
|
||||
return alias_def (op->o.symbol->s.def,
|
||||
ev_types[op->type], 0);
|
||||
return op->o.symbol->s.def;
|
||||
case sy_func:
|
||||
return op->o.symbol->s.func->def;
|
||||
case sy_const:
|
||||
return get_value_def (op->o.symbol->s.value, op->type);
|
||||
case sy_type:
|
||||
case sy_expr:
|
||||
case sy_class:
|
||||
internal_error (expr, "invalid operand type");
|
||||
}
|
||||
break;
|
||||
case op_def:
|
||||
return op->o.def;
|
||||
case op_value:
|
||||
return get_value_def (op->o.value, op->type);
|
||||
case op_label:
|
||||
|
@ -108,22 +91,11 @@ get_operand_def (expr_t *expr, operand_t *op)
|
|||
zero_def.type = &type_short;
|
||||
return &zero_def; //FIXME
|
||||
case op_temp:
|
||||
while (op->o.tempop.alias)
|
||||
op = op->o.tempop.alias;
|
||||
if (!op->o.tempop.def)
|
||||
op->o.tempop.def = temp_def (op->type, op->size);
|
||||
return op->o.tempop.def;
|
||||
case op_pointer:
|
||||
def = op->o.value->v.pointer.def;
|
||||
if (op->o.value->v.pointer.val || op->type != def->type->type) {
|
||||
def = alias_def (def, ev_types[op->type],
|
||||
op->o.value->v.pointer.val);
|
||||
}
|
||||
return def;
|
||||
case op_alias:
|
||||
def = get_operand_def (expr, op->o.alias);
|
||||
if (def->alias)
|
||||
def = def->alias;
|
||||
def = alias_def (def, ev_types[op->type], 0);
|
||||
return def;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -172,10 +144,10 @@ add_statement_op_ref (operand_t *op, dstatement_t *st, int field)
|
|||
static void
|
||||
use_tempop (operand_t *op, expr_t *expr)
|
||||
{
|
||||
while (op && op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (!op || op->op_type != op_temp)
|
||||
return;
|
||||
while (op->o.tempop.alias)
|
||||
op = op->o.tempop.alias;
|
||||
if (--op->o.tempop.users == 0)
|
||||
free_temp_def (op->o.tempop.def);
|
||||
if (op->o.tempop.users <= -1)
|
||||
|
|
|
@ -64,15 +64,15 @@ static struct {
|
|||
const char *name;
|
||||
operand_t op;
|
||||
} flow_params[] = {
|
||||
{".return", {0, op_symbol}},
|
||||
{".param_0", {0, op_symbol}},
|
||||
{".param_1", {0, op_symbol}},
|
||||
{".param_2", {0, op_symbol}},
|
||||
{".param_3", {0, op_symbol}},
|
||||
{".param_4", {0, op_symbol}},
|
||||
{".param_5", {0, op_symbol}},
|
||||
{".param_6", {0, op_symbol}},
|
||||
{".param_7", {0, op_symbol}},
|
||||
{".return", {0, op_def}},
|
||||
{".param_0", {0, op_def}},
|
||||
{".param_1", {0, op_def}},
|
||||
{".param_2", {0, op_def}},
|
||||
{".param_3", {0, op_def}},
|
||||
{".param_4", {0, op_def}},
|
||||
{".param_5", {0, op_def}},
|
||||
{".param_6", {0, op_def}},
|
||||
{".param_7", {0, op_def}},
|
||||
};
|
||||
static const int num_flow_params = sizeof(flow_params)/sizeof(flow_params[0]);
|
||||
|
||||
|
@ -156,36 +156,27 @@ flowvar_get_def (flowvar_t *var)
|
|||
{
|
||||
operand_t *op = var->op;
|
||||
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
switch (op->op_type) {
|
||||
case op_symbol:
|
||||
return op->o.symbol->s.def;
|
||||
case op_def:
|
||||
return op->o.def;
|
||||
case op_value:
|
||||
case op_label:
|
||||
return 0;
|
||||
case op_temp:
|
||||
return op->o.tempop.def;
|
||||
case op_pointer:
|
||||
return op->o.value->v.pointer.def;
|
||||
case op_alias:
|
||||
internal_error (0, "oops, blue pill");
|
||||
}
|
||||
internal_error (0, "oops, blue pill");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
flowvar_is_global (flowvar_t *var)
|
||||
{
|
||||
symbol_t *sym;
|
||||
def_t *def;
|
||||
|
||||
if (var->op->op_type != op_symbol)
|
||||
if (var->op->op_type != op_def)
|
||||
return 0;
|
||||
sym = var->op->o.symbol;
|
||||
if (sym->sy_type != sy_var)
|
||||
return 0;
|
||||
def = sym->s.def;
|
||||
def = var->op->o.def;
|
||||
if (def->local)
|
||||
return 0;
|
||||
return 1;
|
||||
|
@ -194,15 +185,11 @@ flowvar_is_global (flowvar_t *var)
|
|||
static int
|
||||
flowvar_is_param (flowvar_t *var)
|
||||
{
|
||||
symbol_t *sym;
|
||||
def_t *def;
|
||||
|
||||
if (var->op->op_type != op_symbol)
|
||||
if (var->op->op_type != op_def)
|
||||
return 0;
|
||||
sym = var->op->o.symbol;
|
||||
if (sym->sy_type != sy_var)
|
||||
return 0;
|
||||
def = sym->s.def;
|
||||
def = var->op->o.def;
|
||||
if (!def->local)
|
||||
return 0;
|
||||
if (!def->param)
|
||||
|
@ -213,15 +200,11 @@ flowvar_is_param (flowvar_t *var)
|
|||
static int
|
||||
flowvar_is_initialized (flowvar_t *var)
|
||||
{
|
||||
symbol_t *sym;
|
||||
def_t *def;
|
||||
|
||||
if (var->op->op_type != op_symbol)
|
||||
if (var->op->op_type != op_def)
|
||||
return 0;
|
||||
sym = var->op->o.symbol;
|
||||
if (sym->sy_type != sy_var)
|
||||
return 0;
|
||||
def = sym->s.def;
|
||||
def = var->op->o.def;
|
||||
return def->initialized;
|
||||
}
|
||||
|
||||
|
@ -231,18 +214,15 @@ flow_get_var (operand_t *op)
|
|||
if (!op)
|
||||
return 0;
|
||||
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
|
||||
if (op->op_type == op_temp) {
|
||||
if (!op->o.tempop.flowvar)
|
||||
op->o.tempop.flowvar = new_flowvar ();
|
||||
return op->o.tempop.flowvar;
|
||||
}
|
||||
if (op->op_type == op_symbol && op->o.symbol->sy_type == sy_var) {
|
||||
if (!op->o.symbol->flowvar)
|
||||
op->o.symbol->flowvar = new_flowvar ();
|
||||
return op->o.symbol->flowvar;
|
||||
if (op->op_type == op_def) {
|
||||
if (!op->o.def->flowvar)
|
||||
op->o.def->flowvar = new_flowvar ();
|
||||
return op->o.def->flowvar;
|
||||
}
|
||||
//FIXME functions? (some are variable) values?
|
||||
return 0;
|
||||
|
@ -283,8 +263,6 @@ add_operand (function_t *func, operand_t *op)
|
|||
|
||||
if (!op)
|
||||
return;
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (op->op_type == op_label)
|
||||
return;
|
||||
|
||||
|
@ -319,7 +297,7 @@ flow_build_vars (function_t *func)
|
|||
|
||||
// first, count .return and .param_[0-7] as they are always needed
|
||||
for (i = 0; i < num_flow_params; i++) {
|
||||
flow_params[i].op.o.symbol = param_symbol (flow_params[i].name);
|
||||
flow_params[i].op.o.def = param_symbol (flow_params[i].name)->s.def;
|
||||
num_vars += count_operand (&flow_params[i].op);
|
||||
}
|
||||
// then run through the statements in the function looking for accessed
|
||||
|
@ -561,10 +539,8 @@ get_function_type (operand_t *op)
|
|||
type_t *type = &type_void;
|
||||
|
||||
//FIXME fuction type casts?
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (op->op_type == op_symbol) {
|
||||
type = op->o.symbol->type;
|
||||
if (op->op_type == op_def) {
|
||||
type = op->o.def->type;
|
||||
if (type->type != ev_func)
|
||||
internal_error (0, "not a function symbol");
|
||||
type = type->t.func.type;
|
||||
|
|
|
@ -55,16 +55,29 @@
|
|||
#include "type.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
static const char *op_type_names[] = {
|
||||
"op_def",
|
||||
"op_value",
|
||||
"op_label",
|
||||
"op_temp",
|
||||
};
|
||||
|
||||
const char *
|
||||
optype_str (op_type_e type)
|
||||
{
|
||||
if (type < 0 || type > op_temp)
|
||||
return "<invalid op_type>";
|
||||
return op_type_names[type];
|
||||
}
|
||||
|
||||
const char *
|
||||
operand_string (operand_t *op)
|
||||
{
|
||||
type_t *type;
|
||||
|
||||
if (!op)
|
||||
return "";
|
||||
switch (op->op_type) {
|
||||
case op_symbol:
|
||||
return op->o.symbol->name;
|
||||
case op_def:
|
||||
return op->o.def->name;
|
||||
case op_value:
|
||||
switch (op->o.value->type) {
|
||||
case ev_string:
|
||||
|
@ -108,20 +121,9 @@ operand_string (operand_t *op)
|
|||
case op_label:
|
||||
return op->o.label->name;
|
||||
case op_temp:
|
||||
while (op->o.tempop.alias)
|
||||
op = op->o.tempop.alias;
|
||||
return va ("<tmp %p:%d>", op, op->o.tempop.users);
|
||||
case op_pointer:
|
||||
type = op->o.value->v.pointer.type;
|
||||
if (op->o.value->v.pointer.def)
|
||||
return va ("(%s)[%d]<%s>",
|
||||
type ? pr_type_name[type->type] : "???",
|
||||
op->o.value->v.pointer.val,
|
||||
op->o.value->v.pointer.def->name);
|
||||
else
|
||||
return va ("(%s)[%d]",
|
||||
type ? pr_type_name[type->type] : "???",
|
||||
op->o.value->v.pointer.val);
|
||||
case op_alias:
|
||||
return operand_string (op->o.alias);//FIXME better output
|
||||
}
|
||||
return ("??");
|
||||
}
|
||||
|
@ -130,9 +132,9 @@ static void
|
|||
print_operand (operand_t *op)
|
||||
{
|
||||
switch (op->op_type) {
|
||||
case op_symbol:
|
||||
case op_def:
|
||||
printf ("(%s) ", pr_type_name[op->type]);
|
||||
printf ("%s", op->o.symbol->name);
|
||||
printf ("%s", op->o.def->name);
|
||||
break;
|
||||
case op_value:
|
||||
printf ("(%s) ", pr_type_name[op->type]);
|
||||
|
@ -187,15 +189,6 @@ print_operand (operand_t *op)
|
|||
if (op->o.tempop.def)
|
||||
printf (" %s", op->o.tempop.def->name);
|
||||
break;
|
||||
case op_pointer:
|
||||
printf ("ptr (%s)[%d]",
|
||||
pr_type_name[op->o.value->v.pointer.type->type],
|
||||
op->o.value->v.pointer.val);
|
||||
break;
|
||||
case op_alias:
|
||||
printf ("alias %s ", pr_type_name[op->type]);
|
||||
print_operand (op->o.alias);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,14 +252,6 @@ new_operand (op_type_e op)
|
|||
static void __attribute__((unused)) //FIXME
|
||||
free_operand (operand_t *op)
|
||||
{
|
||||
if (op->next) {
|
||||
//FIXME this should be an error, but due to the way operands are used,
|
||||
//it can happen.
|
||||
debug (0, "free_operand: double free");
|
||||
return;
|
||||
}
|
||||
if (op->op_type == op_alias)
|
||||
free_operand (op->o.alias);
|
||||
FREE (operands, op);
|
||||
}
|
||||
|
||||
|
@ -304,16 +289,6 @@ temp_operand (type_t *type)
|
|||
return op;
|
||||
}
|
||||
|
||||
operand_t *
|
||||
alias_operand (operand_t *op, etype_t type)
|
||||
{
|
||||
operand_t *alias = new_operand (op_alias);
|
||||
alias->type = type;
|
||||
alias->size = pr_type_size[type];
|
||||
alias->o.alias = op;
|
||||
return alias;
|
||||
}
|
||||
|
||||
static operand_t *
|
||||
short_operand (short short_val)
|
||||
{
|
||||
|
@ -433,7 +408,7 @@ statement_get_targetlist (statement_t *s)
|
|||
} else if (statement_is_goto (s)) {
|
||||
count = 1;
|
||||
} else if (statement_is_jumpb (s)) {
|
||||
table = s->opa->o.alias->o.symbol->s.def; //FIXME check!!!
|
||||
table = s->opa->o.def;
|
||||
count = table->type->t.array.size;
|
||||
}
|
||||
target_list = malloc ((count + 1) * sizeof (sblock_t *));
|
||||
|
@ -709,9 +684,11 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
|
|||
e = deref->e.expr.e1;
|
||||
if (e->type == ex_uexpr && e->e.expr.op == '&'
|
||||
&& e->e.expr.e1->type == ex_symbol) {
|
||||
*op = new_operand (op_symbol);
|
||||
if (e->e.expr.e1->e.symbol->sy_type != sy_var)
|
||||
internal_error (e, "address of non-var");
|
||||
*op = new_operand (op_def);
|
||||
(*op)->type = low_level_type (type);
|
||||
(*op)->o.symbol = e->e.expr.e1->e.symbol;
|
||||
(*op)->o.def = e->e.expr.e1->e.symbol->s.def;
|
||||
} else if (e->type == ex_expr && e->e.expr.op == '&') {
|
||||
statement_t *s;
|
||||
operand_t *ptr = 0;
|
||||
|
@ -746,9 +723,10 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
|
|||
sblock_add_statement (sblock, s);
|
||||
}
|
||||
} else if (e->type == ex_value && e->e.value->type == ev_pointer) {
|
||||
*op = new_operand (op_pointer);
|
||||
(*op)->type = low_level_type (e->e.value->v.pointer.type);
|
||||
(*op)->o.value = e->e.value;
|
||||
ex_pointer_t *ptr = &e->e.value->v.pointer;
|
||||
*op = new_operand (op_def);
|
||||
(*op)->type = low_level_type (ptr->type);
|
||||
(*op)->o.def = alias_def (ptr->def, ptr->type, ptr->val);
|
||||
} else {
|
||||
statement_t *s;
|
||||
operand_t *ptr = 0;
|
||||
|
@ -813,12 +791,33 @@ static sblock_t *
|
|||
expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
operand_t *aop = 0;
|
||||
def_t *def;
|
||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &aop);
|
||||
while (aop->op_type == op_alias)
|
||||
aop = aop->o.alias;
|
||||
*op = new_operand (op_alias);
|
||||
(*op)->type = low_level_type (e->e.expr.type);
|
||||
(*op)->o.alias = aop;
|
||||
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");
|
||||
}
|
||||
*op = new_operand (op_temp);
|
||||
(*op)->type = low_level_type (e->e.expr.type);
|
||||
(*op)->o.tempop.alias = aop;
|
||||
} else if (aop->op_type == op_def) {
|
||||
def = aop->o.def;
|
||||
while (def->alias)
|
||||
def = def->alias;
|
||||
*op = new_operand (op_def);
|
||||
(*op)->type = low_level_type (e->e.expr.type);
|
||||
(*op)->o.def = alias_def (def, ev_types[(*op)->type], 0);
|
||||
} else if (aop->op_type == op_value && aop->o.value->type == ev_pointer) {
|
||||
ex_pointer_t *ptr = &aop->o.value->v.pointer;
|
||||
*op = new_operand (op_def);
|
||||
(*op)->type = low_level_type (ptr->type);
|
||||
(*op)->o.def = alias_def (ptr->def, ptr->type, ptr->val);
|
||||
} else {
|
||||
internal_error (e, "invalid alias target: %s: %s",
|
||||
optype_str (aop->op_type), operand_string (aop));
|
||||
}
|
||||
return sblock;
|
||||
}
|
||||
|
||||
|
@ -901,9 +900,24 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
static sblock_t *
|
||||
expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
*op = new_operand (op_symbol);
|
||||
(*op)->type = low_level_type (e->e.symbol->type);
|
||||
(*op)->o.symbol = e->e.symbol;
|
||||
symbol_t *sym = e->e.symbol;
|
||||
|
||||
if (sym->sy_type == sy_var) {
|
||||
*op = new_operand (op_def);
|
||||
(*op)->type = low_level_type (sym->type);
|
||||
(*op)->o.def = sym->s.def;
|
||||
} else if (sym->sy_type == sy_const) {
|
||||
*op = new_operand (op_value);
|
||||
(*op)->type = sym->s.value->type;
|
||||
(*op)->o.value = sym->s.value;
|
||||
} else if (sym->sy_type == sy_func) {
|
||||
*op = new_operand (op_def);
|
||||
(*op)->type = ev_func;
|
||||
(*op)->o.def = sym->s.func->def;
|
||||
} else {
|
||||
internal_error (e, "unexpected symbol type: %s",
|
||||
symtype_str(sym->sy_type));
|
||||
}
|
||||
return sblock;
|
||||
}
|
||||
|
||||
|
@ -1463,6 +1477,7 @@ check_final_block (sblock_t *sblock)
|
|||
{
|
||||
statement_t *s;
|
||||
symbol_t *return_symbol = 0;
|
||||
def_t *return_def = 0;
|
||||
operand_t *return_operand = 0;
|
||||
const char *return_opcode = "<RETURN_V>";
|
||||
|
||||
|
@ -1482,12 +1497,13 @@ check_final_block (sblock_t *sblock)
|
|||
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
|
||||
return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
|
||||
sc_extern);
|
||||
return_def = return_symbol->s.def;
|
||||
return_opcode = "<RETURN>";
|
||||
}
|
||||
if (return_symbol) {
|
||||
return_operand = new_operand (op_symbol);
|
||||
return_operand = new_operand (op_def);
|
||||
return_operand->type = ev_void;
|
||||
return_operand->o.symbol = return_symbol;
|
||||
return_operand->o.def = return_def;
|
||||
}
|
||||
s = new_statement (st_func, return_opcode, 0);
|
||||
s->opa = return_operand;
|
||||
|
@ -1529,10 +1545,11 @@ count_temp (operand_t *op)
|
|||
{
|
||||
if (!op)
|
||||
return;
|
||||
while (op->op_type == op_alias)
|
||||
op = op->o.alias;
|
||||
if (op->op_type == op_temp)
|
||||
if (op->op_type == op_temp) {
|
||||
while (op->o.tempop.alias)
|
||||
op = op->o.tempop.alias;
|
||||
op->o.tempop.users++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue