ok, structures seem to generate correct code now

This commit is contained in:
Bill Currie 2001-12-08 08:19:48 +00:00
parent 3293c5e85f
commit b03a1bee42
16 changed files with 236 additions and 34 deletions

View file

@ -39,6 +39,7 @@ typedef enum {
ev_integer,
ev_uinteger,
ev_short, // value is embedded in the opcode
ev_struct,
ev_type_count // not a type, gives number of types
} etype_t;
@ -236,6 +237,8 @@ typedef enum {
OP_STOREBI_FNC,
OP_STOREBI_I,
OP_STOREBI_P,
OP_LEAI,
} pr_opcode_e;
typedef struct

View file

@ -161,7 +161,7 @@ void ED_Count (progs_t *pr);
void PR_Profile (progs_t *pr);
char *PR_GlobalString (progs_t *pr, int ofs, etype_t type);
char *PR_GlobalStringNoContents (progs_t *pr, int ofs);
char *PR_GlobalStringNoContents (progs_t *pr, int ofs, etype_t type);
pr_type_t *GetEdictFieldValue(progs_t *pr, edict_t *ed, const char *field);

View file

@ -40,7 +40,6 @@ static const char rcsid[] =
#include <stdio.h>
#include "QF/cmd.h"
#include "compat.h"
#include "QF/crc.h"
#include "QF/cvar.h"
#include "QF/hash.h"
@ -52,6 +51,8 @@ static const char rcsid[] =
#include "QF/va.h"
#include "QF/vfs.h"
#include "compat.h"
cvar_t *pr_boundscheck;
cvar_t *pr_deadbeef_ents;
cvar_t *pr_deadbeef_locals;
@ -69,6 +70,7 @@ int pr_type_size[ev_type_count] = {
1,
1,
0, // value in opcode
1, // variable
};
const char *type_name[ev_type_count] = {
@ -84,6 +86,7 @@ const char *type_name[ev_type_count] = {
"integer",
"uinteger",
"short",
"struct",
};
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
@ -512,12 +515,16 @@ PR_GlobalString (progs_t * pr, int ofs, etype_t type)
}
char *
PR_GlobalStringNoContents (progs_t * pr, int ofs)
PR_GlobalStringNoContents (progs_t * pr, int ofs, etype_t type)
{
int i;
ddef_t *def = 0;
static char line[128];
if (type == ev_short) {
snprintf (line, sizeof (line), "%-20d", (short) ofs);
return line;
}
if (pr_debug->int_val && pr->debug)
def = PR_Get_Local_Def (pr, ofs);
if (!def)

View file

@ -86,13 +86,15 @@ PR_PrintStatement (progs_t * pr, dstatement_t *s)
if (op->type_c != ev_void)
Sys_Printf ("%s", PR_GlobalString (pr, s->b, op->type_b));
else
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->b));
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->b,
op->type_b));
}
if (op->type_c != ev_void) {
if (op->type_b == ev_pointer && op->type_c == ev_integer)
Sys_Printf ("%s", PR_GlobalString (pr, s->c, op->type_c));
else
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->c));
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->c,
op->type_c));
}
}
Sys_Printf ("\n");
@ -598,6 +600,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
OPC.integer_var = pointer;
break;
case OP_LEAI:
pointer = OPA.integer_var + (short) st->b;
OPC.integer_var = pointer;
break;
case OP_STOREB_F:
case OP_STOREB_S:
case OP_STOREB_ENT:

View file

@ -121,7 +121,8 @@ opcode_t pr_opcodes[] = {
{"&", "address.i", OP_ADDRESS_I, false, ev_integer, ev_void, ev_pointer, PROG_VERSION},
{"&", "address.p", OP_ADDRESS_P, false, ev_pointer, ev_void, ev_pointer, PROG_VERSION},
{"&", "lea", OP_LEA, false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION},
{"&", "lea", OP_LEA, false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION},
{"&", "leai", OP_LEAI, false, ev_pointer, ev_short, ev_pointer, PROG_VERSION},
{"=", "store.f", OP_STORE_F, true, ev_float, ev_float, ev_void, PROG_ID_VERSION},
{"=", "store.v", OP_STORE_V, true, ev_vector, ev_vector, ev_void, PROG_ID_VERSION},

View file

@ -1,3 +1,3 @@
#! /bin/sh
gcc -o GLstub.so -shared -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations gl_stub.c
gcc -o GLstub.so -fPIC -shared -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations gl_stub.c

View file

@ -6,6 +6,7 @@ typedef enum {
ex_def,
ex_temp, // temporary variable
ex_nil, // umm, nil, null. nuff said
ex_name,
ex_string,
ex_float,

View file

@ -283,10 +283,13 @@ typedef struct type_s
etype_t type;
struct def_s *def; // a def that points to this type
struct type_s *next;
// function types are more complex
// function/pointer/struct types are more complex
struct type_s *aux_type; // return type or field type
int num_parms; // -1 = variable args
struct type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated
struct hashtab_s *struct_fields;
struct struct_field_s *struct_head;
struct struct_field_s **struct_tail;
} type_t;
typedef struct statref_s {
@ -359,6 +362,7 @@ extern type_t type_quaternion;
extern type_t type_integer;
extern type_t type_uinteger;
extern type_t type_short;
extern type_t type_struct;
extern def_t def_void;
extern def_t def_string;
@ -372,6 +376,7 @@ extern def_t def_quaternion;
extern def_t def_integer;
extern def_t def_uinteger;
extern def_t def_short;
extern def_t def_struct;
struct function_s
{

View file

@ -33,5 +33,5 @@ YFLAGS = -d
bin_PROGRAMS= qfcc
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 switch.c getopt.c getopt1.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 struct.c switch.c getopt.c getopt1.c
qfcc_LDADD= -lQFgamecode -lQFutil

View file

@ -77,6 +77,8 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b,
if (op->type_c == ev_void) {
var_c = NULL;
statement->c = 0;
} else {
statement->c = var_c->ofs;
}
ret = var_a;
} else { // allocate result space
@ -249,6 +251,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
emit_expr (e);
break;
}
case ex_name:
case ex_nil:
case ex_label:
error (e, "internal error");
@ -299,6 +302,24 @@ emit_sub_expr (expr_t *e, def_t *dest)
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
dest->users += 2;
}
} else if (e->e.expr.op == '&') {
static expr_t zero;
def_t *tmp = 0;
zero.type = ex_short;
operator = "&";
if (e->e.expr.e1->type == ex_expr
&& e->e.expr.e1->e.expr.op == '.') {
tmp = PR_GetTempDef (e->e.expr.type, pr_scope);
tmp->users += 2;
}
def_a = emit_sub_expr (e->e.expr.e1, tmp);
def_b = emit_sub_expr (&zero, 0);
if (!dest) {
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
dest->users += 2;
}
} else {
abort ();
}
@ -335,6 +356,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
d = PR_NewDef (&type_short, 0, pr_scope);
d->ofs = e->e.short_val;
d->absolute = 1;
d->users = 1;
break;
}
PR_FreeTempDefs ();
@ -454,6 +476,7 @@ emit_expr (expr_t *e)
warning (e, "Ignoring useless expression");
break;
case ex_nil:
case ex_name:
error (e, "internal error");
abort ();
}

View file

@ -38,6 +38,7 @@ static const char rcsid[] =
#include "qfcc.h"
#include "scope.h"
#include "struct.h"
#include "qc-parse.h"
@ -51,6 +52,7 @@ etype_t qc_types[] = {
ev_void, // ex_def
ev_void, // ex_temp
ev_void, // ex_nil
ev_void, // ex_name
ev_string, // ex_string
ev_float, // ex_float
@ -93,13 +95,31 @@ expr_type expr_types[] = {
ex_integer, // ev_integer
ex_uinteger, // ev_uinteger
ex_short, // ev_short
ex_nil, // ev_struct FIXME???
};
void
convert_name (expr_t *e)
{
if (e->type == ex_name) {
const char * name = e->e.string_val;
e->type = ex_def;
e->e.def = PR_GetDef (NULL, name, pr_scope, false);
if (!e->e.def) {
error (e, "Undeclared variable \"%s\".", name);
e->e.def = &def_float;
}
}
}
type_t *
get_type (expr_t *e)
{
convert_name (e);
switch (e->type) {
case ex_label:
case ex_name:
return 0; // something went very wrong
case ex_nil:
return &type_void;
@ -487,6 +507,7 @@ print_expr (expr_t *e)
printf ("NULL");
break;
case ex_string:
case ex_name:
printf ("\"%s\"", e->e.string_val);
break;
case ex_float:
@ -798,8 +819,36 @@ field_expr (expr_t *e1, expr_t *e2)
{
etype_t t1, t2;
expr_t *e;
type_t *strct;
struct_field_t *field;
t1 = extract_type (e1);
if (t1 == ev_struct) {
strct = get_type (e1);
if (e2->type != ex_name)
return error (e2, "structure field name expected");
field = struct_find_field (strct, e2->e.string_val);
if (!field)
return error (e2, "structure has no field %s", e2->e.string_val);
e2->type = ex_short;
e2->e.short_val = field->offset;
e = new_binary_expr ('.', unary_expr ('&', e1), e2);
e->e.expr.type = field->type;
return e;
}
if (t1 == ev_pointer
&& (strct = get_type(e1)->aux_type)->type == ev_struct) {
if (e2->type != ex_name)
return error (e2, "structure field name expected");
field = struct_find_field (strct, e2->e.string_val);
if (!field)
return error (e2, "structure has no field %s", e2->e.string_val);
e2->type = ex_short;
e2->e.short_val = field->offset;
e = new_binary_expr ('.', e1, e2);
e->e.expr.type = field->type;
return e;
}
t2 = extract_type (e2);
if ((t1 != ev_entity || t2 != ev_field)
@ -831,8 +880,7 @@ test_expr (expr_t *e, int test)
error (e, "internal error");
abort ();
case ev_void:
error (e, "void has no value");
break;
return error (e, "void has no value");
case ev_string:
new = new_expr ();
new->type = ex_string;
@ -871,6 +919,8 @@ test_expr (expr_t *e, int test)
new = new_expr ();
new->type = ex_quaternion;
break;
case ev_struct:
return error (e, "struct cannot be tested");
}
new->line = e->line;
new->file = e->file;
@ -894,9 +944,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
type_t *type = 0;
expr_t *e;
convert_name (e1);
if (op != '=')
check_initialized (e1);
check_initialized (e2);
if (op == '=' && e1->type == ex_def)
PR_DefInitialized (e1->e.def);
@ -911,6 +961,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
if (op == '.')
return field_expr (e1, e2);
convert_name (e2);
check_initialized (e2);
if (op == OR || op == AND) {
e1 = test_expr (e1, true);
e2 = test_expr (e2, true);
@ -1028,11 +1081,13 @@ asx_expr (int op, expr_t *e1, expr_t *e2)
expr_t *
unary_expr (int op, expr_t *e)
{
convert_name (e);
check_initialized (e);
switch (op) {
case '-':
switch (e->type) {
case ex_label:
case ex_name:
error (e, "internal error");
abort ();
case ex_uexpr:
@ -1084,6 +1139,8 @@ unary_expr (int op, expr_t *e)
case '!':
switch (e->type) {
case ex_label:
case ex_name:
error (e, "internal error");
abort ();
case ex_block:
if (!e->e.block.result)
@ -1142,13 +1199,15 @@ unary_expr (int op, expr_t *e)
case '~':
switch (e->type) {
case ex_label:
case ex_name:
error (e, "internal error");
abort ();
case ex_uexpr:
if (e->e.expr.op == '~')
return e->e.expr.e1;
case ex_block:
if (!e->e.block.result)
return error (e, "invalid type for unary -");
return error (e, "invalid type for unary ~");
case ex_expr:
case ex_def:
case ex_temp:
@ -1183,8 +1242,54 @@ unary_expr (int op, expr_t *e)
return error (e, "invalid type for unary ~");
}
break;
default:
abort ();
case '&':
switch (e->type) {
case ex_label:
case ex_name:
error (e, "internal error");
abort ();
case ex_def:
{
type_t new;
expr_t *n = new_unary_expr (op, e);
memset (&new, 0, sizeof (new));
new.type = ev_pointer;
new.aux_type = e->e.def->type;
n->e.expr.type = PR_FindType (&new);
return n;
}
case ex_expr:
if (e->e.expr.op == '.') {
expr_t *e1 = e->e.expr.e1;
if (get_type (e1) == &type_entity) {
type_t new;
memset (&new, 0, sizeof (new));
new.type = ev_pointer;
new.aux_type = e->e.expr.type;
e->e.expr.type = PR_FindType (&new);
return e;
}
}
case ex_uexpr:
case ex_block:
case ex_temp:
case ex_short:
case ex_integer:
case ex_uinteger:
case ex_float:
case ex_nil:
case ex_string:
case ex_vector:
case ex_quaternion:
case ex_entity:
case ex_field:
case ex_func:
case ex_pointer:
return error (e, "invalid type for unary &");
}
break;
}
error (e, "internal error");
abort ();

View file

@ -102,6 +102,14 @@ PR_GetArray (type_t *etype, const char *name, int size, def_t *scope,
return def;
}
int
PR_GetTypeSize (type_t *type)
{
if (type->type == ev_struct)
return type->num_parms;
return pr_type_size[type->type];
}
/*
PR_GetDef
@ -113,6 +121,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
{
def_t *def = check_for_name (type, name, scope, allocate);
char element[MAX_NAME];
int size;
if (def || !allocate)
return def;
@ -147,7 +156,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
d->used = 1;
d->parent = def;
} else {
*allocate += pr_type_size[type->type];
*allocate += PR_GetTypeSize(type);
}
if (type->type == ev_field) {
@ -171,13 +180,15 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
d->used = 1; // always `used'
d->parent = def;
} else if (type->aux_type->type == ev_pointer) {
pr.size_fields += type->aux_type->num_parms
* pr_type_size[type->aux_type->aux_type->type];
size = PR_GetTypeSize (type->aux_type->aux_type);
pr.size_fields += type->aux_type->num_parms * size;
} else {
pr.size_fields += pr_type_size[type->aux_type->type];
size = PR_GetTypeSize (type->aux_type);
pr.size_fields += size;
}
} else if (type->type == ev_pointer) {
*allocate += type->num_parms * pr_type_size[type->aux_type->type];
size = PR_GetTypeSize (type->aux_type);
*allocate += type->num_parms * size;
def->initialized = def->constant = 1;
}

View file

@ -68,6 +68,7 @@ type_t type_quaternion = { ev_quaternion, &def_quaternion };
type_t type_integer = { ev_integer, &def_integer };
type_t type_uinteger = { ev_uinteger, &def_uinteger };
type_t type_short = { ev_short, &def_short };
type_t type_struct = { ev_struct, &def_struct };
type_t type_floatfield = { ev_field, &def_field, NULL, &type_float };
@ -83,6 +84,7 @@ def_t def_quaternion = { &type_quaternion, "temp" };
def_t def_integer = { &type_integer, "temp" };
def_t def_uinteger = { &type_uinteger, "temp" };
def_t def_short = { &type_short, "temp" };
def_t def_struct = { &type_struct, "temp" };
def_t def_ret, def_parms[MAX_PARMS];
@ -304,8 +306,7 @@ PR_FindType (type_t *type)
// allocate a generic def for the type, so fields can reference it
def = malloc (sizeof (def_t));
if (!check)
if (!def)
Sys_Error ("PR_FindType: Memory Allocation Failure\n");
def->name = "COMPLEX TYPE";
def->type = check;

View file

@ -35,6 +35,7 @@ static const char rcsid[] =
#include <QF/sys.h>
#include "qfcc.h"
#include "scope.h"
#include "struct.h"
#include "qc-parse.h"
#define YY_NO_UNPUT
@ -227,6 +228,7 @@ static keyword_t keywords[] = {
{"case", CASE, 0, PROG_ID_VERSION},
{"default", DEFAULT, 0, PROG_ID_VERSION},
{"NIL", NIL, 0, PROG_ID_VERSION},
{"struct", STRUCT, 0, PROG_VERSION},
};
static const char *
@ -238,23 +240,27 @@ keyword_get_key (void *kw, void *unused)
int
type_or_name (char *token)
{
static int initialized = 0;
static hashtab_t *keyword_tab;
keyword_t *keyword;
keyword_t *keyword;
type_t *type;
if (!initialized) {
if (!keyword_tab) {
int i;
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
if (keywords[i].version <= options.code.progsversion)
Hash_Add (keyword_tab, &keywords[i]);
initialized = 1;
}
keyword = Hash_Find (keyword_tab, token);
if (keyword) {
yylval.type = keyword->type;
return keyword->value;
}
type = find_struct (token);
if (type) {
yylval.type = type;
return TYPE;
}
yylval.string_val = strdup (token);
return NAME;
}

View file

@ -35,6 +35,7 @@ static const char rcsid[] =
#include <QF/hash.h>
#include <QF/sys.h>
#include "struct.h"
#include "switch.h"
#define YYDEBUG 1
@ -110,7 +111,7 @@ typedef struct {
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL
%token IFBE IFB IFAE IFA
%token SWITCH CASE DEFAULT
%token SWITCH CASE DEFAULT STRUCT
%token <type> TYPE
%type <type> type opt_func func_parms array_decl
@ -137,6 +138,7 @@ expr_t *local_expr;
expr_t *break_label;
expr_t *continue_label;
switch_block_t *switch_block;
type_t *struct_type;
def_t *pr_scope; // the function being parsed, or NULL
string_t s_file; // filename for function definition
@ -157,6 +159,22 @@ def
{ current_type = build_type ($1, $4); } var_def_list
| opt_field TYPE { current_type = $2; } func_parms
{ current_type = build_type ($1, $4); } func_def_list
| STRUCT NAME
{ struct_type = new_struct ($2); } '=' '{' struct_defs '}'
;
struct_defs
: /* empty */
| struct_defs struct_def ';'
;
struct_def
: opt_field TYPE
{ current_type = build_type ($1, $2); } struct_def_list
| opt_field TYPE { current_type = $2; } array_decl
{ current_type = build_type ($1, $4); } struct_def_list
| opt_field TYPE { current_type = $2; } func_parms
{ current_type = build_type ($1, $4); } struct_def_list
;
opt_field
@ -218,6 +236,15 @@ array_decl
| '[' ']' { $$ = build_array_type (0); }
;
struct_def_list
: struct_def_list ',' struct_def_item
| struct_def_item
;
struct_def_item
: NAME { new_struct_field (struct_type, current_type, $1); }
;
var_def_list
: var_def_list ',' var_def_item
| var_def_item
@ -683,12 +710,8 @@ expr
| NAME
{
$$ = new_expr ();
$$->type = ex_def;
$$->e.def = PR_GetDef (NULL, $1, pr_scope, false);
if (!$$->e.def) {
error (0, "Undeclared variable \"%s\".", $1);
$$->e.def = &def_float;
}
$$->type = ex_name;
$$->e.string_val = $1;
}
| const { $$ = $1; }
| '(' expr ')' { $$ = $2; $$->paren = 1; }
@ -805,6 +828,14 @@ build_type (int is_field, type_t *type)
new.type = ev_field;
new.aux_type = type;
return PR_FindType (&new);
} else if (type->type == ev_struct) {
type_t new;
memset (&new, 0, sizeof (new));
new.type = ev_pointer;
new.aux_type = type;
new.num_parms = 1;
return PR_FindType (&new);
} else {
return type;
}

View file

@ -37,7 +37,8 @@ new_struct_field (type_t *strct, type_t *type, const char *name)
field->next = 0;
*strct->struct_tail = field;
strct->struct_tail = &field->next;
return 0;
Hash_Add (strct->struct_fields, field);
return field;
}
struct_field_t *