/* 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;
}
*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));
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;
*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;
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;
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;
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) {
}
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;
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;
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;
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) {
return false;
}
self->final = true;
- in = ir_instr_new(self, VINSTR_JUMP);
+ in = ir_instr_new(ctx, self, VINSTR_JUMP);
if (!in)
return false;
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) {
return false;
}
self->final = true;
- in = ir_instr_new(self, INSTR_GOTO);
+ in = ir_instr_new(ctx, self, INSTR_GOTO);
if (!in)
return false;
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);
}
/* 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);
/* 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)
{
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)
{
}
/* 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;
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;
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;
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)
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)
{
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)
{
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)
{
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)
{
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
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);
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;
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) {
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;
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 */
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);
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);
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))
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;
}
stmt.o3.u1 = 0;
}
- vec_push(code_statements, stmt);
+ code_push_statement(&stmt, instr->context.line);
}
return true;
}
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;
}
}
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;
{
prog_section_statement stmt;
size_t i;
+ char *lnofile = NULL;
code_init();
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;
}
/***********************************************************************