start on actually generating code. doesn't work yet (getting a weird type

redeclaration error and not all expressions are handled yet).
This commit is contained in:
Bill Currie 2001-06-26 07:21:20 +00:00
parent e99796c4cf
commit c1753046a9
8 changed files with 378 additions and 6 deletions

View file

@ -55,3 +55,5 @@ void print_expr (expr_t *e);
expr_t *binary_expr (int op, expr_t *e1, expr_t *e2);
expr_t *unary_expr (int op, expr_t *e);
expr_t *function_expr (expr_t *e1, expr_t *e2);
void emit_expr (expr_t *e);

View file

@ -329,6 +329,7 @@ extern type_t type_field;
extern type_t type_function;
extern type_t type_pointer;
extern type_t type_floatfield;
extern type_t type_quaternion;
extern def_t def_void;
extern def_t def_string;
@ -338,6 +339,7 @@ extern def_t def_entity;
extern def_t def_field;
extern def_t def_function;
extern def_t def_pointer;
extern def_t def_quaternion;
struct function_s
{
@ -390,6 +392,8 @@ extern opcode_t *op_ifnot;
extern opcode_t *op_state;
extern opcode_t *op_goto;
statref_t *PR_NewStatref (dstatement_t *st, int field);
void PR_AddStatementRef (def_t *def, dstatement_t *st, int field);
def_t *PR_Statement (opcode_t *op, def_t *var_a, def_t *var_b);
opcode_t *PR_Opcode_Find (const char *name, int priority,
def_t *var_a, def_t *var_b, def_t *var_c);
@ -398,6 +402,8 @@ void PR_Opcode_Init (void);
//============================================================================
#include "expr.h"
extern qboolean pr_dumpasm;
@ -426,6 +432,7 @@ void PR_LexString (void);
type_t *PR_ParseType (void);
char *PR_ParseName (void);
def_t *PR_ParseImmediate (def_t *def);
def_t *PR_ReuseConstant (expr_t *expr, def_t *def);
qboolean PR_Check (token_type_t type, const char *string);
void PR_Expect (token_type_t type, const char *string);

View file

@ -1,9 +1,9 @@
#include <stdlib.h>
#include <QF/mathlib.h>
#include <QF/va.h>
#include "qfcc.h"
#include "expr.h"
#include "scope.h"
#include "qc-parse.h"
@ -34,6 +34,17 @@ static type_t *types[] = {
&type_pointer,
};
static expr_type expr_types[] = {
ex_label, // ev_void (ick)
ex_string, // ev_string
ex_float, // ev_float
ex_vector, // ev_vector
ex_label, // ev_entity (ick)
ex_label, // ev_field (ick)
ex_label, // ev_func (ick)
ex_label, // ev_pointer (ick)
};
static etype_t
get_type (expr_t *e)
{
@ -630,3 +641,242 @@ function_expr (expr_t *e1, expr_t *e2)
e->e.expr.e2 = e2;
return e;
}
def_t *
emit_statement (opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
{
dstatement_t *statement;
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 == &def_void || op->right_associative) {
// ifs, gotos, and assignments don't need vars allocated
var_c = NULL;
statement->c = 0;
} else { // allocate result space
if (!var_c)
var_c = PR_GetTempDef (op->type_c->type, pr_scope);
statement->c = var_c->ofs;
}
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);
def_t *
emit_function_call (expr_t *e, def_t *dest)
{
def_t *func = emit_sub_expr (e->e.expr.e1, 0);
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--;
arg = emit_sub_expr (earg, 0);
def_parms[ind].type = arg->type;
op = PR_Opcode_Find ("=", 5, arg, &def_parms[ind], &def_parms[ind]);
emit_statement (op, arg, &def_parms[ind], 0);
}
op = PR_Opcode_Find (va ("<CALL%d>", count), -1, &def_function, &def_void, &def_void);
emit_statement (op, func, 0, dest);
def_ret.type = func->type->aux_type;
return &def_ret;
}
def_t *
emit_sub_expr (expr_t *e, def_t *dest)
{
opcode_t *op;
char *operator;
def_t *def_a, *def_b;
int priority;
if (e->type == ex_expr && e->e.expr.op == 'c')
return emit_function_call (e, dest);
switch (e->type) {
default:
case ex_label:
case ex_block:
abort ();
case ex_expr:
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 '=':
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 ();
}
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
return emit_statement (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);
} else {
abort ();
}
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
return emit_statement (op, def_a, def_b, dest);
case ex_def:
return e->e.def;
case ex_int:
case ex_float:
case ex_string:
case ex_vector:
case ex_quaternion:
return PR_ReuseConstant (e, 0);
}
}
void
emit_expr (expr_t *e)
{
def_t *def;
statref_t *ref;
dstatement_t *st;
switch (e->type) {
case ex_label:
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 '=':
break;
case 'n':
break;
case 'i':
break;
case 'c':
break;
default:
fprintf (stderr,
"%s:%d: warning: unused expression ignored\n",
strings + s_file, pr_source_line);
}
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);
PR_Statement (op_return, def, 0);
return;
case 'g':
st = &statements[numstatements];
PR_Statement (op_goto, 0, 0);
if (e->e.label.statement) {
st->a = e->e.label.statement - st;
} else {
ref = PR_NewStatref (st, 0);
ref->next = e->e.label.refs;
e->e.label.refs = ref;
}
return;
}
case ex_def:
case ex_int:
case ex_float:
case ex_string:
case ex_vector:
case ex_quaternion:
fprintf (stderr, "%s:%d: warning: unused expression ignored\n",
strings + s_file, pr_source_line);
break;
}
}

View file

@ -27,6 +27,7 @@
static hashtab_t *string_imm_defs;
static hashtab_t *float_imm_defs;
static hashtab_t *vector_imm_defs;
static hashtab_t *quaternion_imm_defs;
static const char *
string_imm_get_key (void *_def, void *unused)
@ -54,6 +55,17 @@ vector_imm_get_key (void *_def, void *unused)
return rep;
}
static const char *
quaternion_imm_get_key (void *_def, void *unused)
{
def_t *def = (def_t*)_def;
static char rep[60];
sprintf (rep, "\001quaternion:%08X\001%08X\001%08X\001%08X\001",
G_INT(def->ofs), G_INT(def->ofs+1),
G_INT(def->ofs+2), G_INT(def->ofs+3));
return rep;
}
/*
PR_ParseImmediate
@ -131,3 +143,90 @@ PR_ParseImmediate (def_t *def)
return cn;
}
def_t *
PR_ReuseConstant (expr_t *e, def_t *def)
{
def_t *cn = 0;
char rep[60];
hashtab_t *tab = 0;
type_t *type;
if (!string_imm_defs) {
string_imm_defs = Hash_NewTable (16381, string_imm_get_key, 0, 0);
float_imm_defs = Hash_NewTable (16381, float_imm_get_key, 0, 0);
vector_imm_defs = Hash_NewTable (16381, vector_imm_get_key, 0, 0);
quaternion_imm_defs = Hash_NewTable (16381, quaternion_imm_get_key, 0, 0);
}
switch (e->type) {
case ex_int:
e->e.float_val = e->e.int_val; //FIXME
case ex_float:
sprintf (rep, "\001float:%08X\001", *(int*)&pr_immediate._float);
cn = (def_t*) Hash_Find (float_imm_defs, rep);
tab = float_imm_defs;
type = &type_float;
//printf ("%f\n",pr_immediate._float);
break;
case ex_string:
cn = (def_t*) Hash_Find (string_imm_defs, pr_immediate_string);
tab = string_imm_defs;
type = &type_string;
//printf ("%s\n",pr_immediate_string);
break;
case ex_vector:
sprintf (rep, "\001vector:%08X\001%08X\001%08X\001",
*(int*)&e->e.vector_val[0],
*(int*)&e->e.vector_val[1],
*(int*)&e->e.vector_val[2]);
cn = (def_t*) Hash_Find (vector_imm_defs, rep);
tab = vector_imm_defs;
type = &type_vector;
//printf ("%f %f %f\n",pr_immediate.vector[0], pr_immediate.vector[1], pr_immediate.vector[2]);
break;
case ex_quaternion:
sprintf (rep, "\001quaternion:%08X\001%08X\001%08X\001%08X\001",
*(int*)&e->e.quaternion_val[0],
*(int*)&e->e.quaternion_val[1],
*(int*)&e->e.quaternion_val[2],
*(int*)&e->e.quaternion_val[3]);
cn = (def_t*) Hash_Find (quaternion_imm_defs, rep);
tab = vector_imm_defs;
type = &type_quaternion;
//printf ("%f %f %f\n",pr_immediate.vector[0], pr_immediate.vector[1], pr_immediate.vector[2]);
break;
default:
abort ();
}
if (cn) {
//printf("found\n");
if (def) {
PR_FreeLocation (def);
def->ofs = cn->ofs;
def->initialized = 1;
cn = def;
}
return cn;
}
// allocate a new one
// always share immediates
if (def) {
cn = def;
} else {
cn = PR_NewDef (pr_immediate_type, "IMMEDIATE", 0);
cn->ofs = PR_NewLocation (pr_immediate_type);
pr_global_defs[cn->ofs] = cn;
}
cn->initialized = 1;
// copy the immediate to the global area
if (e->type == ex_string)
e->e.int_val = CopyString (e->e.string_val);
memcpy (pr_globals + cn->ofs, &e->e, 4 * type_size[type->type]);
Hash_Add (tab, cn);
PR_Lex ();
return cn;
}

View file

@ -60,6 +60,7 @@ type_t type_field = { ev_field, &def_field };
// type_function is a void() function used for state defs
type_t type_function = { ev_func, &def_function, NULL, &type_void };
type_t type_pointer = { ev_pointer, &def_pointer };
type_t type_quaternion = { ev_quaternion, &def_quaternion };
type_t type_floatfield = { ev_field, &def_field, NULL, &type_float };
@ -73,6 +74,7 @@ def_t def_entity = { &type_entity, "temp" };
def_t def_field = { &type_field, "temp" };
def_t def_function = { &type_function, "temp" };
def_t def_pointer = { &type_pointer, "temp" };
def_t def_quaternion = { &type_quaternion, "temp"};
def_t def_ret, def_parms[MAX_PARMS];
@ -684,7 +686,9 @@ PR_ParseError (const char *error, ...)
printf ("%s:%i:%s\n", strings + s_file, pr_source_line, string);
#ifndef NEW_PARSER
longjmp (pr_parse_abort, 1);
#endif
}

View file

@ -131,15 +131,22 @@ opcode_t pr_opcodes[] = {
{"|", "BITOR", OP_BITOR, 2, false, &def_float, &def_float, &def_float, PROG_ID_VERSION},
};
statref_t *
PR_NewStatref (dstatement_t *st, int field)
{
statref_t *ref = calloc (1, sizeof (statref_t));
ref->statement = st;
ref->field = field;
return ref;
}
void
PR_AddStatementRef (def_t *def, dstatement_t *st, int field)
{
if (def) {
statref_t *ref = calloc (1, sizeof (statref_t));
statref_t *ref = PR_NewStatref (st, field);
ref->next = def->refs;
def->refs = ref;
ref->statement = st;
ref->field = field;
}
}

View file

@ -1,7 +1,6 @@
%{
#include <QF/hash.h>
#include "qfcc.h"
#include "expr.h"
#include "scope.h"
#include "qc-parse.h"

View file

@ -1,6 +1,5 @@
%{
#include "qfcc.h"
#include "expr.h"
#define YYDEBUG 1
#define YYERROR_VERBOSE 1
@ -538,6 +537,11 @@ build_function (function_t *f)
void
emit_function (function_t *f, expr_t *e)
{
pr_scope = f->def;
while (e) {
emit_expr (e);
e = e->next;
}
/*PR_PrintType (f->def->type);
printf (" %s =\n", f->def->name);
while (e) {