]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
preprocessing flag for the lexer
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index cb97b29b2a6709a100b9ea94fd2384537d4f701d..f277ac506b8e8a3cf8381d851ae20bf1ce96d06a 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -155,6 +155,10 @@ static bool irwarning(lex_ctx ctx, int warntype, const char *fmt, ...)
  *IR Builder
  */
 
+static void ir_block_delete_quick(ir_block* self);
+static void ir_instr_delete_quick(ir_instr *self);
+static void ir_function_delete_quick(ir_function *self);
+
 ir_builder* ir_builder_new(const char *modulename)
 {
     ir_builder* self;
@@ -166,6 +170,9 @@ ir_builder* ir_builder_new(const char *modulename)
     MEM_VECTOR_INIT(self, functions);
     MEM_VECTOR_INIT(self, globals);
     MEM_VECTOR_INIT(self, fields);
+    MEM_VECTOR_INIT(self, filenames);
+    MEM_VECTOR_INIT(self, filestrings);
+    self->str_immediate = 0;
     self->name = NULL;
     if (!ir_builder_set_name(self, modulename)) {
         mem_d(self);
@@ -175,16 +182,18 @@ ir_builder* ir_builder_new(const char *modulename)
     return self;
 }
 
-MEM_VEC_FUNCTIONS(ir_builder, ir_value*, globals)
-MEM_VEC_FUNCTIONS(ir_builder, ir_value*, fields)
+MEM_VEC_FUNCTIONS(ir_builder, ir_value*,    globals)
+MEM_VEC_FUNCTIONS(ir_builder, ir_value*,    fields)
 MEM_VEC_FUNCTIONS(ir_builder, ir_function*, functions)
+MEM_VEC_FUNCTIONS(ir_builder, const char*,  filenames)
+MEM_VEC_FUNCTIONS(ir_builder, qcint,        filestrings)
 
 void ir_builder_delete(ir_builder* self)
 {
     size_t i;
     mem_d((void*)self->name);
     for (i = 0; i != self->functions_count; ++i) {
-        ir_function_delete(self->functions[i]);
+        ir_function_delete_quick(self->functions[i]);
     }
     MEM_VECTOR_CLEAR(self, functions);
     for (i = 0; i != self->globals_count; ++i) {
@@ -195,6 +204,8 @@ void ir_builder_delete(ir_builder* self)
         ir_value_delete(self->fields[i]);
     }
     MEM_VECTOR_CLEAR(self, fields);
+    MEM_VECTOR_CLEAR(self, filenames);
+    MEM_VECTOR_CLEAR(self, filestrings);
     mem_d(self);
 }
 
@@ -356,6 +367,30 @@ bool ir_function_set_name(ir_function *self, const char *name)
     return !!self->name;
 }
 
+static void ir_function_delete_quick(ir_function *self)
+{
+    size_t i;
+    mem_d((void*)self->name);
+
+    for (i = 0; i != self->blocks_count; ++i)
+        ir_block_delete_quick(self->blocks[i]);
+    MEM_VECTOR_CLEAR(self, blocks);
+
+    MEM_VECTOR_CLEAR(self, params);
+
+    for (i = 0; i != self->values_count; ++i)
+        ir_value_delete(self->values[i]);
+    MEM_VECTOR_CLEAR(self, values);
+
+    for (i = 0; i != self->locals_count; ++i)
+        ir_value_delete(self->locals[i]);
+    MEM_VECTOR_CLEAR(self, locals);
+
+    /* self->value is deleted by the builder */
+
+    mem_d(self);
+}
+
 void ir_function_delete(ir_function *self)
 {
     size_t i;
@@ -462,7 +497,7 @@ ir_block* ir_block_new(ir_function* owner, const char *name)
     memset(self, 0, sizeof(*self));
 
     self->label = NULL;
-    if (!ir_block_set_label(self, name)) {
+    if (name && !ir_block_set_label(self, name)) {
         mem_d(self);
         return NULL;
     }
@@ -488,10 +523,23 @@ MEM_VEC_FUNCTIONS_ALL(ir_block, ir_block*, entries)
 MEM_VEC_FUNCTIONS_ALL(ir_block, ir_block*, exits)
 MEM_VEC_FUNCTIONS_ALL(ir_block, ir_value*, living)
 
+static void ir_block_delete_quick(ir_block* self)
+{
+    size_t i;
+    if (self->label) mem_d(self->label);
+    for (i = 0; i != self->instr_count; ++i)
+        ir_instr_delete_quick(self->instr[i]);
+    MEM_VECTOR_CLEAR(self, instr);
+    MEM_VECTOR_CLEAR(self, entries);
+    MEM_VECTOR_CLEAR(self, exits);
+    MEM_VECTOR_CLEAR(self, living);
+    mem_d(self);
+}
+
 void ir_block_delete(ir_block* self)
 {
     size_t i;
-    mem_d(self->label);
+    if (self->label) mem_d(self->label);
     for (i = 0; i != self->instr_count; ++i)
         ir_instr_delete(self->instr[i]);
     MEM_VECTOR_CLEAR(self, instr);
@@ -538,6 +586,13 @@ ir_instr* ir_instr_new(ir_block* owner, int op)
 MEM_VEC_FUNCTIONS(ir_instr, ir_phi_entry_t, phi)
 MEM_VEC_FUNCTIONS(ir_instr, ir_value*, params)
 
+static void ir_instr_delete_quick(ir_instr *self)
+{
+    MEM_VECTOR_CLEAR(self, phi);
+    MEM_VECTOR_CLEAR(self, params);
+    mem_d(self);
+}
+
 void ir_instr_delete(ir_instr *self)
 {
     size_t i;
@@ -630,7 +685,11 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
     self->context.file = "<@no context>";
     self->context.line = 0;
     self->name = NULL;
-    ir_value_set_name(self, name);
+    if (name && !ir_value_set_name(self, name)) {
+        irerror(self->context, "out of memory");
+        mem_d(self);
+        return NULL;
+    }
 
     memset(&self->constval, 0, sizeof(self->constval));
     memset(&self->code,     0, sizeof(self->code));
@@ -723,11 +782,12 @@ void ir_value_delete(ir_value* self)
     mem_d(self);
 }
 
-void ir_value_set_name(ir_value *self, const char *name)
+bool ir_value_set_name(ir_value *self, const char *name)
 {
     if (self->name)
         mem_d((void*)self->name);
     self->name = util_strdup(name);
+    return !!self->name;
 }
 
 bool ir_value_set_float(ir_value *self, float f)
@@ -919,14 +979,14 @@ bool ir_value_life_merge_into(ir_value *self, const ir_value *other)
             }
 
             if (life->start <  entry->start &&
-                life->end   >= entry->start)
+                life->end+1 >= entry->start)
             {
                 /* starts earlier and overlaps */
                 entry->start = life->start;
             }
 
-            if (life->end     >  entry->end &&
-                life->start-1 <= entry->end)
+            if (life->end   >  entry->end &&
+                life->start <= entry->end+1)
             {
                 /* ends later and overlaps */
                 entry->end = life->end;
@@ -2544,6 +2604,27 @@ static bool gen_function_code(ir_function *self)
     return true;
 }
 
+static qcint ir_builder_filestring(ir_builder *ir, const char *filename)
+{
+    /* NOTE: filename pointers are copied, we never strdup them,
+     * thus we can use pointer-comparison to find the string.
+     */
+    size_t i;
+    qcint  str;
+
+    for (i = 0; i < ir->filenames_count; ++i) {
+        if (ir->filenames[i] == filename)
+            return ir->filestrings[i];
+    }
+
+    str = code_genstring(filename);
+    if (!ir_builder_filenames_add(ir, filename))
+        return 0;
+    if (!ir_builder_filestrings_add(ir, str))
+        ir->filenames_count--;
+    return str;
+}
+
 static bool gen_global_function(ir_builder *ir, ir_value *global)
 {
     prog_section_function fun;
@@ -2561,7 +2642,7 @@ static bool gen_global_function(ir_builder *ir, ir_value *global)
     irfun = global->constval.vfunc;
 
     fun.name    = global->code.name;
-    fun.file    = code_cachedstring(global->context.file);
+    fun.file    = ir_builder_filestring(ir, global->context.file);
     fun.profile = 0; /* always 0 */
     fun.nargs   = irfun->params_count;
 
@@ -2647,7 +2728,18 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
 
     def.type   = global->vtype;
     def.offset = code_globals_elements;
-    def.name   = global->code.name       = code_genstring(global->name);
+
+    if (global->name) {
+        if (global->name[0] == '#') {
+            if (!self->str_immediate)
+                self->str_immediate = code_genstring("IMMEDIATE");
+            def.name = global->code.name = self->str_immediate;
+        }
+        else
+            def.name = global->code.name = code_genstring(global->name);
+    }
+    else
+        def.name   = 0;
 
     switch (global->vtype)
     {
@@ -2702,7 +2794,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
     case TYPE_STRING:
     {
         if (global->isconst)
-            ir_value_code_setaddr(global, code_globals_add(code_cachedstring(global->constval.vstring)));
+            ir_value_code_setaddr(global, code_globals_add(code_genstring(global->constval.vstring)));
         else {
             ir_value_code_setaddr(global, code_globals_add(0));
             if (!islocal)
@@ -3109,10 +3201,10 @@ void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
     }
 }
 
-void ir_value_dump_life(ir_value *self, int (*oprintf)(const char*,...))
+void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...))
 {
     size_t i;
-    oprintf("Life of %s:\n", self->name);
+    oprintf("Life of %12s:", self->name);
     for (i = 0; i < self->life_count; ++i)
     {
         oprintf(" + [%i, %i]\n", self->life[i].start, self->life[i].end);