Refactored the way hops are rendered; add support for emitting code (although

with no prologue or epilogue yet).
This commit is contained in:
David Given 2016-10-11 00:12:11 +02:00
parent 92bd1ac5f4
commit e93c58dc8d
6 changed files with 122 additions and 40 deletions

View file

@ -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 : */

View file

@ -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 : */

View file

@ -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

View file

@ -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;
} }

View file

@ -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;

View 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)