From: Wolfgang Bumiller Date: Sat, 5 May 2012 08:56:00 +0000 (+0200) Subject: More work on generating code - still not instantiating function-statements, 2 kinds... X-Git-Tag: 0.1-rc1~485^2~16 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=5ca6f4abcafcaaf0f5804111f381a97a2b0e871c;p=xonotic%2Fgmqcc.git More work on generating code - still not instantiating function-statements, 2 kinds of FIXME comments: relocation and creation of ir_values for ir_functions --- diff --git a/ir.c b/ir.c index 75ea4aa..850f070 100644 --- a/ir.c +++ b/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; - case TYPE_FUNCTION: - def.type = 6; - nelems = 1; - break; - default: - /* refuse to create 'void' type or any other fancy business. */ - return false; - } - - def.offset = code_globals_allocated; - def.name = code_genstring(global->name); - if (code_defs_add(def) < 0) - return false; + 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) + 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 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; - } + 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; + 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; } - - 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])) diff --git a/ir.h b/ir.h index d3ad5b3..d095054 100644 --- a/ir.h +++ b/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