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:
parent
ed67d427c9
commit
bb9aa030a5
|
@ -39,7 +39,7 @@ bool tracing(char k)
|
||||||
{
|
{
|
||||||
case 'E': return false;
|
case 'E': return false;
|
||||||
case '0': return false;
|
case '0': return false;
|
||||||
case '1': return false;
|
case '1': return true;
|
||||||
case '2': return true;
|
case '2': return true;
|
||||||
default: 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[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
symbol_init();
|
symbol_init();
|
||||||
|
@ -64,8 +71,17 @@ int main(int argc, char* argv[])
|
||||||
if (!EM_open(argv[1]))
|
if (!EM_open(argv[1]))
|
||||||
fatal("Couldn't open input file: %s", EM_error);
|
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();
|
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();
|
EM_close();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct symbol
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
int section;
|
int section;
|
||||||
|
struct procedure* proc;
|
||||||
bool is_defined : 1;
|
bool is_defined : 1;
|
||||||
bool is_exported : 1;
|
bool is_exported : 1;
|
||||||
bool is_proc : 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 struct symbol* symbol_get(const char* name);
|
||||||
extern void symbol_declare(const char* name, bool is_exported, bool is_proc);
|
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_label(const char* name);
|
||||||
extern void data_int(arith data, size_t size, bool is_ro);
|
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);
|
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_remove_dead_blocks(struct procedure* proc);
|
||||||
extern void pass_eliminate_trivial_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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,9 @@ static void parse_pseu(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
case ps_pro: /* procedure start */
|
case ps_pro: /* procedure start */
|
||||||
|
{
|
||||||
|
struct symbol* symbol;
|
||||||
|
|
||||||
current_proc = calloc(sizeof(struct procedure), 1);
|
current_proc = calloc(sizeof(struct procedure), 1);
|
||||||
current_proc->name = strdup(insn.em_pnam);
|
current_proc->name = strdup(insn.em_pnam);
|
||||||
current_proc->root_bb = bb_get(current_proc->name);
|
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 = current_proc->root_bb;
|
||||||
code_bb->is_root = true;
|
code_bb->is_root = true;
|
||||||
APPEND(current_proc->blocks, code_bb);
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ps_end: /* procedure end */
|
case ps_end: /* procedure end */
|
||||||
tb_procedure(current_proc);
|
tb_procedure(current_proc);
|
||||||
compile(current_proc);
|
|
||||||
|
|
||||||
current_proc = NULL;
|
current_proc = NULL;
|
||||||
code_bb = NULL;
|
code_bb = NULL;
|
||||||
|
@ -336,6 +344,17 @@ static void parse_mes(void)
|
||||||
fatal("malformed MES");
|
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)
|
void parse_em(void)
|
||||||
{
|
{
|
||||||
EM_getinstr(&insn);
|
EM_getinstr(&insn);
|
||||||
|
@ -354,16 +373,11 @@ void parse_em(void)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EM_DEFDLB:
|
case EM_DEFDLB:
|
||||||
{
|
create_data_label(dlabel_to_str(insn.em_dlb));
|
||||||
const char* label = dlabel_to_str(insn.em_dlb);
|
|
||||||
data_label(label);
|
|
||||||
data_bb = bb_get(label);
|
|
||||||
data_bb->is_fake = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case EM_DEFDNAM:
|
case EM_DEFDNAM:
|
||||||
data_label(strdup(insn.em_dnam));
|
create_data_label(strdup(insn.em_dnam));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EM_STARTMES:
|
case EM_STARTMES:
|
||||||
|
|
|
@ -5,7 +5,8 @@ static bool rewrite_jumps_cb(struct ir* ir, void* user)
|
||||||
if (ir->opcode == IR_BLOCK)
|
if (ir->opcode == IR_BLOCK)
|
||||||
{
|
{
|
||||||
struct basicblock* bb = ir->u.bvalue;
|
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]->opcode == IR_JUMP)
|
||||||
&& (bb->irs[0]->left->opcode == IR_BLOCK))
|
&& (bb->irs[0]->left->opcode == IR_BLOCK))
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,14 +11,16 @@ static void print_blocks(char k, struct procedure* proc)
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
tracef(k, "%c:\n", k);
|
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++)
|
for (int j=0; j<bb->irs_count; j++)
|
||||||
ir_print(k, bb->irs[j]);
|
ir_print(k, bb->irs[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile(struct procedure* proc)
|
void procedure_compile(struct procedure* proc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
|
|
||||||
|
typedef int idf_walker_t(struct idf* idf, void* user);
|
||||||
|
|
||||||
static void init_idf();
|
static void init_idf();
|
||||||
static struct idf* str2idf(char* tg, int cp);
|
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_TYPE struct symbol
|
||||||
#define IDF_NAME 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,12 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case op_lae:
|
||||||
|
push(
|
||||||
|
new_bbir(leftbb)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatal("treebuilder: unknown bvalue instruction '%s'",
|
fatal("treebuilder: unknown bvalue instruction '%s'",
|
||||||
em_mnem[opcode - sp_fmnem]);
|
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)
|
static void insn_ivalue(int opcode, arith value)
|
||||||
{
|
{
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
|
@ -540,17 +567,13 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
fatal("csa/csb are only supported if they refer "
|
fatal("csa/csb are only supported if they refer "
|
||||||
"directly to a descriptor block");
|
"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);
|
push(descriptor);
|
||||||
materialise_stack();
|
materialise_stack();
|
||||||
appendir(
|
appendir(
|
||||||
new_ir1(
|
new_ir2(
|
||||||
IR_JUMP, 0,
|
IR_JUMP, 0,
|
||||||
new_labelir(helper)
|
new_labelir(helper),
|
||||||
|
extract_block_refs(bb_get(descriptor->u.lvalue))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -675,6 +698,7 @@ void tb_procedure(struct procedure* current_proc)
|
||||||
|
|
||||||
for (i=0; i<current_proc->blocks_count; i++)
|
for (i=0; i<current_proc->blocks_count; i++)
|
||||||
generate_tree(current_proc->blocks[i]);
|
generate_tree(current_proc->blocks[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
Loading…
Reference in a new issue