Refactored the way hops are rendered; add support for emitting code (although
with no prologue or epilogue yet).
This commit is contained in:
parent
92bd1ac5f4
commit
e93c58dc8d
6 changed files with 122 additions and 40 deletions
|
@ -36,8 +36,8 @@ static void emit_header(int desired_section)
|
||||||
else if (pending->section != desired_section)
|
else if (pending->section != desired_section)
|
||||||
fatal("label '%s' can't change sections", pending->name);
|
fatal("label '%s' can't change sections", pending->name);
|
||||||
|
|
||||||
printf("\n.sect %s\n", section_to_str(pending->section));
|
fprintf(outputfile, "\n.sect %s\n", section_to_str(pending->section));
|
||||||
printf("%s:\n", pending->name);
|
fprintf(outputfile, "%s:\n", pending->name);
|
||||||
pending = NULL;
|
pending = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ void data_int(arith data, size_t size, bool is_ro)
|
||||||
{
|
{
|
||||||
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
|
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
|
||||||
assert((size == 1) || (size == 2) || (size == 4) || (size == 8));
|
assert((size == 1) || (size == 2) || (size == 4) || (size == 8));
|
||||||
printf("\t.data%d 0x%0*lld\n", size, size*2, data);
|
fprintf(outputfile, "\t.data%d 0x%0*lld\n", size, size*2, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void data_block(const uint8_t* data, size_t size, bool is_ro)
|
void data_block(const uint8_t* data, size_t size, bool is_ro)
|
||||||
|
@ -65,13 +65,13 @@ void data_block(const uint8_t* data, size_t size, bool is_ro)
|
||||||
|
|
||||||
if (start < p)
|
if (start < p)
|
||||||
{
|
{
|
||||||
printf("\t.ascii \"");
|
fprintf(outputfile, "\t.ascii \"");
|
||||||
while (start < p)
|
while (start < p)
|
||||||
{
|
{
|
||||||
printf("%c", *start);
|
fprintf(outputfile, "%c", *start);
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
printf("\"\n");
|
fprintf(outputfile, "\"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((p < end) && !isprint(*p))
|
while ((p < end) && !isprint(*p))
|
||||||
|
@ -81,16 +81,16 @@ void data_block(const uint8_t* data, size_t size, bool is_ro)
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
printf("\t.data1 ");
|
fprintf(outputfile, "\t.data1 ");
|
||||||
while (start < p)
|
while (start < p)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (!first)
|
||||||
printf(", ");
|
fprintf(outputfile, ", ");
|
||||||
printf("0x%02x", *start);
|
fprintf(outputfile, "0x%02x", *start);
|
||||||
start++;
|
start++;
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
printf("\n");
|
fprintf(outputfile, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ void data_block(const uint8_t* data, size_t size, bool is_ro)
|
||||||
void data_offset(const char* label, arith offset, bool is_ro)
|
void data_offset(const char* label, arith offset, bool is_ro)
|
||||||
{
|
{
|
||||||
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
|
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
|
||||||
printf("\t.data%d %s+%lld\n", EM_pointersize, label, offset);
|
fprintf(outputfile, "\t.data%d %s+%lld\n", EM_pointersize, label, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void data_bss(arith size, int init)
|
void data_bss(arith size, int init)
|
||||||
|
@ -107,7 +107,7 @@ void data_bss(arith size, int init)
|
||||||
fatal("non-zero-initialised bss not supported");
|
fatal("non-zero-initialised bss not supported");
|
||||||
|
|
||||||
emit_header(SECTION_BSS);
|
emit_header(SECTION_BSS);
|
||||||
printf("\t.space %lld\n", size);
|
fprintf(outputfile, "\t.space %lld\n", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
static int hop_count = 1;
|
static int hop_count = 1;
|
||||||
static struct hop* current_hop;
|
static struct hop* current_hop;
|
||||||
|
static char* buffer = NULL;
|
||||||
|
static int bufferlen = 0;
|
||||||
|
static int buffersize = 0;
|
||||||
|
|
||||||
static const struct burm_emitter_data emitter_data;
|
static const struct burm_emitter_data emitter_data;
|
||||||
|
|
||||||
|
@ -73,35 +76,54 @@ static void print_header(char k, struct hop* hop)
|
||||||
tracef(k, " ");
|
tracef(k, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void hop_print(char k, struct hop* hop)
|
static char* appendf(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
int i;
|
int n;
|
||||||
bool soi = false;
|
char* p;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
print_header(k, hop);
|
va_start(ap, fmt);
|
||||||
|
n = bufferlen + vsnprintf(NULL, 0, fmt, ap) + 1;
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (n > buffersize)
|
||||||
|
{
|
||||||
|
buffersize *= 2;
|
||||||
|
if (buffersize < n)
|
||||||
|
buffersize = n*2;
|
||||||
|
buffer = realloc(buffer, buffersize);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsprintf(buffer+bufferlen, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
bufferlen = n - 1; /* remember the \0 at the end */
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* hop_render(struct hop* hop)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
appendf(""); /* ensure the buffer has been allocated */
|
||||||
|
bufferlen = 0;
|
||||||
|
buffer[0] = '\0';
|
||||||
|
|
||||||
i = 0;
|
|
||||||
for (i=0; i<hop->insels.count; i++)
|
for (i=0; i<hop->insels.count; i++)
|
||||||
{
|
{
|
||||||
struct insel* insel = hop->insels.item[i];
|
struct insel* insel = hop->insels.item[i];
|
||||||
|
|
||||||
if (soi)
|
|
||||||
{
|
|
||||||
print_header(k, hop);
|
|
||||||
soi = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (insel->type)
|
switch (insel->type)
|
||||||
{
|
{
|
||||||
case INSEL_EOI:
|
case INSEL_EOI:
|
||||||
tracef(k, "\n");
|
appendf("\n");
|
||||||
soi = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INSEL_HREG:
|
case INSEL_HREG:
|
||||||
{
|
{
|
||||||
struct hreg* hreg = insel->u.hreg;
|
struct hreg* hreg = insel->u.hreg;
|
||||||
tracef(k, "%s", hreg->name);
|
appendf("%s", hreg->name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,14 +134,14 @@ void hop_print(char k, struct hop* hop)
|
||||||
if (!hreg)
|
if (!hreg)
|
||||||
hreg = pmap_findright(&hop->regsout, vreg);
|
hreg = pmap_findright(&hop->regsout, vreg);
|
||||||
if (hreg)
|
if (hreg)
|
||||||
tracef(k, "%s", hreg->name);
|
appendf("%s", hreg->name);
|
||||||
else
|
else
|
||||||
tracef(k, "%%%d", vreg->id);
|
appendf("%%%d", vreg->id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case INSEL_STRING:
|
case INSEL_STRING:
|
||||||
tracef(k, "%s", insel->u.string);
|
appendf("%s", insel->u.string);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INSEL_VALUE:
|
case INSEL_VALUE:
|
||||||
|
@ -128,16 +150,16 @@ void hop_print(char k, struct hop* hop)
|
||||||
switch (ir->opcode)
|
switch (ir->opcode)
|
||||||
{
|
{
|
||||||
case IR_BLOCK:
|
case IR_BLOCK:
|
||||||
tracef(k, "%s", ir->u.bvalue->name);
|
appendf("%s", ir->u.bvalue->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IR_LABEL:
|
case IR_LABEL:
|
||||||
tracef(k, "%s", ir->u.lvalue);
|
appendf("%s", ir->u.lvalue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IR_LOCAL:
|
case IR_LOCAL:
|
||||||
case IR_CONST:
|
case IR_CONST:
|
||||||
tracef(k, "%d", ir->u.ivalue);
|
appendf("%d", ir->u.ivalue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -145,8 +167,24 @@ void hop_print(char k, struct hop* hop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!soi)
|
return buffer;
|
||||||
tracef(k, "\n", k);
|
}
|
||||||
|
|
||||||
|
void hop_print(char k, struct hop* hop)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool soi = false;
|
||||||
|
char* p;
|
||||||
|
|
||||||
|
hop_render(hop);
|
||||||
|
|
||||||
|
p = strtok(buffer, "\n");
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
print_header(k, hop);
|
||||||
|
tracef(k, "%s\n", p);
|
||||||
|
p = strtok(NULL, "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
|
@ -53,6 +53,7 @@ extern void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg);
|
||||||
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
|
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
|
||||||
extern void hop_add_eoi_insel(struct hop* hop);
|
extern void hop_add_eoi_insel(struct hop* hop);
|
||||||
|
|
||||||
|
extern char* hop_render(struct hop* hop);
|
||||||
extern void hop_print(char k, struct hop* hop);
|
extern void hop_print(char k, struct hop* hop);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
static const char* tracechars = NULL;
|
static const char* tracechars = NULL;
|
||||||
|
|
||||||
|
FILE* outputfile = NULL;
|
||||||
FILE* dominance_dot_file = NULL;
|
FILE* dominance_dot_file = NULL;
|
||||||
FILE* cfg_dot_file = NULL;
|
FILE* cfg_dot_file = NULL;
|
||||||
|
|
||||||
|
@ -36,7 +37,9 @@ static bool find_procedures_cb(struct symbol* symbol, void* user)
|
||||||
|
|
||||||
int main(int argc, char* const argv[])
|
int main(int argc, char* const argv[])
|
||||||
{
|
{
|
||||||
const char* inputfile = NULL;
|
const char* inputfilename = NULL;
|
||||||
|
const char* outputfilename = NULL;
|
||||||
|
FILE* output;
|
||||||
|
|
||||||
program_name = argv[0];
|
program_name = argv[0];
|
||||||
|
|
||||||
|
@ -69,19 +72,35 @@ int main(int argc, char* const argv[])
|
||||||
tracechars = optarg;
|
tracechars = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
if (outputfilename)
|
||||||
|
fatal("already specified an output file");
|
||||||
|
outputfilename = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
if (inputfile)
|
if (inputfilename)
|
||||||
fatal("unexpected argument '%s'", optarg);
|
fatal("unexpected argument '%s'", optarg);
|
||||||
inputfile = optarg;
|
inputfilename = optarg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol_init();
|
symbol_init();
|
||||||
|
|
||||||
if (!EM_open((char*) inputfile))
|
if (!EM_open((char*) inputfilename))
|
||||||
fatal("couldn't open '%s': %s",
|
fatal("couldn't open input '%s': %s",
|
||||||
inputfile ? inputfile : "<stdin>", EM_error);
|
inputfilename ? inputfilename : "<stdin>", EM_error);
|
||||||
|
|
||||||
|
if (outputfilename)
|
||||||
|
{
|
||||||
|
outputfile = fopen(outputfilename, "w");
|
||||||
|
if (!outputfile)
|
||||||
|
fatal("couldn't open output '%s': %s",
|
||||||
|
outputfilename, strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
outputfile = stdout;
|
||||||
|
|
||||||
/* Reads in the EM, outputs the data sections, parses any code and
|
/* Reads in the EM, outputs the data sections, parses any code and
|
||||||
* generates IR trees. */
|
* generates IR trees. */
|
||||||
|
|
||||||
|
@ -93,7 +112,10 @@ int main(int argc, char* const argv[])
|
||||||
|
|
||||||
symbol_walk(find_procedures_cb, NULL);
|
symbol_walk(find_procedures_cb, NULL);
|
||||||
|
|
||||||
|
if (outputfilename)
|
||||||
|
fclose(outputfile);
|
||||||
EM_close();
|
EM_close();
|
||||||
|
|
||||||
if (cfg_dot_file)
|
if (cfg_dot_file)
|
||||||
{
|
{
|
||||||
fprintf(cfg_dot_file, "}\n");
|
fprintf(cfg_dot_file, "}\n");
|
||||||
|
@ -104,6 +126,7 @@ int main(int argc, char* const argv[])
|
||||||
fprintf(dominance_dot_file, "}\n");
|
fprintf(dominance_dot_file, "}\n");
|
||||||
fclose(dominance_dot_file);
|
fclose(dominance_dot_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ extern void pass_register_allocator(void);
|
||||||
extern void pass_remove_dead_blocks(struct procedure* proc);
|
extern void pass_remove_dead_blocks(struct procedure* proc);
|
||||||
extern void pass_split_critical_edges(struct procedure* proc);
|
extern void pass_split_critical_edges(struct procedure* proc);
|
||||||
|
|
||||||
|
extern FILE* outputfile;
|
||||||
extern FILE* dominance_dot_file;
|
extern FILE* dominance_dot_file;
|
||||||
extern FILE* cfg_dot_file;
|
extern FILE* cfg_dot_file;
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,23 @@ static void print_hops(char k, struct procedure* proc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emit_procedure(struct procedure* proc)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i=0; i<dominance.preorder.count; i++)
|
||||||
|
{
|
||||||
|
struct basicblock* bb = dominance.preorder.item[i];
|
||||||
|
|
||||||
|
fprintf(outputfile, "%s:\n", bb->name);
|
||||||
|
for (j=0; j<bb->hops.count; j++)
|
||||||
|
{
|
||||||
|
struct hop* hop = bb->hops.item[j];
|
||||||
|
fprintf(outputfile, "%s", hop_render(hop));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void write_cfg_graph(const char* name)
|
static void write_cfg_graph(const char* name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -174,6 +191,8 @@ void procedure_compile(struct procedure* proc)
|
||||||
pass_register_allocator();
|
pass_register_allocator();
|
||||||
print_hops('9', proc);
|
print_hops('9', proc);
|
||||||
|
|
||||||
|
emit_procedure(proc);
|
||||||
|
|
||||||
if (cfg_dot_file)
|
if (cfg_dot_file)
|
||||||
write_cfg_graph(proc->name);
|
write_cfg_graph(proc->name);
|
||||||
if (dominance_dot_file)
|
if (dominance_dot_file)
|
||||||
|
|
Loading…
Reference in a new issue