mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-21 02:10:53 +00:00
More work on generating code - still not instantiating function-statements, 2 kinds of FIXME comments: relocation and creation of ir_values for ir_functions
This commit is contained in:
parent
c252c7e62b
commit
5ca6f4abca
2 changed files with 216 additions and 57 deletions
261
ir.c
261
ir.c
|
@ -381,6 +381,7 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
|
|||
ir_value *self;
|
||||
self = (ir_value*)mem_a(sizeof(*self));
|
||||
self->vtype = vtype;
|
||||
self->fieldtype = TYPE_VOID;
|
||||
self->store = storetype;
|
||||
MEM_VECTOR_INIT(self, reads);
|
||||
MEM_VECTOR_INIT(self, writes);
|
||||
|
@ -390,6 +391,9 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
|
|||
self->name = NULL;
|
||||
ir_value_set_name(self, name);
|
||||
|
||||
memset(&self->constval, 0, sizeof(self->constval));
|
||||
memset(&self->code, 0, sizeof(self->code));
|
||||
|
||||
MEM_VECTOR_INIT(self, life);
|
||||
return self;
|
||||
}
|
||||
|
@ -1670,84 +1674,223 @@ on_error:
|
|||
*
|
||||
* Breaking conventions is annoying...
|
||||
*/
|
||||
static bool ir_builder_gen_global(ir_builder *self, ir_value *global);
|
||||
|
||||
static bool gen_global_field(ir_value *global)
|
||||
{
|
||||
if (global->isconst)
|
||||
{
|
||||
ir_value *fld = global->constval.vpointer;
|
||||
if (!fld) {
|
||||
printf("Invalid field constant with no field: %s\n", global->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now, in this case, a relocation would be impossible to code
|
||||
* since it looks like this:
|
||||
* .vector v = origin; <- parse error, wtf is 'origin'?
|
||||
* .vector origin;
|
||||
*
|
||||
* But we will need a general relocation support later anyway
|
||||
* for functions... might as well support that here.
|
||||
*/
|
||||
if (!fld->code.globaladdr) {
|
||||
printf("FIXME: Relocation support\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* copy the field's value */
|
||||
global->code.globaladdr = code_globals_add(code_globals_data[fld->code.globaladdr]);
|
||||
}
|
||||
else
|
||||
{
|
||||
prog_section_field fld;
|
||||
|
||||
fld.name = global->code.name;
|
||||
fld.offset = code_fields_elements;
|
||||
fld.type = global->fieldtype;
|
||||
|
||||
if (fld.type == TYPE_VOID) {
|
||||
printf("Field is missing a type: %s\n", global->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (code_fields_add(fld) < 0)
|
||||
return false;
|
||||
|
||||
global->code.globaladdr = code_globals_add(fld.offset);
|
||||
}
|
||||
if (global->code.globaladdr < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool gen_global_pointer(ir_value *global)
|
||||
{
|
||||
if (global->isconst)
|
||||
{
|
||||
ir_value *target = global->constval.vpointer;
|
||||
if (!target) {
|
||||
printf("Invalid pointer constant: %s\n", global->name);
|
||||
/* NULL pointers are pointing to the NULL constant, which also
|
||||
* sits at address 0, but still has an ir_value for itself.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Here, relocations ARE possible - in fteqcc-enhanced-qc:
|
||||
* void() foo; <- proto
|
||||
* void() *fooptr = &foo;
|
||||
* void() foo = { code }
|
||||
*/
|
||||
if (!target->code.globaladdr) {
|
||||
/* FIXME: Check for the constant nullptr ir_value!
|
||||
* because then code.globaladdr being 0 is valid.
|
||||
*/
|
||||
printf("FIXME: Relocation support\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
global->code.globaladdr = code_globals_add(target->code.globaladdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
global->code.globaladdr = code_globals_add(0);
|
||||
}
|
||||
if (global->code.globaladdr < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool gen_function_code(ir_function *self)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gen_global_function(ir_builder *ir, ir_value *global)
|
||||
{
|
||||
prog_section_function fun;
|
||||
ir_function *irfun;
|
||||
|
||||
size_t i;
|
||||
|
||||
if (!global->isconst ||
|
||||
!global->constval.vfunc)
|
||||
{
|
||||
printf("Invalid state of function-global: not constant: %s\n", global->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
irfun = global->constval.vfunc;
|
||||
|
||||
fun.name = global->code.name;
|
||||
fun.file = code_cachedstring(global->context.file);
|
||||
fun.profile = 0; /* always 0 */
|
||||
fun.nargs = irfun->params_count;
|
||||
|
||||
for (i = 0;i < 8; ++i) {
|
||||
if (i >= fun.nargs)
|
||||
fun.argsize[i] = 0;
|
||||
else if (irfun->params[i] == TYPE_VECTOR)
|
||||
fun.argsize[i] = 3;
|
||||
else
|
||||
fun.argsize[i] = 1;
|
||||
}
|
||||
|
||||
fun.locals = irfun->locals_count;
|
||||
fun.firstlocal = code_globals_elements;
|
||||
for (i = 0; i < irfun->locals_count; ++i) {
|
||||
if (!ir_builder_gen_global(ir, irfun->locals[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
fun.entry = code_statements_elements;
|
||||
if (!gen_function_code(irfun))
|
||||
return false;
|
||||
|
||||
return (code_functions_add(fun) >= 0);
|
||||
}
|
||||
|
||||
static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
|
||||
{
|
||||
int nelems;
|
||||
uint32_t *elems;
|
||||
int32_t *iptr;
|
||||
prog_section_def def;
|
||||
|
||||
def.type = 0;
|
||||
def.offset = code_globals_elements;
|
||||
def.name = global->code.name = code_genstring(global->name);
|
||||
|
||||
switch (global->vtype)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
def.type++;
|
||||
def.type++;
|
||||
def.type = 7;
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
return gen_global_pointer(global);
|
||||
case TYPE_FIELD:
|
||||
def.type++;
|
||||
def.type = 5;
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
return gen_global_field(global);
|
||||
case TYPE_ENTITY:
|
||||
def.type++;
|
||||
def.type++;
|
||||
def.type = 4;
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
case TYPE_FLOAT:
|
||||
def.type++;
|
||||
{
|
||||
def.type = 2;
|
||||
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
|
||||
if (global->isconst) {
|
||||
iptr = (int32_t*)&global->constval.vfloat;
|
||||
global->code.globaladdr = code_globals_add(*iptr);
|
||||
} else
|
||||
global->code.globaladdr = code_globals_add(0);
|
||||
|
||||
return global->code.globaladdr >= 0;
|
||||
}
|
||||
case TYPE_STRING:
|
||||
def.type++;
|
||||
nelems = 1;
|
||||
break;
|
||||
{
|
||||
def.type = 1;
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
if (global->isconst)
|
||||
global->code.globaladdr = code_globals_add(code_cachedstring(global->constval.vstring));
|
||||
else
|
||||
global->code.globaladdr = code_globals_add(0);
|
||||
return global->code.globaladdr >= 0;
|
||||
}
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
def.type = 3;
|
||||
nelems = 3;
|
||||
break;
|
||||
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
|
||||
if (global->isconst) {
|
||||
iptr = (int32_t*)&global->constval.vvec;
|
||||
global->code.globaladdr = code_globals_add(iptr[0]);
|
||||
if (code_globals_add(iptr[1]) < 0 || code_globals_add(iptr[2]) < 0)
|
||||
return false;
|
||||
} else {
|
||||
global->code.globaladdr = code_globals_add(0);
|
||||
if (code_globals_add(0) < 0 || code_globals_add(0) < 0)
|
||||
return false;
|
||||
}
|
||||
return global->code.globaladdr >= 0;
|
||||
}
|
||||
case TYPE_FUNCTION:
|
||||
def.type = 6;
|
||||
nelems = 1;
|
||||
break;
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
return gen_global_function(self, global);
|
||||
default:
|
||||
/* refuse to create 'void' type or any other fancy business. */
|
||||
printf("Invalid type for global variable %s\n", global->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
def.offset = code_globals_allocated;
|
||||
def.name = code_genstring(global->name);
|
||||
|
||||
if (code_defs_add(def) < 0)
|
||||
return false;
|
||||
|
||||
if (!global->isconst) {
|
||||
int i;
|
||||
for (i = 0; i < nelems; ++i) {
|
||||
if (code_globals_add(0) < 0)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (global->vtype == TYPE_STRING) {
|
||||
if (code_globals_add(code_genstring(global->constval.vstring)) < 0)
|
||||
return false;
|
||||
} else if (global->vtype == TYPE_FUNCTION) {
|
||||
prog_section_function fun;
|
||||
int i;
|
||||
|
||||
fun.profile = 0;
|
||||
fun.file = code_cachedstring(global->context.file);
|
||||
fun.name = def.name;
|
||||
for (i = 0; i < 8; ++i)
|
||||
fun.argsize[i] = 0;
|
||||
fun.nargs = 0;
|
||||
fun.entry = 0;
|
||||
fun.firstlocal = 0;
|
||||
fun.locals = 0;
|
||||
code_functions_add(fun);
|
||||
} else {
|
||||
int i;
|
||||
elems = (uint32_t*)&global->constval;
|
||||
for (i = 0; i < nelems; ++i) {
|
||||
if (code_globals_add(elems[i]) < 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ir_builder_generate(ir_builder *self, const char *filename)
|
||||
|
@ -1756,6 +1899,10 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
|
|||
|
||||
code_init();
|
||||
|
||||
/* FIXME: generate TYPE_FUNCTION globals and link them
|
||||
* to their ir_function.
|
||||
*/
|
||||
|
||||
for (i = 0; i < self->globals_count; ++i)
|
||||
{
|
||||
if (!ir_builder_gen_global(self, self->globals[i]))
|
||||
|
|
12
ir.h
12
ir.h
|
@ -38,6 +38,8 @@ typedef struct ir_value_s {
|
|||
int vtype;
|
||||
int store;
|
||||
lex_ctx context;
|
||||
/* even the IR knows the subtype of a field */
|
||||
int fieldtype;
|
||||
|
||||
MEM_VECTOR_MAKE(struct ir_instr_s*, reads);
|
||||
MEM_VECTOR_MAKE(struct ir_instr_s*, writes);
|
||||
|
@ -50,8 +52,14 @@ typedef struct ir_value_s {
|
|||
vector vvec;
|
||||
char *vstring;
|
||||
struct ir_value_s *vpointer;
|
||||
struct ir_function_s *vfunc;
|
||||
} constval;
|
||||
|
||||
struct {
|
||||
int32_t globaladdr;
|
||||
int32_t name;
|
||||
} code;
|
||||
|
||||
/* For the temp allocator */
|
||||
MEM_VECTOR_MAKE(ir_life_entry_t, life);
|
||||
} ir_value;
|
||||
|
@ -266,4 +274,8 @@ ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype);
|
|||
|
||||
void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...));
|
||||
|
||||
/* This code assumes 32 bit floats while generating binary */
|
||||
extern int check_int_and_float_size
|
||||
[ (sizeof(int32_t) == sizeof(( (ir_value*)(NULL) )->constval.vvec.x)) ? 1 : -1 ];
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue