All ir_instrs now get their lex-context, so that we can create an LNO file with -flno

This commit is contained in:
Wolfgang (Blub) Bumiller 2012-11-30 18:19:26 +01:00
parent 2f3612d905
commit 6fc00e523d
6 changed files with 201 additions and 127 deletions

88
ast.c
View file

@ -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;

49
code.c
View file

@ -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));

View file

@ -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.

146
ir.c
View file

@ -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)
con_out("writing '%s'...\n", filename);
return code_write(filename);
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 (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;
}
/***********************************************************************

38
ir.h
View file

@ -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*,...));

View file

@ -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 */