]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
All ir_instrs now get their lex-context, so that we can create an LNO file with ...
authorWolfgang (Blub) Bumiller <blub@speed.at>
Fri, 30 Nov 2012 17:19:26 +0000 (18:19 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Fri, 30 Nov 2012 17:20:02 +0000 (18:20 +0100)
ast.c
code.c
gmqcc.h
ir.c
ir.h
opts.def

diff --git a/ast.c b/ast.c
index 25be65bc39f701b8450e913a25a8cbb887298536..063084fd1967953c265cccef04023109372b2490 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1451,7 +1451,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
         if (!self->vtype->expression.next ||
             self->vtype->expression.next->expression.vtype == TYPE_VOID)
         {
-            return ir_block_create_return(self->curblock, NULL);
+            return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
         }
         else if (vec_size(self->curblock->entries))
         {
@@ -1462,7 +1462,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
             {
                 return false;
             }
-            return ir_block_create_return(self->curblock, NULL);
+            return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
         }
     }
     return true;
@@ -1584,7 +1584,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
         if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
             return false;
 
-        call = ir_block_create_call(func->curblock, ast_function_label(func, "store"), funval);
+        call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval);
         if (!call)
             return false;
         ir_call_param(call, iridx);
@@ -1606,7 +1606,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
         if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
             return false;
 
-        if (!ir_block_create_store_op(func->curblock, self->op, left, right))
+        if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->op, left, right))
             return false;
         self->expression.outr = right;
     }
@@ -1670,7 +1670,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
                 compile_error(ast_ctx(self), "don't know how to cast to bool...");
                 return false;
             }
-            left = ir_block_create_unary(func->curblock,
+            left = ir_block_create_unary(func->curblock, ast_ctx(self),
                                          ast_function_label(func, "sce_not"),
                                          notop,
                                          left);
@@ -1679,10 +1679,10 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
 
         other = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_other"));
         if ( !(self->op == INSTR_OR) != !OPTS_FLAG(PERL_LOGIC) ) {
-            if (!ir_block_create_if(func->curblock, left, other, merge))
+            if (!ir_block_create_if(func->curblock, ast_ctx(self), left, other, merge))
                 return false;
         } else {
-            if (!ir_block_create_if(func->curblock, left, merge, other))
+            if (!ir_block_create_if(func->curblock, ast_ctx(self), left, merge, other))
                 return false;
         }
         /* use the likely flag */
@@ -1698,21 +1698,21 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
                 compile_error(ast_ctx(self), "don't know how to cast to bool...");
                 return false;
             }
-            right = ir_block_create_unary(func->curblock,
+            right = ir_block_create_unary(func->curblock, ast_ctx(self),
                                           ast_function_label(func, "sce_not"),
                                           notop,
                                           right);
         }
         from_right = func->curblock;
 
-        if (!ir_block_create_jump(func->curblock, merge))
+        if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge))
             return false;
 
         vec_remove(func->ir_func->blocks, merge_id, 1);
         vec_push(func->ir_func->blocks, merge);
 
         func->curblock = merge;
-        phi = ir_block_create_phi(func->curblock, ast_function_label(func, "sce_value"), TYPE_FLOAT);
+        phi = ir_block_create_phi(func->curblock, ast_ctx(self), ast_function_label(func, "sce_value"), TYPE_FLOAT);
         ir_phi_add(phi, from_left, left);
         ir_phi_add(phi, from_right, right);
         *out = ir_phi_value(phi);
@@ -1722,7 +1722,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
                 compile_error(ast_ctx(self), "don't know how to cast to bool...");
                 return false;
             }
-            *out = ir_block_create_unary(func->curblock,
+            *out = ir_block_create_unary(func->curblock, ast_ctx(self),
                                          ast_function_label(func, "sce_final_not"),
                                          notop,
                                          *out);
@@ -1741,7 +1741,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
     if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
         return false;
 
-    *out = ir_block_create_binop(func->curblock, ast_function_label(func, "bin"),
+    *out = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "bin"),
                                  self->op, left, right);
     if (!*out)
         return false;
@@ -1797,7 +1797,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
         return false;
 
     /* now the binary */
-    bin = ir_block_create_binop(func->curblock, ast_function_label(func, "binst"),
+    bin = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "binst"),
                                 self->opbin, leftr, right);
     self->expression.outr = bin;
 
@@ -1822,7 +1822,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
         if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
             return false;
 
-        call = ir_block_create_call(func->curblock, ast_function_label(func, "store"), funval);
+        call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval);
         if (!call)
             return false;
         ir_call_param(call, iridx);
@@ -1836,7 +1836,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
             return false;
         self->expression.outl = leftl;
 
-        if (!ir_block_create_store_op(func->curblock, self->opstore, leftl, bin))
+        if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->opstore, leftl, bin))
             return false;
         self->expression.outr = bin;
     }
@@ -1874,7 +1874,7 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu
     if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
         return false;
 
-    *out = ir_block_create_unary(func->curblock, ast_function_label(func, "unary"),
+    *out = ir_block_create_unary(func->curblock, ast_ctx(self), ast_function_label(func, "unary"),
                                  self->op, operand);
     if (!*out)
         return false;
@@ -1910,10 +1910,10 @@ bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_va
         if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
             return false;
 
-        if (!ir_block_create_return(func->curblock, operand))
+        if (!ir_block_create_return(func->curblock, ast_ctx(self), operand))
             return false;
     } else {
-        if (!ir_block_create_return(func->curblock, NULL))
+        if (!ir_block_create_return(func->curblock, ast_ctx(self), NULL))
             return false;
     }
 
@@ -1950,10 +1950,10 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
 
     if (lvalue) {
         /* address! */
-        *out = ir_block_create_fieldaddress(func->curblock, ast_function_label(func, "efa"),
+        *out = ir_block_create_fieldaddress(func->curblock, ast_ctx(self), ast_function_label(func, "efa"),
                                             ent, field);
     } else {
-        *out = ir_block_create_load_from_ent(func->curblock, ast_function_label(func, "efv"),
+        *out = ir_block_create_load_from_ent(func->curblock, ast_ctx(self), ast_function_label(func, "efv"),
                                              ent, field, self->expression.vtype);
     }
     if (!*out) {
@@ -2049,7 +2049,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
         if (!(*cgen)((ast_expression*)(arr->getter), func, true, &funval))
             return false;
 
-        call = ir_block_create_call(func->curblock, ast_function_label(func, "fetch"), funval);
+        call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "fetch"), funval);
         if (!call)
             return false;
         ir_call_param(call, iridx);
@@ -2163,9 +2163,9 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
         if (!merge)
             return false;
         /* add jumps ot the merge block */
-        if (ontrue && !ontrue_endblock->final && !ir_block_create_jump(ontrue_endblock, merge))
+        if (ontrue && !ontrue_endblock->final && !ir_block_create_jump(ontrue_endblock, ast_ctx(self), merge))
             return false;
-        if (onfalse && !onfalse_endblock->final && !ir_block_create_jump(onfalse_endblock, merge))
+        if (onfalse && !onfalse_endblock->final && !ir_block_create_jump(onfalse_endblock, ast_ctx(self), merge))
             return false;
 
         /* Now enter the merge block */
@@ -2174,7 +2174,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
 
     /* we create the if here, that way all blocks are ordered :)
      */
-    if (!ir_block_create_if(cond, condval,
+    if (!ir_block_create_if(cond, ast_ctx(self), condval,
                             (ontrue  ? ontrue  : merge),
                             (onfalse ? onfalse : merge)))
     {
@@ -2260,13 +2260,13 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     if (!merge)
         return false;
     /* jump to merge block */
-    if (!ir_block_create_jump(ontrue_out, merge))
+    if (!ir_block_create_jump(ontrue_out, ast_ctx(self), merge))
         return false;
-    if (!ir_block_create_jump(onfalse_out, merge))
+    if (!ir_block_create_jump(onfalse_out, ast_ctx(self), merge))
         return false;
 
     /* create if instruction */
-    if (!ir_block_create_if(cond_out, condval, ontrue, onfalse))
+    if (!ir_block_create_if(cond_out, ast_ctx(self), condval, ontrue, onfalse))
         return false;
 
     /* Now enter the merge block */
@@ -2281,7 +2281,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     }
 
     /* create PHI */
-    phi = ir_block_create_phi(merge, ast_function_label(func, "phi"), trueval->vtype);
+    phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), trueval->vtype);
     if (!phi)
         return false;
     ir_phi_add(phi, ontrue_out,  trueval);
@@ -2467,7 +2467,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
     else if (bbody)      tmpblock = bbody;
     else if (bpostcond)  tmpblock = bpostcond;
     else                 tmpblock = bout;
-    if (!ir_block_create_jump(bin, tmpblock))
+    if (!ir_block_create_jump(bin, ast_ctx(self), tmpblock))
         return false;
 
     /* From precond */
@@ -2479,7 +2479,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         else if (bpostcond)  ontrue = bpostcond;
         else                 ontrue = bprecond;
         onfalse = bout;
-        if (!ir_block_create_if(end_bprecond, precond, ontrue, onfalse))
+        if (!ir_block_create_if(end_bprecond, ast_ctx(self), precond, ontrue, onfalse))
             return false;
     }
 
@@ -2490,7 +2490,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         else if (bpostcond)  tmpblock = bpostcond;
         else if (bprecond)   tmpblock = bprecond;
         else                 tmpblock = bbody;
-        if (!end_bbody->final && !ir_block_create_jump(end_bbody, tmpblock))
+        if (!end_bbody->final && !ir_block_create_jump(end_bbody, ast_ctx(self), tmpblock))
             return false;
     }
 
@@ -2501,7 +2501,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         else if (bprecond)   tmpblock = bprecond;
         else if (bbody)      tmpblock = bbody;
         else                 tmpblock = bout;
-        if (!ir_block_create_jump(end_bincrement, tmpblock))
+        if (!ir_block_create_jump(end_bincrement, ast_ctx(self), tmpblock))
             return false;
     }
 
@@ -2514,7 +2514,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         else if (bincrement) ontrue = bincrement;
         else                 ontrue = bpostcond;
         onfalse = bout;
-        if (!ir_block_create_if(end_bpostcond, postcond, ontrue, onfalse))
+        if (!ir_block_create_if(end_bpostcond, ast_ctx(self), postcond, ontrue, onfalse))
             return false;
     }
 
@@ -2552,7 +2552,7 @@ bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue,
         return false;
     }
 
-    if (!ir_block_create_jump(func->curblock, target))
+    if (!ir_block_create_jump(func->curblock, ast_ctx(self), target))
         return false;
     return true;
 }
@@ -2627,7 +2627,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
             if (!(*cgen)((ast_expression*)(swcase->value), func, false, &val))
                 return false;
             /* generate the condition */
-            cond = ir_block_create_binop(func->curblock, ast_function_label(func, "switch_eq"), cmpinstr, irop, val);
+            cond = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "switch_eq"), cmpinstr, irop, val);
             if (!cond)
                 return false;
 
@@ -2636,12 +2636,12 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
             bnot = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "not_case"));
             if (!bcase || !bnot)
                 return false;
-            if (!ir_block_create_if(func->curblock, cond, bcase, bnot))
+            if (!ir_block_create_if(func->curblock, ast_ctx(self), cond, bcase, bnot))
                 return false;
 
             /* Make the previous case-end fall through */
             if (bfall && !bfall->final) {
-                if (!ir_block_create_jump(bfall, bcase))
+                if (!ir_block_create_jump(bfall, ast_ctx(self), bcase))
                     return false;
             }
 
@@ -2669,7 +2669,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
     }
 
     /* Jump from the last bnot to bout */
-    if (bfall && !bfall->final && !ir_block_create_jump(bfall, bout)) {
+    if (bfall && !bfall->final && !ir_block_create_jump(bfall, ast_ctx(self), bout)) {
         /*
         astwarning(ast_ctx(bfall), WARN_???, "missing break after last case");
         */
@@ -2685,7 +2685,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
 
         /* Insert the fallthrough jump */
         if (def_bfall && !def_bfall->final) {
-            if (!ir_block_create_jump(def_bfall, bcase))
+            if (!ir_block_create_jump(def_bfall, ast_ctx(self), bcase))
                 return false;
         }
 
@@ -2696,7 +2696,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
     }
 
     /* Jump from the last bnot to bout */
-    if (!func->curblock->final && !ir_block_create_jump(func->curblock, bout))
+    if (!func->curblock->final && !ir_block_create_jump(func->curblock, ast_ctx(self), bout))
         return false;
     /* enter the outgoing block */
     func->curblock = bout;
@@ -2729,7 +2729,7 @@ bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_valu
         return false;
     }
     if (!func->curblock->final) {
-        if (!ir_block_create_jump(func->curblock, self->irblock))
+        if (!ir_block_create_jump(func->curblock, ast_ctx(self), self->irblock))
             return false;
     }
 
@@ -2757,14 +2757,14 @@ bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value
         if (self->irblock_from) {
             /* we already tried once, this is the callback */
             self->irblock_from->final = false;
-            if (!ir_block_create_jump(self->irblock_from, self->target->irblock)) {
+            if (!ir_block_create_jump(self->irblock_from, ast_ctx(self), self->target->irblock)) {
                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
                 return false;
             }
         }
         else
         {
-            if (!ir_block_create_jump(func->curblock, self->target->irblock)) {
+            if (!ir_block_create_jump(func->curblock, ast_ctx(self), self->target->irblock)) {
                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
                 return false;
             }
@@ -2825,7 +2825,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
         vec_push(params, param);
     }
 
-    callinstr = ir_block_create_call(func->curblock, ast_function_label(func, "call"), funval);
+    callinstr = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "call"), funval);
     if (!callinstr)
         goto error;
 
diff --git a/code.c b/code.c
index dbc9963b32d4fcff4ca56bb6d1a6d9533a68eaa4..052b13a8937016bd2cb5997b6989cc17510c43e7 100644 (file)
--- a/code.c
+++ b/code.c
 #include "gmqcc.h"
 
 prog_section_statement *code_statements;
+int                    *code_linenums;
 prog_section_def       *code_defs;
 prog_section_field     *code_fields;
 prog_section_function  *code_functions;
 int                    *code_globals;
 char                   *code_chars;
 
-uint16_t                            code_crc;
-uint32_t                            code_entfields;
+uint16_t                code_crc;
+uint32_t                code_entfields;
+
+void code_push_statement(prog_section_statement *stmt, int linenum)
+{
+    vec_push(code_statements, *stmt);
+    vec_push(code_linenums,   linenum);
+}
 
 void code_init() {
     prog_section_function  empty_function  = {0,0,0,0,0,0,0,{0}};
@@ -54,7 +61,7 @@ void code_init() {
 
     vec_push(code_chars, '\0');
     vec_push(code_functions,  empty_function);
-    vec_push(code_statements, empty_statement);
+    code_push_statement(&empty_statement, 0);
     vec_push(code_defs,       empty_def);
     vec_push(code_fields,     empty_def);
 }
@@ -134,7 +141,7 @@ qcint code_alloc_field (size_t qcsize)
     return pos;
 }
 
-bool code_write(const char *filename) {
+bool code_write(const char *filename, const char *lnofile) {
     prog_header  code_header;
     FILE        *fp           = NULL;
     size_t       it           = 2;
@@ -169,6 +176,40 @@ bool code_write(const char *filename) {
         vec_push(code_chars, '\0'); /* P */
     }
 
+    if (lnofile) {
+        uint32_t lnotype = *(unsigned int*)"LNOF";
+        uint32_t version = 1;
+
+        fp = util_fopen(lnofile, "wb");
+        if (!fp)
+            return false;
+
+        if (fwrite(&lnotype, sizeof(lnotype), 1, fp) != 1 ||
+            fwrite(&version, sizeof(version), 1, fp) != 1 ||
+            fwrite(&code_header.defs.length,        sizeof(code_header.defs.length),        1, fp) != 1 ||
+            fwrite(&code_header.globals.length,     sizeof(code_header.globals.length),     1, fp) != 1 ||
+            fwrite(&code_header.fields.length,      sizeof(code_header.fields.length),      1, fp) != 1 ||
+            fwrite(&code_header.statements.length,  sizeof(code_header.statements.length),  1, fp) != 1 ||
+            fwrite(code_linenums, sizeof(code_linenums[0]), vec_size(code_linenums), fp) != vec_size(code_linenums))
+        {
+            con_err("failed to write lno file\n");
+        }
+            /*
+                       h = SafeOpenWrite (destfile, 2*1024*1024);
+                       SafeWrite (h, &lnotype, sizeof(int));
+                       SafeWrite (h, &version, sizeof(int));
+                       SafeWrite (h, &numglobaldefs, sizeof(int));
+                       SafeWrite (h, &numpr_globals, sizeof(int));
+                       SafeWrite (h, &numfielddefs, sizeof(int));
+                       SafeWrite (h, &numstatements, sizeof(int));
+                       SafeWrite (h, statement_linenums, numstatements*sizeof(int));
+                       SafeClose (h);
+                       */
+
+        fclose(fp);
+        fp = NULL;
+    }
+
     /* ensure all data is in LE format */
     util_endianswap(&code_header,    1,                         sizeof(prog_header));
     util_endianswap(code_statements, vec_size(code_statements), sizeof(prog_section_statement));
diff --git a/gmqcc.h b/gmqcc.h
index 33346cef93e091c9f4f8c71736cc5f15218bdd09..0e4f4bd3b00ef0309bc88d058314326ab87ec0a1 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -537,6 +537,7 @@ enum {
 };
 
 extern prog_section_statement *code_statements;
+extern int                    *code_linenums;
 extern prog_section_def       *code_defs;
 extern prog_section_field     *code_fields;
 extern prog_section_function  *code_functions;
@@ -551,12 +552,15 @@ typedef int32_t qcint;
  * code_write -- writes out the compiled file
  * code_init  -- prepares the code file
  */
-bool     code_write       (const char *filename);
+bool     code_write       (const char *filename, const char *lno);
 void     code_init        ();
 uint32_t code_genstring   (const char *string);
 uint32_t code_cachedstring(const char *string);
 qcint    code_alloc_field (size_t qcsize);
 
+/* this function is used to keep statements and linenumbers together */
+void     code_push_statement(prog_section_statement *stmt, int linenum);
+
 /*
  * A shallow copy of a lex_file to remember where which ast node
  * came from.
diff --git a/ir.c b/ir.c
index b2bdeb0bcc3b44c0d54e32567dde30316488c382..a203d170a69d07449226b77f6cc5c671011f7661 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -594,12 +594,12 @@ bool ir_function_pass_tailcall(ir_function *self)
         /* emite parameter-stores */
         for (p = 0; p < vec_size(call->params); ++p) {
             /* assert(call->params_count <= self->locals_count); */
-            if (!ir_block_create_store(block, self->locals[p], call->params[p])) {
+            if (!ir_block_create_store(block, call->context, self->locals[p], call->params[p])) {
                 irerror(call->context, "failed to create tailcall store instruction for parameter %i", (int)p);
                 return false;
             }
         }
-        if (!ir_block_create_jump(block, self->blocks[0])) {
+        if (!ir_block_create_jump(block, call->context, self->blocks[0])) {
             irerror(call->context, "failed to create tailcall jump");
             return false;
         }
@@ -727,7 +727,7 @@ bool ir_block_set_label(ir_block *self, const char *name)
  *IR Instructions
  */
 
-ir_instr* ir_instr_new(ir_block* owner, int op)
+ir_instr* ir_instr_new(lex_ctx ctx, ir_block* owner, int op)
 {
     ir_instr *self;
     self = (ir_instr*)mem_a(sizeof(*self));
@@ -735,8 +735,7 @@ ir_instr* ir_instr_new(ir_block* owner, int op)
         return NULL;
 
     self->owner = owner;
-    self->context.file = "<@no context>";
-    self->context.line = 0;
+    self->context = ctx;
     self->opcode = op;
     self->_ops[0] = NULL;
     self->_ops[1] = NULL;
@@ -1228,14 +1227,14 @@ bool ir_values_overlap(const ir_value *a, const ir_value *b)
  *IR main operations
  */
 
-bool ir_block_create_store_op(ir_block *self, int op, ir_value *target, ir_value *what)
+bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *target, ir_value *what)
 {
     ir_instr *in;
     if (self->final) {
         irerror(self->context, "unreachable statement (%s)", self->label);
         return false;
     }
-    in = ir_instr_new(self, op);
+    in = ir_instr_new(ctx, self, op);
     if (!in)
         return false;
 
@@ -1257,7 +1256,7 @@ bool ir_block_create_store_op(ir_block *self, int op, ir_value *target, ir_value
     return true;
 }
 
-bool ir_block_create_store(ir_block *self, ir_value *target, ir_value *what)
+bool ir_block_create_store(ir_block *self, lex_ctx ctx, ir_value *target, ir_value *what)
 {
     int op = 0;
     int vtype;
@@ -1279,10 +1278,10 @@ bool ir_block_create_store(ir_block *self, ir_value *target, ir_value *what)
             op = INSTR_STORE_V;
     }
 
-    return ir_block_create_store_op(self, op, target, what);
+    return ir_block_create_store_op(self, ctx, op, target, what);
 }
 
-bool ir_block_create_storep(ir_block *self, ir_value *target, ir_value *what)
+bool ir_block_create_storep(ir_block *self, lex_ctx ctx, ir_value *target, ir_value *what)
 {
     int op = 0;
     int vtype;
@@ -1301,10 +1300,10 @@ bool ir_block_create_storep(ir_block *self, ir_value *target, ir_value *what)
             op = INSTR_STOREP_V;
     }
 
-    return ir_block_create_store_op(self, op, target, what);
+    return ir_block_create_store_op(self, ctx, op, target, what);
 }
 
-bool ir_block_create_return(ir_block *self, ir_value *v)
+bool ir_block_create_return(ir_block *self, lex_ctx ctx, ir_value *v)
 {
     ir_instr *in;
     if (self->final) {
@@ -1313,7 +1312,7 @@ bool ir_block_create_return(ir_block *self, ir_value *v)
     }
     self->final = true;
     self->is_return = true;
-    in = ir_instr_new(self, INSTR_RETURN);
+    in = ir_instr_new(ctx, self, INSTR_RETURN);
     if (!in)
         return false;
 
@@ -1324,7 +1323,7 @@ bool ir_block_create_return(ir_block *self, ir_value *v)
     return true;
 }
 
-bool ir_block_create_if(ir_block *self, ir_value *v,
+bool ir_block_create_if(ir_block *self, lex_ctx ctx, ir_value *v,
                         ir_block *ontrue, ir_block *onfalse)
 {
     ir_instr *in;
@@ -1333,8 +1332,8 @@ bool ir_block_create_if(ir_block *self, ir_value *v,
         return false;
     }
     self->final = true;
-    /*in = ir_instr_new(self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/
-    in = ir_instr_new(self, VINSTR_COND);
+    /*in = ir_instr_new(ctx, self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/
+    in = ir_instr_new(ctx, self, VINSTR_COND);
     if (!in)
         return false;
 
@@ -1355,7 +1354,7 @@ bool ir_block_create_if(ir_block *self, ir_value *v,
     return true;
 }
 
-bool ir_block_create_jump(ir_block *self, ir_block *to)
+bool ir_block_create_jump(ir_block *self, lex_ctx ctx, ir_block *to)
 {
     ir_instr *in;
     if (self->final) {
@@ -1363,7 +1362,7 @@ bool ir_block_create_jump(ir_block *self, ir_block *to)
         return false;
     }
     self->final = true;
-    in = ir_instr_new(self, VINSTR_JUMP);
+    in = ir_instr_new(ctx, self, VINSTR_JUMP);
     if (!in)
         return false;
 
@@ -1375,7 +1374,7 @@ bool ir_block_create_jump(ir_block *self, ir_block *to)
     return true;
 }
 
-bool ir_block_create_goto(ir_block *self, ir_block *to)
+bool ir_block_create_goto(ir_block *self, lex_ctx ctx, ir_block *to)
 {
     ir_instr *in;
     if (self->final) {
@@ -1383,7 +1382,7 @@ bool ir_block_create_goto(ir_block *self, ir_block *to)
         return false;
     }
     self->final = true;
-    in = ir_instr_new(self, INSTR_GOTO);
+    in = ir_instr_new(ctx, self, INSTR_GOTO);
     if (!in)
         return false;
 
@@ -1395,11 +1394,11 @@ bool ir_block_create_goto(ir_block *self, ir_block *to)
     return true;
 }
 
-ir_instr* ir_block_create_phi(ir_block *self, const char *label, int ot)
+ir_instr* ir_block_create_phi(ir_block *self, lex_ctx ctx, const char *label, int ot)
 {
     ir_value *out;
     ir_instr *in;
-    in = ir_instr_new(self, VINSTR_PHI);
+    in = ir_instr_new(ctx, self, VINSTR_PHI);
     if (!in)
         return NULL;
     out = ir_value_out(self->owner, label, store_value, ot);
@@ -1440,11 +1439,11 @@ void ir_phi_add(ir_instr* self, ir_block *b, ir_value *v)
 }
 
 /* call related code */
-ir_instr* ir_block_create_call(ir_block *self, const char *label, ir_value *func)
+ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, ir_value *func)
 {
     ir_value *out;
     ir_instr *in;
-    in = ir_instr_new(self, INSTR_CALL0);
+    in = ir_instr_new(ctx, self, INSTR_CALL0);
     if (!in)
         return NULL;
     out = ir_value_out(self->owner, label, (func->outtype == TYPE_VOID) ? store_return : store_value, func->outtype);
@@ -1476,7 +1475,7 @@ void ir_call_param(ir_instr* self, ir_value *v)
 
 /* binary op related code */
 
-ir_value* ir_block_create_binop(ir_block *self,
+ir_value* ir_block_create_binop(ir_block *self, lex_ctx ctx,
                                 const char *label, int opcode,
                                 ir_value *left, ir_value *right)
 {
@@ -1565,10 +1564,10 @@ ir_value* ir_block_create_binop(ir_block *self,
         return NULL;
     }
 
-    return ir_block_create_general_instr(self, label, opcode, left, right, ot);
+    return ir_block_create_general_instr(self, ctx, label, opcode, left, right, ot);
 }
 
-ir_value* ir_block_create_unary(ir_block *self,
+ir_value* ir_block_create_unary(ir_block *self, lex_ctx ctx,
                                 const char *label, int opcode,
                                 ir_value *operand)
 {
@@ -1598,10 +1597,10 @@ ir_value* ir_block_create_unary(ir_block *self,
     }
 
     /* let's use the general instruction creator and pass NULL for OPB */
-    return ir_block_create_general_instr(self, label, opcode, operand, NULL, ot);
+    return ir_block_create_general_instr(self, ctx, label, opcode, operand, NULL, ot);
 }
 
-ir_value* ir_block_create_general_instr(ir_block *self, const char *label,
+ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx ctx, const char *label,
                                         int op, ir_value *a, ir_value *b, int outype)
 {
     ir_instr *instr;
@@ -1611,7 +1610,7 @@ ir_value* ir_block_create_general_instr(ir_block *self, const char *label,
     if (!out)
         return NULL;
 
-    instr = ir_instr_new(self, op);
+    instr = ir_instr_new(ctx, self, op);
     if (!instr) {
         ir_value_delete(out);
         return NULL;
@@ -1633,7 +1632,7 @@ on_error:
     return NULL;
 }
 
-ir_value* ir_block_create_fieldaddress(ir_block *self, const char *label, ir_value *ent, ir_value *field)
+ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx ctx, const char *label, ir_value *ent, ir_value *field)
 {
     ir_value *v;
 
@@ -1644,12 +1643,12 @@ ir_value* ir_block_create_fieldaddress(ir_block *self, const char *label, ir_val
     if (field->vtype != TYPE_FIELD)
         return NULL;
 
-    v = ir_block_create_general_instr(self, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
+    v = ir_block_create_general_instr(self, ctx, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
     v->fieldtype = field->fieldtype;
     return v;
 }
 
-ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_value *ent, ir_value *field, int outype)
+ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx ctx, const char *label, ir_value *ent, ir_value *field, int outype)
 {
     int op;
     if (ent->vtype != TYPE_ENTITY)
@@ -1676,10 +1675,10 @@ ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_va
             return NULL;
     }
 
-    return ir_block_create_general_instr(self, label, op, ent, field, outype);
+    return ir_block_create_general_instr(self, ctx, label, op, ent, field, outype);
 }
 
-ir_value* ir_block_create_add(ir_block *self,
+ir_value* ir_block_create_add(ir_block *self, lex_ctx ctx,
                               const char *label,
                               ir_value *left, ir_value *right)
 {
@@ -1716,10 +1715,10 @@ ir_value* ir_block_create_add(ir_block *self,
             return NULL;
         }
     }
-    return ir_block_create_binop(self, label, op, left, right);
+    return ir_block_create_binop(self, ctx, label, op, left, right);
 }
 
-ir_value* ir_block_create_sub(ir_block *self,
+ir_value* ir_block_create_sub(ir_block *self, lex_ctx ctx,
                               const char *label,
                               ir_value *left, ir_value *right)
 {
@@ -1757,10 +1756,10 @@ ir_value* ir_block_create_sub(ir_block *self,
             return NULL;
         }
     }
-    return ir_block_create_binop(self, label, op, left, right);
+    return ir_block_create_binop(self, ctx, label, op, left, right);
 }
 
-ir_value* ir_block_create_mul(ir_block *self,
+ir_value* ir_block_create_mul(ir_block *self, lex_ctx ctx,
                               const char *label,
                               ir_value *left, ir_value *right)
 {
@@ -1805,10 +1804,10 @@ ir_value* ir_block_create_mul(ir_block *self,
             return NULL;
         }
     }
-    return ir_block_create_binop(self, label, op, left, right);
+    return ir_block_create_binop(self, ctx, label, op, left, right);
 }
 
-ir_value* ir_block_create_div(ir_block *self,
+ir_value* ir_block_create_div(ir_block *self, lex_ctx ctx,
                               const char *label,
                               ir_value *left, ir_value *right)
 {
@@ -1845,7 +1844,7 @@ ir_value* ir_block_create_div(ir_block *self,
             return NULL;
         }
     }
-    return ir_block_create_binop(self, label, op, left, right);
+    return ir_block_create_binop(self, ctx, label, op, left, right);
 }
 
 /* PHI resolving breaks the SSA, and must thus be the last
@@ -1921,7 +1920,7 @@ static bool ir_block_naive_phi(ir_block *self)
                 vec_pop(b->instr);
                 b->final = false;
                 instr->_ops[0]->store = store_global;
-                if (!ir_block_create_store(b, instr->_ops[0], v))
+                if (!ir_block_create_store(b, instr->context, instr->_ops[0], v))
                     return false;
                 instr->_ops[0]->store = store_value;
                 vec_push(b->instr, prevjump);
@@ -2560,7 +2559,7 @@ tailcall:
             stmt.o1.s1 = (target->code_start) - vec_size(code_statements);
             stmt.o2.s1 = 0;
             stmt.o3.s1 = 0;
-            vec_push(code_statements, stmt);
+            code_push_statement(&stmt, instr->context.line);
 
             /* no further instructions can be in this block */
             return true;
@@ -2580,12 +2579,12 @@ tailcall:
             if (ontrue->generated) {
                 stmt.opcode = INSTR_IF;
                 stmt.o2.s1 = (ontrue->code_start) - vec_size(code_statements);
-                vec_push(code_statements, stmt);
+                code_push_statement(&stmt, instr->context.line);
             }
             if (onfalse->generated) {
                 stmt.opcode = INSTR_IFNOT;
                 stmt.o2.s1 = (onfalse->code_start) - vec_size(code_statements);
-                vec_push(code_statements, stmt);
+                code_push_statement(&stmt, instr->context.line);
             }
             if (!ontrue->generated) {
                 if (onfalse->generated) {
@@ -2609,7 +2608,7 @@ tailcall:
                 ontrue = tmp;
             }
             stidx = vec_size(code_statements);
-            vec_push(code_statements, stmt);
+            code_push_statement(&stmt, instr->context.line);
             /* on false we jump, so add ontrue-path */
             if (!gen_blocks_recursive(func, ontrue))
                 return false;
@@ -2634,7 +2633,7 @@ tailcall:
                 stmt.o1.s1 = (onfalse->code_start) - vec_size(code_statements);
                 stmt.o2.s1 = 0;
                 stmt.o3.s1 = 0;
-                vec_push(code_statements, stmt);
+                code_push_statement(&stmt, instr->context.line);
                 return true;
             }
             /* if not, generate now */
@@ -2675,7 +2674,7 @@ tailcall:
                     stmt.opcode = type_store_instr[param->vtype];
                 stmt.o1.u1 = ir_value_code_addr(param);
                 stmt.o2.u1 = OFS_PARM0 + 3 * p;
-                vec_push(code_statements, stmt);
+                code_push_statement(&stmt, instr->context.line);
             }
             /* Now handle extparams */
             first = vec_size(instr->params);
@@ -2701,7 +2700,7 @@ tailcall:
                     stmt.opcode = type_store_instr[param->vtype];
                 stmt.o1.u1 = ir_value_code_addr(param);
                 stmt.o2.u1 = ir_value_code_addr(targetparam);
-                vec_push(code_statements, stmt);
+                code_push_statement(&stmt, instr->context.line);
             }
 
             stmt.opcode = INSTR_CALL0 + vec_size(instr->params);
@@ -2710,7 +2709,7 @@ tailcall:
             stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.u1 = 0;
             stmt.o3.u1 = 0;
-            vec_push(code_statements, stmt);
+            code_push_statement(&stmt, instr->context.line);
 
             retvalue = instr->_ops[0];
             if (retvalue && retvalue->store != store_return && vec_size(retvalue->life))
@@ -2723,7 +2722,7 @@ tailcall:
                 stmt.o1.u1 = OFS_RETURN;
                 stmt.o2.u1 = ir_value_code_addr(retvalue);
                 stmt.o3.u1 = 0;
-                vec_push(code_statements, stmt);
+                code_push_statement(&stmt, instr->context.line);
             }
             continue;
         }
@@ -2763,7 +2762,7 @@ tailcall:
             stmt.o3.u1 = 0;
         }
 
-        vec_push(code_statements, stmt);
+        code_push_statement(&stmt, instr->context.line);
     }
     return true;
 }
@@ -2795,7 +2794,7 @@ static bool gen_function_code(ir_function *self)
     stmt.o1.u1 = 0;
     stmt.o2.u1 = 0;
     stmt.o3.u1 = 0;
-    vec_push(code_statements, stmt);
+    code_push_statement(&stmt, vec_last(code_linenums));
     return true;
 }
 
@@ -2937,7 +2936,7 @@ static bool gen_function_extparam_copy(ir_function *self)
         }
         stmt.o1.u1 = ir_value_code_addr(ep);
         stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
-        vec_push(code_statements, stmt);
+        code_push_statement(&stmt, self->context.line);
     }
 
     return true;
@@ -3190,6 +3189,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
 {
     prog_section_statement stmt;
     size_t i;
+    char   *lnofile = NULL;
 
     code_init();
 
@@ -3230,11 +3230,39 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
     stmt.o1.u1 = 0;
     stmt.o2.u1 = 0;
     stmt.o3.u1 = 0;
-    vec_push(code_statements, stmt);
+    code_push_statement(&stmt, vec_last(code_linenums));
+
+    if (opts_pp_only)
+        return true;
+
+    if (vec_size(code_statements) != vec_size(code_linenums)) {
+        con_err("Linecounter wrong: %lu != %lu\n",
+                (unsigned long)vec_size(code_statements),
+                (unsigned long)vec_size(code_linenums));
+    } else if (OPTS_FLAG(LNO)) {
+        char *dot;
+        size_t filelen = strlen(filename);
+
+        memcpy(vec_add(lnofile, filelen+1), filename, filelen+1);
+        dot = strrchr(lnofile, '.');
+        if (!dot) {
+            vec_pop(lnofile);
+        } else {
+            vec_shrinkto(lnofile, dot - lnofile);
+        }
+        memcpy(vec_add(lnofile, 5), ".lno", 5);
+    }
 
-    if (!opts_pp_only)
-        con_out("writing '%s'...\n", filename);
-    return code_write(filename);
+    if (lnofile)
+        con_out("writing '%s' and '%s'...\n", filename, lnofile);
+    else
+        con_out("writing '%s'\n", filename);
+    if (!code_write(filename, lnofile)) {
+        vec_free(lnofile);
+        return false;
+    }
+    vec_free(lnofile);
+    return true;
 }
 
 /***********************************************************************
diff --git a/ir.h b/ir.h
index 6e32d98ef07cdb69eb3373293445965df646ef32..6888e6c4172b85c2d111098d928ced47e4a4ce3c 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -141,7 +141,7 @@ typedef struct ir_instr_s
     struct ir_block_s *owner;
 } ir_instr;
 
-ir_instr* ir_instr_new(struct ir_block_s *owner, int opcode);
+ir_instr* ir_instr_new(lex_ctx ctx, struct ir_block_s *owner, int opcode);
 void      ir_instr_delete(ir_instr*);
 
 bool GMQCC_WARN vec_ir_instr_find(ir_instr **vec, ir_instr *what, size_t *idx);
@@ -178,39 +178,39 @@ void      ir_block_delete(ir_block*);
 
 bool      ir_block_set_label(ir_block*, const char *label);
 
-ir_value* ir_block_create_binop(ir_block*, const char *label, int op,
+ir_value* ir_block_create_binop(ir_block*, lex_ctx, const char *label, int op,
                                 ir_value *left, ir_value *right);
-ir_value* ir_block_create_unary(ir_block*, const char *label, int op,
+ir_value* ir_block_create_unary(ir_block*, lex_ctx, const char *label, int op,
                                 ir_value *operand);
-bool GMQCC_WARN ir_block_create_store_op(ir_block*, int op, ir_value *target, ir_value *what);
-bool GMQCC_WARN ir_block_create_store(ir_block*, ir_value *target, ir_value *what);
-bool GMQCC_WARN ir_block_create_storep(ir_block*, ir_value *target, ir_value *what);
+bool GMQCC_WARN ir_block_create_store_op(ir_block*, lex_ctx, int op, ir_value *target, ir_value *what);
+bool GMQCC_WARN ir_block_create_store(ir_block*, lex_ctx, ir_value *target, ir_value *what);
+bool GMQCC_WARN ir_block_create_storep(ir_block*, lex_ctx, ir_value *target, ir_value *what);
 
 /* field must be of TYPE_FIELD */
-ir_value* ir_block_create_load_from_ent(ir_block*, const char *label, ir_value *ent, ir_value *field, int outype);
+ir_value* ir_block_create_load_from_ent(ir_block*, lex_ctx, const char *label, ir_value *ent, ir_value *field, int outype);
 
-ir_value* ir_block_create_fieldaddress(ir_block*, const char *label, ir_value *entity, ir_value *field);
+ir_value* ir_block_create_fieldaddress(ir_block*, lex_ctx, const char *label, ir_value *entity, ir_value *field);
 
 /* This is to create an instruction of the form
  * <outtype>%label := opcode a, b
  */
-ir_value* ir_block_create_general_instr(ir_block *self, const char *label,
+ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx, const char *label,
                                         int op, ir_value *a, ir_value *b, int outype);
 
-ir_value* ir_block_create_add(ir_block*, const char *label, ir_value *l, ir_value *r);
-ir_value* ir_block_create_sub(ir_block*, const char *label, ir_value *l, ir_value *r);
-ir_value* ir_block_create_mul(ir_block*, const char *label, ir_value *l, ir_value *r);
-ir_value* ir_block_create_div(ir_block*, const char *label, ir_value *l, ir_value *r);
-ir_instr* ir_block_create_phi(ir_block*, const char *label, int vtype);
+ir_value* ir_block_create_add(ir_block*, lex_ctx, const char *label, ir_value *l, ir_value *r);
+ir_value* ir_block_create_sub(ir_block*, lex_ctx, const char *label, ir_value *l, ir_value *r);
+ir_value* ir_block_create_mul(ir_block*, lex_ctx, const char *label, ir_value *l, ir_value *r);
+ir_value* ir_block_create_div(ir_block*, lex_ctx, const char *label, ir_value *l, ir_value *r);
+ir_instr* ir_block_create_phi(ir_block*, lex_ctx, const char *label, int vtype);
 ir_value* ir_phi_value(ir_instr*);
 void ir_phi_add(ir_instr*, ir_block *b, ir_value *v);
-ir_instr* ir_block_create_call(ir_block*, const char *label, ir_value *func);
+ir_instr* ir_block_create_call(ir_block*, lex_ctx, const char *label, ir_value *func);
 ir_value* ir_call_value(ir_instr*);
 void ir_call_param(ir_instr*, ir_value*);
 
-bool GMQCC_WARN ir_block_create_return(ir_block*, ir_value *opt_value);
+bool GMQCC_WARN ir_block_create_return(ir_block*, lex_ctx, ir_value *opt_value);
 
-bool GMQCC_WARN ir_block_create_if(ir_block*, ir_value *cond,
+bool GMQCC_WARN ir_block_create_if(ir_block*, lex_ctx, ir_value *cond,
                                    ir_block *ontrue, ir_block *onfalse);
 /* A 'goto' is an actual 'goto' coded in QC, whereas
  * a 'jump' is a virtual construct which simply names the
@@ -218,8 +218,8 @@ bool GMQCC_WARN ir_block_create_if(ir_block*, ir_value *cond,
  * A goto usually becomes an OP_GOTO in the resulting code,
  * whereas a 'jump' usually doesn't add any actual instruction.
  */
-bool GMQCC_WARN ir_block_create_jump(ir_block*, ir_block *to);
-bool GMQCC_WARN ir_block_create_goto(ir_block*, ir_block *to);
+bool GMQCC_WARN ir_block_create_jump(ir_block*, lex_ctx, ir_block *to);
+bool GMQCC_WARN ir_block_create_goto(ir_block*, lex_ctx, ir_block *to);
 
 void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...));
 
index 62da391c4b46bd1d1659e611e0ba39ea261c431e..64152243b63769ac1b6bf3cbda7c9eb3008908ec 100644 (file)
--- a/opts.def
+++ b/opts.def
@@ -38,6 +38,7 @@
     GMQCC_DEFINE_FLAG(TRANSLATABLE_STRINGS)
     GMQCC_DEFINE_FLAG(INITIALIZED_NONCONSTANTS)
     GMQCC_DEFINE_FLAG(ASSIGN_FUNCTION_TYPES)
+    GMQCC_DEFINE_FLAG(LNO)
 #endif
 
 /* warning flags */