mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
break the emit_* functions out of expr.c into emit.c
This commit is contained in:
parent
7718ca4c96
commit
28b1598e7e
4 changed files with 380 additions and 366 deletions
|
@ -56,6 +56,12 @@ typedef struct expr_s {
|
||||||
} e;
|
} e;
|
||||||
} expr_t;
|
} expr_t;
|
||||||
|
|
||||||
|
extern etype_t qc_types[];
|
||||||
|
extern struct type_s *types[];
|
||||||
|
extern expr_type expr_types[];
|
||||||
|
|
||||||
|
etype_t get_type (expr_t *e);
|
||||||
|
|
||||||
expr_t *new_expr (void);
|
expr_t *new_expr (void);
|
||||||
expr_t *new_label_expr (void);
|
expr_t *new_label_expr (void);
|
||||||
expr_t *new_block_expr (void);
|
expr_t *new_block_expr (void);
|
||||||
|
|
|
@ -34,7 +34,7 @@ YFLAGS = -d
|
||||||
bin_PROGRAMS= qfcc
|
bin_PROGRAMS= qfcc
|
||||||
|
|
||||||
if NEW_PARSER
|
if NEW_PARSER
|
||||||
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l expr.c
|
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c
|
||||||
else
|
else
|
||||||
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c
|
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c
|
||||||
endif
|
endif
|
||||||
|
|
369
tools/qfcc/source/emit.c
Normal file
369
tools/qfcc/source/emit.c
Normal file
|
@ -0,0 +1,369 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <QF/mathlib.h>
|
||||||
|
#include <QF/va.h>
|
||||||
|
|
||||||
|
#include "qfcc.h"
|
||||||
|
#include "scope.h"
|
||||||
|
#include "qc-parse.h"
|
||||||
|
|
||||||
|
def_t *
|
||||||
|
emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
|
||||||
|
{
|
||||||
|
dstatement_t *statement;
|
||||||
|
def_t *ret;
|
||||||
|
|
||||||
|
if (!op) {
|
||||||
|
expr_t e;
|
||||||
|
e.line = sline;
|
||||||
|
e.file = s_file;
|
||||||
|
error (&e, "ice ice baby\n");
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
if (options.debug) {
|
||||||
|
int line = sline - lineno_base;
|
||||||
|
|
||||||
|
if (line != linenos[num_linenos - 1].line) {
|
||||||
|
pr_lineno_t *lineno = new_lineno ();
|
||||||
|
lineno->line = line;
|
||||||
|
lineno->fa.addr = numstatements;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statement = &statements[numstatements];
|
||||||
|
numstatements++;
|
||||||
|
statement_linenums[statement - statements] = pr_source_line;
|
||||||
|
statement->op = op->opcode;
|
||||||
|
statement->a = var_a ? var_a->ofs : 0;
|
||||||
|
statement->b = var_b ? var_b->ofs : 0;
|
||||||
|
if (op->type_c == ev_void || op->right_associative) {
|
||||||
|
// ifs, gotos, and assignments don't need vars allocated
|
||||||
|
var_c = NULL;
|
||||||
|
statement->c = 0;
|
||||||
|
ret = var_a;
|
||||||
|
} else { // allocate result space
|
||||||
|
if (!var_c)
|
||||||
|
var_c = PR_GetTempDef (types[op->type_c], pr_scope);
|
||||||
|
statement->c = var_c->ofs;
|
||||||
|
ret = var_c;
|
||||||
|
}
|
||||||
|
PR_AddStatementRef (var_a, statement, 0);
|
||||||
|
PR_AddStatementRef (var_b, statement, 1);
|
||||||
|
PR_AddStatementRef (var_c, statement, 2);
|
||||||
|
|
||||||
|
if (op->right_associative)
|
||||||
|
return var_a;
|
||||||
|
return var_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
def_t *emit_sub_expr (expr_t *e, def_t *dest);
|
||||||
|
|
||||||
|
void
|
||||||
|
emit_branch (int line, opcode_t *op, expr_t *e, expr_t *l)
|
||||||
|
{
|
||||||
|
dstatement_t *st;
|
||||||
|
statref_t *ref;
|
||||||
|
def_t *def = 0;
|
||||||
|
|
||||||
|
if (e)
|
||||||
|
def = emit_sub_expr (e, 0);
|
||||||
|
st = &statements[numstatements];
|
||||||
|
emit_statement (line, op, def, 0, 0);
|
||||||
|
if (l->e.label.statement) {
|
||||||
|
if (op == op_goto)
|
||||||
|
st->a = l->e.label.statement - st;
|
||||||
|
else
|
||||||
|
st->b = l->e.label.statement - st;
|
||||||
|
} else {
|
||||||
|
ref = PR_NewStatref (st, op != op_goto);
|
||||||
|
ref->next = l->e.label.refs;
|
||||||
|
l->e.label.refs = ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def_t *
|
||||||
|
emit_function_call (expr_t *e, def_t *dest)
|
||||||
|
{
|
||||||
|
def_t *func = emit_sub_expr (e->e.expr.e1, 0);
|
||||||
|
def_t parm;
|
||||||
|
def_t *arg;
|
||||||
|
expr_t *earg;
|
||||||
|
opcode_t *op;
|
||||||
|
int count = 0, ind;
|
||||||
|
|
||||||
|
for (earg = e->e.expr.e2; earg; earg = earg->next)
|
||||||
|
count++;
|
||||||
|
ind = count;
|
||||||
|
for (earg = e->e.expr.e2; earg; earg = earg->next) {
|
||||||
|
ind--;
|
||||||
|
parm = def_parms[ind];
|
||||||
|
parm.type = types[get_type (earg)];
|
||||||
|
arg = emit_sub_expr (earg, &parm);
|
||||||
|
if (earg->type != ex_expr) {
|
||||||
|
op = PR_Opcode_Find ("=", 5, arg, &parm, &parm);
|
||||||
|
emit_statement (e->line, op, arg, &parm, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
op = PR_Opcode_Find (va ("<CALL%d>", count), -1, &def_function, &def_void, &def_void);
|
||||||
|
emit_statement (e->line, op, func, 0, 0);
|
||||||
|
|
||||||
|
def_ret.type = func->type->aux_type;
|
||||||
|
if (dest) {
|
||||||
|
op = PR_Opcode_Find ("=", 5, dest, &def_ret, &def_ret);
|
||||||
|
emit_statement (e->line, op, &def_ret, dest, 0);
|
||||||
|
return dest;
|
||||||
|
} else {
|
||||||
|
return &def_ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def_t *
|
||||||
|
emit_assign_expr (expr_t *e)
|
||||||
|
{
|
||||||
|
def_t *def_a, *def_b;
|
||||||
|
opcode_t *op;
|
||||||
|
expr_t *e1 = e->e.expr.e1;
|
||||||
|
expr_t *e2 = e->e.expr.e2;
|
||||||
|
|
||||||
|
def_a = emit_sub_expr (e1, 0);
|
||||||
|
if (def_a->type == &type_pointer) {
|
||||||
|
def_b = emit_sub_expr (e2, 0);
|
||||||
|
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
|
||||||
|
emit_statement (e->line, op, def_b, def_a, 0);
|
||||||
|
} else {
|
||||||
|
if (def_a->initialized) {
|
||||||
|
if (options.cow) {
|
||||||
|
int size = type_size [def_a->type->type];
|
||||||
|
int ofs = PR_NewLocation (def_a->type);
|
||||||
|
memcpy (pr_globals + ofs, pr_globals + def_a->ofs, size);
|
||||||
|
def_a->ofs = ofs;
|
||||||
|
def_a->initialized = 0;
|
||||||
|
warning (e1, "assignment to constant %s", def_a->name);
|
||||||
|
} else {
|
||||||
|
error (e1, "assignment to constant %s", def_a->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def_b = emit_sub_expr (e2, def_a);
|
||||||
|
if (def_b != def_a) {
|
||||||
|
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
|
||||||
|
emit_statement (e->line, op, def_b, def_a, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return def_b;
|
||||||
|
}
|
||||||
|
|
||||||
|
def_t *
|
||||||
|
emit_sub_expr (expr_t *e, def_t *dest)
|
||||||
|
{
|
||||||
|
opcode_t *op;
|
||||||
|
char *operator;
|
||||||
|
def_t *def_a, *def_b;
|
||||||
|
int priority;
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
case ex_label:
|
||||||
|
case ex_block:
|
||||||
|
error (e, "internal error");
|
||||||
|
abort ();
|
||||||
|
case ex_expr:
|
||||||
|
if (e->e.expr.op == 'c')
|
||||||
|
return emit_function_call (e, dest);
|
||||||
|
if (e->e.expr.op == '=')
|
||||||
|
return emit_assign_expr (e);
|
||||||
|
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
||||||
|
def_b = emit_sub_expr (e->e.expr.e2, 0);
|
||||||
|
switch (e->e.expr.op) {
|
||||||
|
case AND:
|
||||||
|
operator = "&&";
|
||||||
|
priority = 6;
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
operator = "||";
|
||||||
|
priority = 6;
|
||||||
|
break;
|
||||||
|
case EQ:
|
||||||
|
operator = "==";
|
||||||
|
priority = 4;
|
||||||
|
break;
|
||||||
|
case NE:
|
||||||
|
operator = "!=";
|
||||||
|
priority = 4;
|
||||||
|
break;
|
||||||
|
case LE:
|
||||||
|
operator = "<=";
|
||||||
|
priority = 4;
|
||||||
|
break;
|
||||||
|
case GE:
|
||||||
|
operator = ">=";
|
||||||
|
priority = 4;
|
||||||
|
break;
|
||||||
|
case LT:
|
||||||
|
operator = "<";
|
||||||
|
priority = 4;
|
||||||
|
break;
|
||||||
|
case GT:
|
||||||
|
operator = ">";
|
||||||
|
priority = 4;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
operator = "+";
|
||||||
|
priority = 3;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
operator = "-";
|
||||||
|
priority = 3;
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
operator = "*";
|
||||||
|
priority = 2;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
operator = "/";
|
||||||
|
priority = 2;
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
operator = "&";
|
||||||
|
priority = 2;
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
operator = "|";
|
||||||
|
priority = 2;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
operator = ".";
|
||||||
|
priority = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
if (!dest)
|
||||||
|
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
||||||
|
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
|
||||||
|
return emit_statement (e->line, op, def_a, def_b, dest);
|
||||||
|
case ex_uexpr:
|
||||||
|
if (e->e.expr.op == '!') {
|
||||||
|
operator = "!";
|
||||||
|
priority = -1;
|
||||||
|
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
||||||
|
def_b = &def_void;
|
||||||
|
} else if (e->e.expr.op == '-') {
|
||||||
|
static expr_t zero;
|
||||||
|
|
||||||
|
zero.type = expr_types[get_type (e->e.expr.e1)];
|
||||||
|
|
||||||
|
operator = "-";
|
||||||
|
priority = 3;
|
||||||
|
def_a = PR_ReuseConstant (&zero, 0);
|
||||||
|
def_b = emit_sub_expr (e->e.expr.e1, 0);
|
||||||
|
if (!dest)
|
||||||
|
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
||||||
|
} else {
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
|
||||||
|
return emit_statement (e->line, op, def_a, def_b, dest);
|
||||||
|
case ex_def:
|
||||||
|
return e->e.def;
|
||||||
|
case ex_string:
|
||||||
|
case ex_float:
|
||||||
|
case ex_vector:
|
||||||
|
case ex_entity:
|
||||||
|
case ex_field:
|
||||||
|
case ex_func:
|
||||||
|
case ex_pointer:
|
||||||
|
case ex_quaternion:
|
||||||
|
case ex_integer:
|
||||||
|
return PR_ReuseConstant (e, 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
emit_expr (expr_t *e)
|
||||||
|
{
|
||||||
|
def_t *def;
|
||||||
|
def_t *def_a;
|
||||||
|
def_t *def_b;
|
||||||
|
statref_t *ref;
|
||||||
|
label_t *label;
|
||||||
|
//opcode_t *op;
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
case ex_label:
|
||||||
|
label = &e->e.label;
|
||||||
|
label->statement = &statements[numstatements];
|
||||||
|
for (ref = label->refs; ref; ref = ref->next) {
|
||||||
|
switch (ref->field) {
|
||||||
|
case 0:
|
||||||
|
ref->statement->a = label->statement - ref->statement;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ref->statement->b = label->statement - ref->statement;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ref->statement->c = label->statement - ref->statement;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ex_block:
|
||||||
|
for (e = e->e.block.head; e; e = e->next)
|
||||||
|
emit_expr (e);
|
||||||
|
break;
|
||||||
|
case ex_expr:
|
||||||
|
switch (e->e.expr.op) {
|
||||||
|
case '=':
|
||||||
|
emit_assign_expr (e);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
emit_branch (e->line, op_ifnot, e->e.expr.e1, e->e.expr.e2);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
emit_branch (e->line, op_if, e->e.expr.e1, e->e.expr.e2);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
emit_function_call (e, 0);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
||||||
|
def_b = emit_sub_expr (e->e.expr.e2, 0);
|
||||||
|
emit_statement (e->line, op_state, def_a, def_b, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warning (e, "Ignoring useless expression");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ex_uexpr:
|
||||||
|
switch (e->e.expr.op) {
|
||||||
|
case 'r':
|
||||||
|
def = 0;
|
||||||
|
if (e->e.expr.e1)
|
||||||
|
def = emit_sub_expr (e->e.expr.e1, 0);
|
||||||
|
emit_statement (e->line, op_return, def, 0, 0);
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
emit_branch (e->line, op_goto, 0, e->e.expr.e1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warning (e, "Ignoring useless expression");
|
||||||
|
emit_expr (e->e.expr.e1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ex_def:
|
||||||
|
case ex_string:
|
||||||
|
case ex_float:
|
||||||
|
case ex_vector:
|
||||||
|
case ex_entity:
|
||||||
|
case ex_field:
|
||||||
|
case ex_func:
|
||||||
|
case ex_pointer:
|
||||||
|
case ex_quaternion:
|
||||||
|
case ex_integer:
|
||||||
|
warning (e, "Ignoring useless expression");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PR_FreeTempDefs ();
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ extern function_t *current_func;
|
||||||
|
|
||||||
int lineno_base;
|
int lineno_base;
|
||||||
|
|
||||||
static etype_t qc_types[] = {
|
etype_t qc_types[] = {
|
||||||
ev_void, // ex_label
|
ev_void, // ex_label
|
||||||
ev_void, // ex_block
|
ev_void, // ex_block
|
||||||
ev_void, // ex_expr
|
ev_void, // ex_expr
|
||||||
|
@ -29,7 +29,7 @@ static etype_t qc_types[] = {
|
||||||
ev_integer, // ex_integer
|
ev_integer, // ex_integer
|
||||||
};
|
};
|
||||||
|
|
||||||
static type_t *types[] = {
|
type_t *types[] = {
|
||||||
&type_void,
|
&type_void,
|
||||||
&type_string,
|
&type_string,
|
||||||
&type_float,
|
&type_float,
|
||||||
|
@ -42,7 +42,7 @@ static type_t *types[] = {
|
||||||
&type_integer,
|
&type_integer,
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type expr_types[] = {
|
expr_type expr_types[] = {
|
||||||
ex_label, // ev_void (ick)
|
ex_label, // ev_void (ick)
|
||||||
ex_string, // ev_string
|
ex_string, // ev_string
|
||||||
ex_float, // ev_float
|
ex_float, // ev_float
|
||||||
|
@ -68,7 +68,7 @@ static const char *type_names[] = {
|
||||||
"int",
|
"int",
|
||||||
};
|
};
|
||||||
|
|
||||||
static etype_t
|
etype_t
|
||||||
get_type (expr_t *e)
|
get_type (expr_t *e)
|
||||||
{
|
{
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
|
@ -952,364 +952,3 @@ return_expr (function_t *f, expr_t *e)
|
||||||
}
|
}
|
||||||
return new_unary_expr ('r', e);
|
return new_unary_expr ('r', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
def_t *
|
|
||||||
emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
|
|
||||||
{
|
|
||||||
dstatement_t *statement;
|
|
||||||
def_t *ret;
|
|
||||||
|
|
||||||
if (!op) {
|
|
||||||
expr_t e;
|
|
||||||
e.line = sline;
|
|
||||||
e.file = s_file;
|
|
||||||
error (&e, "ice ice baby\n");
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
if (options.debug) {
|
|
||||||
int line = sline - lineno_base;
|
|
||||||
|
|
||||||
if (line != linenos[num_linenos - 1].line) {
|
|
||||||
pr_lineno_t *lineno = new_lineno ();
|
|
||||||
lineno->line = line;
|
|
||||||
lineno->fa.addr = numstatements;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statement = &statements[numstatements];
|
|
||||||
numstatements++;
|
|
||||||
statement_linenums[statement - statements] = pr_source_line;
|
|
||||||
statement->op = op->opcode;
|
|
||||||
statement->a = var_a ? var_a->ofs : 0;
|
|
||||||
statement->b = var_b ? var_b->ofs : 0;
|
|
||||||
if (op->type_c == ev_void || op->right_associative) {
|
|
||||||
// ifs, gotos, and assignments don't need vars allocated
|
|
||||||
var_c = NULL;
|
|
||||||
statement->c = 0;
|
|
||||||
ret = var_a;
|
|
||||||
} else { // allocate result space
|
|
||||||
if (!var_c)
|
|
||||||
var_c = PR_GetTempDef (types[op->type_c], pr_scope);
|
|
||||||
statement->c = var_c->ofs;
|
|
||||||
ret = var_c;
|
|
||||||
}
|
|
||||||
PR_AddStatementRef (var_a, statement, 0);
|
|
||||||
PR_AddStatementRef (var_b, statement, 1);
|
|
||||||
PR_AddStatementRef (var_c, statement, 2);
|
|
||||||
|
|
||||||
if (op->right_associative)
|
|
||||||
return var_a;
|
|
||||||
return var_c;
|
|
||||||
}
|
|
||||||
|
|
||||||
def_t *emit_sub_expr (expr_t *e, def_t *dest);
|
|
||||||
|
|
||||||
void
|
|
||||||
emit_branch (int line, opcode_t *op, expr_t *e, expr_t *l)
|
|
||||||
{
|
|
||||||
dstatement_t *st;
|
|
||||||
statref_t *ref;
|
|
||||||
def_t *def = 0;
|
|
||||||
|
|
||||||
if (e)
|
|
||||||
def = emit_sub_expr (e, 0);
|
|
||||||
st = &statements[numstatements];
|
|
||||||
emit_statement (line, op, def, 0, 0);
|
|
||||||
if (l->e.label.statement) {
|
|
||||||
if (op == op_goto)
|
|
||||||
st->a = l->e.label.statement - st;
|
|
||||||
else
|
|
||||||
st->b = l->e.label.statement - st;
|
|
||||||
} else {
|
|
||||||
ref = PR_NewStatref (st, op != op_goto);
|
|
||||||
ref->next = l->e.label.refs;
|
|
||||||
l->e.label.refs = ref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def_t *
|
|
||||||
emit_function_call (expr_t *e, def_t *dest)
|
|
||||||
{
|
|
||||||
def_t *func = emit_sub_expr (e->e.expr.e1, 0);
|
|
||||||
def_t parm;
|
|
||||||
def_t *arg;
|
|
||||||
expr_t *earg;
|
|
||||||
opcode_t *op;
|
|
||||||
int count = 0, ind;
|
|
||||||
|
|
||||||
for (earg = e->e.expr.e2; earg; earg = earg->next)
|
|
||||||
count++;
|
|
||||||
ind = count;
|
|
||||||
for (earg = e->e.expr.e2; earg; earg = earg->next) {
|
|
||||||
ind--;
|
|
||||||
parm = def_parms[ind];
|
|
||||||
parm.type = types[get_type (earg)];
|
|
||||||
arg = emit_sub_expr (earg, &parm);
|
|
||||||
if (earg->type != ex_expr) {
|
|
||||||
op = PR_Opcode_Find ("=", 5, arg, &parm, &parm);
|
|
||||||
emit_statement (e->line, op, arg, &parm, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
op = PR_Opcode_Find (va ("<CALL%d>", count), -1, &def_function, &def_void, &def_void);
|
|
||||||
emit_statement (e->line, op, func, 0, 0);
|
|
||||||
|
|
||||||
def_ret.type = func->type->aux_type;
|
|
||||||
if (dest) {
|
|
||||||
op = PR_Opcode_Find ("=", 5, dest, &def_ret, &def_ret);
|
|
||||||
emit_statement (e->line, op, &def_ret, dest, 0);
|
|
||||||
return dest;
|
|
||||||
} else {
|
|
||||||
return &def_ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def_t *
|
|
||||||
emit_assign_expr (expr_t *e)
|
|
||||||
{
|
|
||||||
def_t *def_a, *def_b;
|
|
||||||
opcode_t *op;
|
|
||||||
expr_t *e1 = e->e.expr.e1;
|
|
||||||
expr_t *e2 = e->e.expr.e2;
|
|
||||||
|
|
||||||
def_a = emit_sub_expr (e1, 0);
|
|
||||||
if (def_a->type == &type_pointer) {
|
|
||||||
def_b = emit_sub_expr (e2, 0);
|
|
||||||
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
|
|
||||||
emit_statement (e->line, op, def_b, def_a, 0);
|
|
||||||
} else {
|
|
||||||
if (def_a->initialized) {
|
|
||||||
if (options.cow) {
|
|
||||||
int size = type_size [def_a->type->type];
|
|
||||||
int ofs = PR_NewLocation (def_a->type);
|
|
||||||
memcpy (pr_globals + ofs, pr_globals + def_a->ofs, size);
|
|
||||||
def_a->ofs = ofs;
|
|
||||||
def_a->initialized = 0;
|
|
||||||
warning (e1, "assignment to constant %s", def_a->name);
|
|
||||||
} else {
|
|
||||||
error (e1, "assignment to constant %s", def_a->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def_b = emit_sub_expr (e2, def_a);
|
|
||||||
if (def_b != def_a) {
|
|
||||||
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
|
|
||||||
emit_statement (e->line, op, def_b, def_a, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return def_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
def_t *
|
|
||||||
emit_sub_expr (expr_t *e, def_t *dest)
|
|
||||||
{
|
|
||||||
opcode_t *op;
|
|
||||||
char *operator;
|
|
||||||
def_t *def_a, *def_b;
|
|
||||||
int priority;
|
|
||||||
|
|
||||||
switch (e->type) {
|
|
||||||
case ex_label:
|
|
||||||
case ex_block:
|
|
||||||
error (e, "internal error");
|
|
||||||
abort ();
|
|
||||||
case ex_expr:
|
|
||||||
if (e->e.expr.op == 'c')
|
|
||||||
return emit_function_call (e, dest);
|
|
||||||
if (e->e.expr.op == '=')
|
|
||||||
return emit_assign_expr (e);
|
|
||||||
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
|
||||||
def_b = emit_sub_expr (e->e.expr.e2, 0);
|
|
||||||
switch (e->e.expr.op) {
|
|
||||||
case AND:
|
|
||||||
operator = "&&";
|
|
||||||
priority = 6;
|
|
||||||
break;
|
|
||||||
case OR:
|
|
||||||
operator = "||";
|
|
||||||
priority = 6;
|
|
||||||
break;
|
|
||||||
case EQ:
|
|
||||||
operator = "==";
|
|
||||||
priority = 4;
|
|
||||||
break;
|
|
||||||
case NE:
|
|
||||||
operator = "!=";
|
|
||||||
priority = 4;
|
|
||||||
break;
|
|
||||||
case LE:
|
|
||||||
operator = "<=";
|
|
||||||
priority = 4;
|
|
||||||
break;
|
|
||||||
case GE:
|
|
||||||
operator = ">=";
|
|
||||||
priority = 4;
|
|
||||||
break;
|
|
||||||
case LT:
|
|
||||||
operator = "<";
|
|
||||||
priority = 4;
|
|
||||||
break;
|
|
||||||
case GT:
|
|
||||||
operator = ">";
|
|
||||||
priority = 4;
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
operator = "+";
|
|
||||||
priority = 3;
|
|
||||||
break;
|
|
||||||
case '-':
|
|
||||||
operator = "-";
|
|
||||||
priority = 3;
|
|
||||||
break;
|
|
||||||
case '*':
|
|
||||||
operator = "*";
|
|
||||||
priority = 2;
|
|
||||||
break;
|
|
||||||
case '/':
|
|
||||||
operator = "/";
|
|
||||||
priority = 2;
|
|
||||||
break;
|
|
||||||
case '&':
|
|
||||||
operator = "&";
|
|
||||||
priority = 2;
|
|
||||||
break;
|
|
||||||
case '|':
|
|
||||||
operator = "|";
|
|
||||||
priority = 2;
|
|
||||||
break;
|
|
||||||
case '.':
|
|
||||||
operator = ".";
|
|
||||||
priority = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
if (!dest)
|
|
||||||
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
|
||||||
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
|
|
||||||
return emit_statement (e->line, op, def_a, def_b, dest);
|
|
||||||
case ex_uexpr:
|
|
||||||
if (e->e.expr.op == '!') {
|
|
||||||
operator = "!";
|
|
||||||
priority = -1;
|
|
||||||
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
|
||||||
def_b = &def_void;
|
|
||||||
} else if (e->e.expr.op == '-') {
|
|
||||||
static expr_t zero;
|
|
||||||
|
|
||||||
zero.type = expr_types[get_type (e->e.expr.e1)];
|
|
||||||
|
|
||||||
operator = "-";
|
|
||||||
priority = 3;
|
|
||||||
def_a = PR_ReuseConstant (&zero, 0);
|
|
||||||
def_b = emit_sub_expr (e->e.expr.e1, 0);
|
|
||||||
if (!dest)
|
|
||||||
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
|
||||||
} else {
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
|
|
||||||
return emit_statement (e->line, op, def_a, def_b, dest);
|
|
||||||
case ex_def:
|
|
||||||
return e->e.def;
|
|
||||||
case ex_string:
|
|
||||||
case ex_float:
|
|
||||||
case ex_vector:
|
|
||||||
case ex_entity:
|
|
||||||
case ex_field:
|
|
||||||
case ex_func:
|
|
||||||
case ex_pointer:
|
|
||||||
case ex_quaternion:
|
|
||||||
case ex_integer:
|
|
||||||
return PR_ReuseConstant (e, 0);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
emit_expr (expr_t *e)
|
|
||||||
{
|
|
||||||
def_t *def;
|
|
||||||
def_t *def_a;
|
|
||||||
def_t *def_b;
|
|
||||||
statref_t *ref;
|
|
||||||
label_t *label;
|
|
||||||
//opcode_t *op;
|
|
||||||
|
|
||||||
switch (e->type) {
|
|
||||||
case ex_label:
|
|
||||||
label = &e->e.label;
|
|
||||||
label->statement = &statements[numstatements];
|
|
||||||
for (ref = label->refs; ref; ref = ref->next) {
|
|
||||||
switch (ref->field) {
|
|
||||||
case 0:
|
|
||||||
ref->statement->a = label->statement - ref->statement;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ref->statement->b = label->statement - ref->statement;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ref->statement->c = label->statement - ref->statement;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ex_block:
|
|
||||||
for (e = e->e.block.head; e; e = e->next)
|
|
||||||
emit_expr (e);
|
|
||||||
break;
|
|
||||||
case ex_expr:
|
|
||||||
switch (e->e.expr.op) {
|
|
||||||
case '=':
|
|
||||||
emit_assign_expr (e);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
emit_branch (e->line, op_ifnot, e->e.expr.e1, e->e.expr.e2);
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
emit_branch (e->line, op_if, e->e.expr.e1, e->e.expr.e2);
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
emit_function_call (e, 0);
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
|
||||||
def_b = emit_sub_expr (e->e.expr.e2, 0);
|
|
||||||
emit_statement (e->line, op_state, def_a, def_b, 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warning (e, "Ignoring useless expression");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ex_uexpr:
|
|
||||||
switch (e->e.expr.op) {
|
|
||||||
case 'r':
|
|
||||||
def = 0;
|
|
||||||
if (e->e.expr.e1)
|
|
||||||
def = emit_sub_expr (e->e.expr.e1, 0);
|
|
||||||
emit_statement (e->line, op_return, def, 0, 0);
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
emit_branch (e->line, op_goto, 0, e->e.expr.e1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warning (e, "Ignoring useless expression");
|
|
||||||
emit_expr (e->e.expr.e1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ex_def:
|
|
||||||
case ex_string:
|
|
||||||
case ex_float:
|
|
||||||
case ex_vector:
|
|
||||||
case ex_entity:
|
|
||||||
case ex_field:
|
|
||||||
case ex_func:
|
|
||||||
case ex_pointer:
|
|
||||||
case ex_quaternion:
|
|
||||||
case ex_integer:
|
|
||||||
warning (e, "Ignoring useless expression");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
PR_FreeTempDefs ();
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue