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.
{
case 'E': return false;
case '0': return false;
- case '1': return false;
+ case '1': return true;
case '2': return true;
default: return true;
}
}
}
+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();
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;
}
{
const char* name;
int section;
+ struct procedure* proc;
bool is_defined : 1;
bool is_exported : 1;
bool is_proc : 1;
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);
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
}
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);
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;
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);
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:
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))
{
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;
#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
}
}
+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;
+}
+
break;
}
+ case op_lae:
+ push(
+ new_bbir(leftbb)
+ );
+ break;
+
default:
fatal("treebuilder: unknown bvalue instruction '%s'",
em_mnem[opcode - sp_fmnem]);
);
}
+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)
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;
for (i=0; i<current_proc->blocks_count; i++)
generate_tree(current_proc->blocks[i]);
+
}
/* vim: set sw=4 ts=4 expandtab : */