with no prologue or epilogue yet).
else if (pending->section != desired_section)
fatal("label '%s' can't change sections", pending->name);
- printf("\n.sect %s\n", section_to_str(pending->section));
- printf("%s:\n", pending->name);
+ fprintf(outputfile, "\n.sect %s\n", section_to_str(pending->section));
+ fprintf(outputfile, "%s:\n", pending->name);
pending = NULL;
}
}
{
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
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)
if (start < p)
{
- printf("\t.ascii \"");
+ fprintf(outputfile, "\t.ascii \"");
while (start < p)
{
- printf("%c", *start);
+ fprintf(outputfile, "%c", *start);
start++;
}
- printf("\"\n");
+ fprintf(outputfile, "\"\n");
}
while ((p < end) && !isprint(*p))
{
bool first = true;
- printf("\t.data1 ");
+ fprintf(outputfile, "\t.data1 ");
while (start < p)
{
if (!first)
- printf(", ");
- printf("0x%02x", *start);
+ fprintf(outputfile, ", ");
+ fprintf(outputfile, "0x%02x", *start);
start++;
first = false;
}
- printf("\n");
+ fprintf(outputfile, "\n");
}
}
}
void data_offset(const char* label, arith offset, bool is_ro)
{
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)
fatal("non-zero-initialised bss not supported");
emit_header(SECTION_BSS);
- printf("\t.space %lld\n", size);
+ fprintf(outputfile, "\t.space %lld\n", size);
}
/* vim: set sw=4 ts=4 expandtab : */
static int hop_count = 1;
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;
tracef(k, " ");
}
-void hop_print(char k, struct hop* hop)
+static char* appendf(const char* fmt, ...)
{
- int i;
- bool soi = false;
+ int n;
+ char* p;
+ va_list ap;
+
+ 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;
+}
- print_header(k, hop);
+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++)
{
struct insel* insel = hop->insels.item[i];
- if (soi)
- {
- print_header(k, hop);
- soi = false;
- }
-
switch (insel->type)
{
case INSEL_EOI:
- tracef(k, "\n");
- soi = true;
+ appendf("\n");
break;
case INSEL_HREG:
{
struct hreg* hreg = insel->u.hreg;
- tracef(k, "%s", hreg->name);
+ appendf("%s", hreg->name);
break;
}
if (!hreg)
hreg = pmap_findright(&hop->regsout, vreg);
if (hreg)
- tracef(k, "%s", hreg->name);
+ appendf("%s", hreg->name);
else
- tracef(k, "%%%d", vreg->id);
+ appendf("%%%d", vreg->id);
break;
}
case INSEL_STRING:
- tracef(k, "%s", insel->u.string);
+ appendf("%s", insel->u.string);
break;
case INSEL_VALUE:
switch (ir->opcode)
{
case IR_BLOCK:
- tracef(k, "%s", ir->u.bvalue->name);
+ appendf("%s", ir->u.bvalue->name);
break;
case IR_LABEL:
- tracef(k, "%s", ir->u.lvalue);
+ appendf("%s", ir->u.lvalue);
break;
case IR_LOCAL:
case IR_CONST:
- tracef(k, "%d", ir->u.ivalue);
+ appendf("%d", ir->u.ivalue);
break;
}
break;
}
}
- if (!soi)
- tracef(k, "\n", k);
+ return buffer;
+}
+
+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 : */
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
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);
#endif
static const char* tracechars = NULL;
+FILE* outputfile = NULL;
FILE* dominance_dot_file = NULL;
FILE* cfg_dot_file = NULL;
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];
tracechars = optarg;
break;
+ case 'o':
+ if (outputfilename)
+ fatal("already specified an output file");
+ outputfilename = optarg;
+ break;
+
case 1:
- if (inputfile)
+ if (inputfilename)
fatal("unexpected argument '%s'", optarg);
- inputfile = optarg;
+ inputfilename = optarg;
}
}
symbol_init();
- if (!EM_open((char*) inputfile))
- fatal("couldn't open '%s': %s",
- inputfile ? inputfile : "<stdin>", EM_error);
+ if (!EM_open((char*) inputfilename))
+ fatal("couldn't open input '%s': %s",
+ 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
* generates IR trees. */
symbol_walk(find_procedures_cb, NULL);
+ if (outputfilename)
+ fclose(outputfile);
EM_close();
+
if (cfg_dot_file)
{
fprintf(cfg_dot_file, "}\n");
fprintf(dominance_dot_file, "}\n");
fclose(dominance_dot_file);
}
+
return 0;
}
extern void pass_remove_dead_blocks(struct procedure* proc);
extern void pass_split_critical_edges(struct procedure* proc);
+extern FILE* outputfile;
extern FILE* dominance_dot_file;
extern FILE* cfg_dot_file;
}
}
+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)
{
int i;
pass_register_allocator();
print_hops('9', proc);
+ emit_procedure(proc);
+
if (cfg_dot_file)
write_cfg_graph(proc->name);
if (dominance_dot_file)