Procedure compilation now happens after the entire EM file has been read in (so

that we can look inside data blocks which might be defined in the future...
sigh, csa and csb). csa and csb no longer generate invalid IR.
This commit is contained in:
David Given 2016-09-24 01:04:00 +02:00
parent ed67d427c9
commit bb9aa030a5
7 changed files with 103 additions and 20 deletions

View file

@ -39,7 +39,7 @@ bool tracing(char k)
{
case 'E': return false;
case '0': return false;
case '1': return false;
case '1': return true;
case '2': return true;
default: return true;
}
@ -57,6 +57,13 @@ void tracef(char k, const char* fmt, ...)
}
}
static bool find_procedures_cb(struct symbol* symbol, void* user)
{
if (symbol->proc)
procedure_compile(symbol->proc);
return false;
}
int main(int argc, char* argv[])
{
symbol_init();
@ -64,8 +71,17 @@ int main(int argc, char* argv[])
if (!EM_open(argv[1]))
fatal("Couldn't open input file: %s", EM_error);
/* Reads in the EM, outputs the data sections, parses any code and
* generates IR trees. */
parse_em();
/* For every procedure, go ahead and do the compilation proper. We do this
* now so that we know that all the data has been read correctly and our
* symbol table is complete (we may need to refer to it). */
symbol_walk(find_procedures_cb, NULL);
EM_close();
return 0;
}

View file

@ -36,6 +36,7 @@ struct symbol
{
const char* name;
int section;
struct procedure* proc;
bool is_defined : 1;
bool is_exported : 1;
bool is_proc : 1;
@ -96,6 +97,9 @@ extern bool symbol_exists(const char* name);
extern struct symbol* symbol_get(const char* name);
extern void symbol_declare(const char* name, bool is_exported, bool is_proc);
typedef bool symbol_walker_t(struct symbol* symbol, void* user);
extern struct symbol* symbol_walk(symbol_walker_t* walker, void* user);
extern void data_label(const char* name);
extern void data_int(arith data, size_t size, bool is_ro);
extern void data_block(const uint8_t* data, size_t size, bool is_ro);
@ -116,7 +120,7 @@ extern void pass_convert_stack_ops(struct procedure* proc);
extern void pass_remove_dead_blocks(struct procedure* proc);
extern void pass_eliminate_trivial_blocks(struct procedure* proc);
extern void compile(struct procedure* proc);
extern void procedure_compile(struct procedure* proc);
#endif

View file

@ -280,6 +280,9 @@ static void parse_pseu(void)
}
case ps_pro: /* procedure start */
{
struct symbol* symbol;
current_proc = calloc(sizeof(struct procedure), 1);
current_proc->name = strdup(insn.em_pnam);
current_proc->root_bb = bb_get(current_proc->name);
@ -287,11 +290,16 @@ static void parse_pseu(void)
code_bb = current_proc->root_bb;
code_bb->is_root = true;
APPEND(current_proc->blocks, code_bb);
symbol = symbol_get(current_proc->name);
symbol->section = SECTION_TEXT;
symbol->proc = current_proc;
symbol->is_proc = true;
break;
}
case ps_end: /* procedure end */
tb_procedure(current_proc);
compile(current_proc);
current_proc = NULL;
code_bb = NULL;
@ -336,6 +344,17 @@ static void parse_mes(void)
fatal("malformed MES");
}
static void create_data_label(const char* label)
{
data_label(label);
if (current_proc)
{
data_bb = bb_get(label);
data_bb->is_fake = true;
APPEND(current_proc->blocks, data_bb);
}
}
void parse_em(void)
{
EM_getinstr(&insn);
@ -354,16 +373,11 @@ void parse_em(void)
break;
case EM_DEFDLB:
{
const char* label = dlabel_to_str(insn.em_dlb);
data_label(label);
data_bb = bb_get(label);
data_bb->is_fake = true;
create_data_label(dlabel_to_str(insn.em_dlb));
break;
}
case EM_DEFDNAM:
data_label(strdup(insn.em_dnam));
create_data_label(strdup(insn.em_dnam));
break;
case EM_STARTMES:

View file

@ -5,7 +5,8 @@ static bool rewrite_jumps_cb(struct ir* ir, void* user)
if (ir->opcode == IR_BLOCK)
{
struct basicblock* bb = ir->u.bvalue;
if ((bb->irs_count > 0)
if (!bb->is_fake
&& (bb->irs_count > 0)
&& (bb->irs[0]->opcode == IR_JUMP)
&& (bb->irs[0]->left->opcode == IR_BLOCK))
{

View file

@ -11,14 +11,16 @@ static void print_blocks(char k, struct procedure* proc)
int j;
tracef(k, "%c:\n", k);
tracef(k, "%c: BLOCK: %s\n", k, bb->name);
tracef(k, "%c: %sBLOCK: %s\n", k,
bb->is_fake ? "FAKE " : "",
bb->name);
for (int j=0; j<bb->irs_count; j++)
ir_print(k, bb->irs[j]);
}
}
void compile(struct procedure* proc)
void procedure_compile(struct procedure* proc)
{
int i;

View file

@ -1,7 +1,10 @@
#include "mcg.h"
typedef int idf_walker_t(struct idf* idf, void* user);
static void init_idf();
static struct idf* str2idf(char* tg, int cp);
static struct idf* walk_idf(idf_walker_t* cb, void* user);
#define IDF_TYPE struct symbol
#define IDF_NAME symbol
@ -39,3 +42,22 @@ void symbol_declare(const char* name, bool is_exported, bool is_proc)
}
}
struct symbol* symbol_walk(symbol_walker_t* cb, void* user)
{
int i;
for (i=0; i<IDF_HASHSIZE; i++)
{
struct idf* idf = IDF_hashtable[i];
while (idf)
{
struct symbol* symbol = &idf->symbol;
if (cb(symbol, user))
return &symbol;
idf = idf->id_next;
}
}
return NULL;
}

View file

@ -281,6 +281,12 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock
break;
}
case op_lae:
push(
new_bbir(leftbb)
);
break;
default:
fatal("treebuilder: unknown bvalue instruction '%s'",
em_mnem[opcode - sp_fmnem]);
@ -312,6 +318,27 @@ static void simple_alu2(int opcode, int size, int irop)
);
}
static struct ir* extract_block_refs(struct basicblock* bb)
{
struct ir* outir = NULL;
int i;
for (i=0; i<bb->insns_count; i++)
{
struct insn* insn = bb->insns[i];
assert(insn->opcode == op_bra);
assert(insn->paramtype == PARAM_BVALUE);
outir = new_ir2(
IR_PAIR, 0,
new_bbir(insn->u.bvalue.left),
outir
);
}
return outir;
}
static void insn_ivalue(int opcode, arith value)
{
switch (opcode)
@ -540,17 +567,13 @@ static void insn_ivalue(int opcode, arith value)
fatal("csa/csb are only supported if they refer "
"directly to a descriptor block");
/* Turn the label reference into a block. */
descriptor->opcode = IR_BLOCK;
descriptor->u.bvalue = bb_get(descriptor->u.lvalue);
push(descriptor);
materialise_stack();
appendir(
new_ir1(
new_ir2(
IR_JUMP, 0,
new_labelir(helper)
new_labelir(helper),
extract_block_refs(bb_get(descriptor->u.lvalue))
)
);
break;
@ -675,6 +698,7 @@ void tb_procedure(struct procedure* current_proc)
for (i=0; i<current_proc->blocks_count; i++)
generate_tree(current_proc->blocks[i]);
}
/* vim: set sw=4 ts=4 expandtab : */