From 6fc00e523d1c5678e40c9296b9e66fb6a6ee5bc7 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 30 Nov 2012 18:19:26 +0100 Subject: [PATCH] All ir_instrs now get their lex-context, so that we can create an LNO file with -flno --- ast.c | 88 ++++++++++++++++----------------- code.c | 49 +++++++++++++++++-- gmqcc.h | 6 ++- ir.c | 146 +++++++++++++++++++++++++++++++++---------------------- ir.h | 38 +++++++-------- opts.def | 1 + 6 files changed, 201 insertions(+), 127 deletions(-) diff --git a/ast.c b/ast.c index 25be65b..063084f 100644 --- 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 dbc9963..052b13a 100644 --- a/code.c +++ b/code.c @@ -24,14 +24,21 @@ #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 33346ce..0e4f4bd 100644 --- 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 b2bdeb0..a203d17 100644 --- 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 6e32d98..6888e6c 100644 --- 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 * %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*,...)); diff --git a/opts.def b/opts.def index 62da391..6415224 100644 --- 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 */ -- 2.39.2