From 61d3a9d1a0d94406bd6ee215b18748d7ba9c83a8 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Wed, 9 May 2012 15:02:58 +0200 Subject: [PATCH] generating block code in a simple naive order for now - the ast / parser should help improving order --- ir.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- ir.h | 3 ++ 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/ir.c b/ir.c index 5f2477d..30817a0 100644 --- a/ir.c +++ b/ir.c @@ -1780,9 +1780,166 @@ static bool gen_global_pointer(ir_value *global) return true; } +static bool gen_blocks_recursive(ir_function *func, ir_block *block) +{ + prog_section_statement stmt; + prog_section_statement *stptr; + ir_instr *instr; + ir_block *target; + ir_block *ontrue; + ir_block *onfalse; + size_t stidx; + size_t i; + +tailcall: + block->generated = true; + block->code_start = code_statements_elements; + for (i = 0; i < block->instr_count; ++i) + { + instr = block->instr[i]; + + if (instr->opcode == VINSTR_PHI) { + printf("cannot generate virtual instruction (phi)\n"); + return false; + } + + if (instr->opcode == VINSTR_JUMP) { + target = instr->bops[0]; + /* for uncoditional jumps, if the target hasn't been generated + * yet, we generate them right here. + */ + if (!target->generated) { + block = target; + goto tailcall; + } + + /* otherwise we generate a jump instruction */ + stmt.opcode = INSTR_GOTO; + stmt.o1.s1 = (target->code_start-1) - code_statements_elements; + stmt.o2.s1 = 0; + stmt.o3.s1 = 0; + if (code_statements_add(stmt) < 0) + return false; + + /* no further instructions can be in this block */ + return true; + } + + if (instr->opcode == VINSTR_COND) { + ontrue = instr->bops[0]; + onfalse = instr->bops[1]; + /* TODO: have the AST signal which block should + * come first: eg. optimize IFs without ELSE... + */ + + stmt.o1.s1 = instr->_ops[0]->code.globaladdr; + + stmt.o3.s1 = 0; + if (ontrue->generated) { + stmt.opcode = INSTR_IF; + stmt.o2.s1 = (ontrue->code_start-1) - code_statements_elements; + if (code_statements_add(stmt) < 0) + return false; + } + if (onfalse->generated) { + stmt.opcode = INSTR_IFNOT; + stmt.o2.s1 = (onfalse->code_start-1) - code_statements_elements; + if (code_statements_add(stmt) < 0) + return false; + } + if (!ontrue->generated) { + if (onfalse->generated) { + block = ontrue; + goto tailcall; + } + } + if (!onfalse->generated) { + if (ontrue->generated) { + block = onfalse; + goto tailcall; + } + } + /* neither ontrue nor onfalse exist */ + stmt.opcode = INSTR_IFNOT; + stidx = code_statements_elements - 1; + if (code_statements_add(stmt) < 0) + return false; + stptr = &code_statements_data[stidx]; + /* on false we jump, so add ontrue-path */ + if (!gen_blocks_recursive(func, ontrue)) + return false; + /* fixup the jump address */ + stptr->o2.s1 = (ontrue->code_start-1) - (stidx+1); + /* generate onfalse path */ + if (onfalse->generated) { + /* may have been generated in the previous recursive call */ + stmt.opcode = INSTR_GOTO; + stmt.o2.s1 = 0; + stmt.o3.s1 = 0; + stmt.o1.s1 = (onfalse->code_start-1) - code_statements_elements; + return (code_statements_add(stmt) >= 0); + } + /* if not, generate now */ + block = onfalse; + goto tailcall; + } + + if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) { + printf("TODO: call instruction\n"); + return false; + } + + if (instr->opcode == INSTR_STATE) { + printf("TODO: state instruction\n"); + return false; + } + + stmt.opcode = instr->opcode; + stmt.o1.u1 = 0; + stmt.o2.u1 = 0; + stmt.o3.u1 = 0; + + /* This is the general order of operands */ + if (instr->_ops[0]) + stmt.o3.u1 = instr->_ops[0]->code.globaladdr; + + if (instr->_ops[1]) + stmt.o1.u1 = instr->_ops[1]->code.globaladdr; + + if (instr->_ops[2]) + stmt.o2.u1 = instr->_ops[2]->code.globaladdr; + + if (stmt.opcode == INSTR_RETURN) + { + stmt.o1.u1 = stmt.o3.u1; + stmt.o3.u1 = 0; + } + + if (code_statements_add(stmt) < 0) + return false; + } + return true; +} + static bool gen_function_code(ir_function *self) { - return false; + ir_block *block; + + /* Starting from entry point, we generate blocks "as they come" + * for now. Dead blocks will not be translated obviously. + */ + if (!self->blocks_count) { + printf("Function '%s' declared without body.\n", self->name); + return false; + } + + block = self->blocks[0]; + if (block->generated) + return true; + + if (!gen_blocks_recursive(self, block)) + return false; + return true; } static bool gen_global_function(ir_builder *ir, ir_value *global) diff --git a/ir.h b/ir.h index d095054..78ff3c2 100644 --- a/ir.h +++ b/ir.h @@ -145,6 +145,9 @@ typedef struct ir_block_s size_t run_id; struct ir_function_s *owner; + + bool generated; + size_t code_start; } ir_block; ir_block* ir_block_new(struct ir_function_s *owner, const char *label); -- 2.39.2