2016-09-25 21:29:59 +00:00
|
|
|
#include "mcg.h"
|
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
static int hop_count = 1;
|
2016-09-26 22:19:45 +00:00
|
|
|
static struct hop* current_hop;
|
2016-10-10 22:12:11 +00:00
|
|
|
static char* buffer = NULL;
|
|
|
|
static int bufferlen = 0;
|
|
|
|
static int buffersize = 0;
|
2016-09-26 22:19:45 +00:00
|
|
|
|
|
|
|
static const struct burm_emitter_data emitter_data;
|
|
|
|
|
2016-10-07 22:21:23 +00:00
|
|
|
struct hop* new_hop(struct basicblock* bb, struct ir* ir)
|
2016-09-25 21:29:59 +00:00
|
|
|
{
|
|
|
|
struct hop* hop = calloc(1, sizeof *hop);
|
2016-09-27 21:38:47 +00:00
|
|
|
hop->id = hop_count++;
|
2016-10-07 22:21:23 +00:00
|
|
|
hop->bb = bb;
|
2016-09-25 21:29:59 +00:00
|
|
|
hop->ir = ir;
|
2016-09-26 22:19:45 +00:00
|
|
|
return hop;
|
2016-09-25 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
static struct insel* new_insel(enum insel_type type)
|
2016-09-25 21:29:59 +00:00
|
|
|
{
|
2016-09-27 21:38:47 +00:00
|
|
|
struct insel* insel = calloc(1, sizeof(*insel));
|
|
|
|
insel->type = type;
|
|
|
|
return insel;
|
2016-09-26 22:19:45 +00:00
|
|
|
}
|
2016-09-25 21:29:59 +00:00
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
void hop_add_string_insel(struct hop* hop, const char* string)
|
2016-09-26 22:19:45 +00:00
|
|
|
{
|
2016-09-27 21:38:47 +00:00
|
|
|
struct insel* insel = new_insel(INSEL_STRING);
|
|
|
|
insel->u.string = string;
|
|
|
|
array_append(&hop->insels, insel);
|
2016-09-26 22:19:45 +00:00
|
|
|
}
|
2016-09-25 21:29:59 +00:00
|
|
|
|
2016-10-10 21:19:46 +00:00
|
|
|
void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg)
|
|
|
|
{
|
|
|
|
struct insel* insel = new_insel(INSEL_HREG);
|
|
|
|
insel->u.hreg = hreg;
|
|
|
|
array_append(&hop->insels, insel);
|
|
|
|
}
|
|
|
|
|
2016-10-02 21:25:54 +00:00
|
|
|
void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg)
|
2016-09-26 22:19:45 +00:00
|
|
|
{
|
2016-10-02 21:25:54 +00:00
|
|
|
struct insel* insel = new_insel(INSEL_VREG);
|
|
|
|
insel->u.vreg = vreg;
|
2016-09-27 21:38:47 +00:00
|
|
|
array_append(&hop->insels, insel);
|
2016-09-25 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
void hop_add_value_insel(struct hop* hop, struct ir* ir)
|
2016-09-25 21:29:59 +00:00
|
|
|
{
|
2016-09-27 21:38:47 +00:00
|
|
|
struct insel* insel = new_insel(INSEL_VALUE);
|
|
|
|
insel->u.value = ir;
|
|
|
|
array_append(&hop->insels, insel);
|
2016-09-25 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
2016-10-15 20:53:56 +00:00
|
|
|
void hop_add_st_offset_insel(struct hop* hop, struct hreg* hreg)
|
|
|
|
{
|
|
|
|
struct insel* insel = new_insel(INSEL_ST_OFFSET);
|
|
|
|
insel->u.hreg = hreg;
|
|
|
|
array_append(&hop->insels, insel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hop_add_ab_offset_insel(struct hop* hop, int offset)
|
|
|
|
{
|
|
|
|
struct insel* insel = new_insel(INSEL_AB_OFFSET);
|
|
|
|
insel->u.offset = offset;
|
|
|
|
array_append(&hop->insels, insel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hop_add_lb_offset_insel(struct hop* hop, int offset)
|
|
|
|
{
|
|
|
|
struct insel* insel = new_insel(INSEL_LB_OFFSET);
|
|
|
|
insel->u.offset = offset;
|
|
|
|
array_append(&hop->insels, insel);
|
|
|
|
}
|
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
void hop_add_eoi_insel(struct hop* hop)
|
2016-09-25 21:29:59 +00:00
|
|
|
{
|
2016-09-27 21:38:47 +00:00
|
|
|
struct insel* insel = new_insel(INSEL_EOI);
|
|
|
|
array_append(&hop->insels, insel);
|
2016-09-25 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
2016-10-15 16:38:46 +00:00
|
|
|
void hop_add_insel(struct hop* hop, const char* fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
|
|
|
while (*fmt)
|
|
|
|
{
|
|
|
|
if (*fmt == '%')
|
|
|
|
{
|
|
|
|
fmt += 2;
|
|
|
|
switch (fmt[-1])
|
|
|
|
{
|
|
|
|
case 'd':
|
|
|
|
hop_add_string_insel(hop, aprintf("%d", va_arg(ap, int)));
|
|
|
|
break;
|
|
|
|
|
2016-10-15 20:53:56 +00:00
|
|
|
case 'S':
|
|
|
|
hop_add_st_offset_insel(hop, va_arg(ap, struct hreg*));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'A':
|
|
|
|
hop_add_ab_offset_insel(hop, va_arg(ap, int));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'L':
|
|
|
|
hop_add_lb_offset_insel(hop, va_arg(ap, int));
|
|
|
|
break;
|
|
|
|
|
2016-10-15 16:38:46 +00:00
|
|
|
case 'H':
|
|
|
|
hop_add_hreg_insel(hop, va_arg(ap, struct hreg*));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'V':
|
|
|
|
hop_add_vreg_insel(hop, va_arg(ap, struct vreg*));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const char* end = strchr(fmt, '%');
|
|
|
|
const char* s;
|
|
|
|
if (end)
|
|
|
|
{
|
|
|
|
int len = end - fmt;
|
|
|
|
s = strndup(fmt, len);
|
|
|
|
fmt = end;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s = fmt;
|
|
|
|
fmt += strlen(fmt);
|
|
|
|
}
|
|
|
|
|
|
|
|
hop_add_string_insel(hop, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hop_add_eoi_insel(hop);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2016-10-10 21:19:46 +00:00
|
|
|
static void print_header(char k, struct hop* hop)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
tracef(k, "%c: %d", k, hop->id);
|
|
|
|
if (hop->ir)
|
|
|
|
tracef(k, " from $%d", hop->ir->id);
|
|
|
|
tracef(k, ":");
|
|
|
|
|
|
|
|
for (i=0; i<hop->ins.count; i++)
|
|
|
|
tracef(k, " r%%%d", hop->ins.item[i]->id);
|
|
|
|
for (i=0; i<hop->throughs.count; i++)
|
|
|
|
tracef(k, " =%%%d", hop->throughs.item[i]->id);
|
|
|
|
for (i=0; i<hop->outs.count; i++)
|
|
|
|
tracef(k, " w%%%d", hop->outs.item[i]->id);
|
|
|
|
tracef(k, " ");
|
|
|
|
}
|
|
|
|
|
2016-10-10 22:12:11 +00:00
|
|
|
static char* appendf(const char* fmt, ...)
|
2016-09-26 22:19:45 +00:00
|
|
|
{
|
2016-10-10 22:12:11 +00:00
|
|
|
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;
|
|
|
|
}
|
2016-10-10 21:19:46 +00:00
|
|
|
|
2016-10-10 22:12:11 +00:00
|
|
|
char* hop_render(struct hop* hop)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
appendf(""); /* ensure the buffer has been allocated */
|
|
|
|
bufferlen = 0;
|
|
|
|
buffer[0] = '\0';
|
2016-09-26 22:19:45 +00:00
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
for (i=0; i<hop->insels.count; i++)
|
2016-09-26 22:19:45 +00:00
|
|
|
{
|
2016-09-27 21:38:47 +00:00
|
|
|
struct insel* insel = hop->insels.item[i];
|
2016-09-26 22:19:45 +00:00
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
switch (insel->type)
|
|
|
|
{
|
|
|
|
case INSEL_EOI:
|
2016-10-10 22:12:11 +00:00
|
|
|
appendf("\n");
|
2016-09-27 21:38:47 +00:00
|
|
|
break;
|
|
|
|
|
2016-10-10 21:19:46 +00:00
|
|
|
case INSEL_HREG:
|
|
|
|
{
|
|
|
|
struct hreg* hreg = insel->u.hreg;
|
2016-10-15 09:42:47 +00:00
|
|
|
appendf("%s", hreg->realname);
|
2016-10-10 21:19:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-10-02 21:25:54 +00:00
|
|
|
case INSEL_VREG:
|
2016-10-08 21:32:54 +00:00
|
|
|
{
|
|
|
|
struct vreg* vreg = insel->u.vreg;
|
|
|
|
struct hreg* hreg = pmap_findright(&hop->regsin, vreg);
|
|
|
|
if (!hreg)
|
|
|
|
hreg = pmap_findright(&hop->regsout, vreg);
|
|
|
|
if (hreg)
|
2016-10-15 09:42:47 +00:00
|
|
|
appendf("%s", hreg->realname);
|
2016-10-08 21:32:54 +00:00
|
|
|
else
|
2016-10-10 22:12:11 +00:00
|
|
|
appendf("%%%d", vreg->id);
|
2016-09-27 21:38:47 +00:00
|
|
|
break;
|
2016-10-08 21:32:54 +00:00
|
|
|
}
|
2016-09-27 21:38:47 +00:00
|
|
|
|
|
|
|
case INSEL_STRING:
|
2016-10-10 22:12:11 +00:00
|
|
|
appendf("%s", insel->u.string);
|
2016-09-27 21:38:47 +00:00
|
|
|
break;
|
|
|
|
|
2016-10-15 20:53:56 +00:00
|
|
|
case INSEL_ST_OFFSET:
|
|
|
|
appendf("(st+%d)", insel->u.hreg->offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case INSEL_AB_OFFSET:
|
|
|
|
appendf("(ab+%d)", insel->u.offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case INSEL_LB_OFFSET:
|
|
|
|
appendf("(lb+%d)", insel->u.offset);
|
|
|
|
break;
|
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
case INSEL_VALUE:
|
|
|
|
{
|
|
|
|
struct ir* ir = insel->u.value;
|
|
|
|
switch (ir->opcode)
|
|
|
|
{
|
|
|
|
case IR_BLOCK:
|
2016-10-10 22:12:11 +00:00
|
|
|
appendf("%s", ir->u.bvalue->name);
|
2016-09-27 21:38:47 +00:00
|
|
|
break;
|
|
|
|
|
2016-10-01 11:56:52 +00:00
|
|
|
case IR_LABEL:
|
2016-10-10 22:12:11 +00:00
|
|
|
appendf("%s", ir->u.lvalue);
|
2016-10-01 11:56:52 +00:00
|
|
|
break;
|
|
|
|
|
2016-09-27 21:38:47 +00:00
|
|
|
case IR_LOCAL:
|
|
|
|
case IR_CONST:
|
2016-10-10 22:12:11 +00:00
|
|
|
appendf("%d", ir->u.ivalue);
|
2016-09-27 21:38:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-09-26 22:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-27 21:38:47 +00:00
|
|
|
|
2016-10-10 22:12:11 +00:00
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hop_print(char k, struct hop* hop)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
bool soi = false;
|
|
|
|
char* p;
|
|
|
|
|
|
|
|
hop_render(hop);
|
|
|
|
|
|
|
|
p = strtok(buffer, "\n");
|
2016-10-14 23:15:08 +00:00
|
|
|
print_header(k, hop);
|
2016-10-10 22:12:11 +00:00
|
|
|
while (p)
|
|
|
|
{
|
2016-10-14 23:15:08 +00:00
|
|
|
tracef(k, "%s", p);
|
2016-10-10 22:12:11 +00:00
|
|
|
p = strtok(NULL, "\n");
|
2016-10-14 23:15:08 +00:00
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
tracef(k, "\n");
|
|
|
|
print_header(k, hop);
|
|
|
|
}
|
2016-10-10 22:12:11 +00:00
|
|
|
}
|
2016-10-14 23:15:08 +00:00
|
|
|
tracef(k, "\n");
|
2016-09-25 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
2016-10-05 19:07:29 +00:00
|
|
|
/* vim: set sw=4 ts=4 expandtab : */
|
|
|
|
|