mirror of https://github.com/inolen/redream.git
convert to integer based labels in ir_read / ir_write
This commit is contained in:
parent
2364f9d764
commit
89541723f7
|
@ -119,24 +119,6 @@ struct ir_block *ir_split_block(struct ir *ir, struct ir_instr *before) {
|
|||
return new_block;
|
||||
}
|
||||
|
||||
void ir_set_block_label(struct ir *ir, struct ir_block *block,
|
||||
const char *format, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
int label_len = vsnprintf(0, 0, format, args);
|
||||
int label_size = label_len + 1;
|
||||
CHECK_LE(label_size, IR_MAX_LABEL);
|
||||
char *label = ir_calloc(ir, label_size);
|
||||
va_end(args);
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(label, label_size, format, args);
|
||||
va_end(args);
|
||||
|
||||
block->label = label;
|
||||
}
|
||||
|
||||
void ir_remove_block(struct ir *ir, struct ir_block *block) {
|
||||
/* remove all instructions */
|
||||
list_for_each_entry_safe(instr, &block->instrs, struct ir_instr, it) {
|
||||
|
@ -201,24 +183,6 @@ struct ir_instr *ir_append_instr(struct ir *ir, enum ir_op op,
|
|||
return instr;
|
||||
}
|
||||
|
||||
void ir_set_instr_label(struct ir *ir, struct ir_instr *instr,
|
||||
const char *format, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
int label_len = vsnprintf(0, 0, format, args);
|
||||
int label_size = label_len + 1;
|
||||
CHECK_LE(label_size, IR_MAX_LABEL);
|
||||
char *label = ir_calloc(ir, label_size);
|
||||
va_end(args);
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(label, label_size, format, args);
|
||||
va_end(args);
|
||||
|
||||
instr->label = label;
|
||||
}
|
||||
|
||||
void ir_remove_instr(struct ir *ir, struct ir_instr *instr) {
|
||||
/* remove arguments from the use lists of their values */
|
||||
for (int i = 0; i < IR_MAX_ARGS; i++) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "core/assert.h"
|
||||
#include "core/list.h"
|
||||
|
||||
#define IR_MAX_LABEL 128
|
||||
#define IR_MAX_ARGS 4
|
||||
#define NO_REGISTER -1
|
||||
|
||||
|
@ -99,8 +98,6 @@ struct ir_value {
|
|||
};
|
||||
|
||||
struct ir_instr {
|
||||
const char *label;
|
||||
|
||||
enum ir_op op;
|
||||
|
||||
/* values used by each argument. note, the argument / use is split into two
|
||||
|
@ -132,8 +129,6 @@ struct ir_edge {
|
|||
};
|
||||
|
||||
struct ir_block {
|
||||
const char *label;
|
||||
|
||||
struct list instrs;
|
||||
|
||||
/* edges between this block and others */
|
||||
|
@ -226,15 +221,11 @@ void ir_set_current_instr(struct ir *ir, struct ir_instr *instr);
|
|||
struct ir_block *ir_insert_block(struct ir *ir, struct ir_block *after);
|
||||
struct ir_block *ir_append_block(struct ir *ir);
|
||||
struct ir_block *ir_split_block(struct ir *ir, struct ir_instr *before);
|
||||
void ir_set_block_label(struct ir *ir, struct ir_block *block,
|
||||
const char *format, ...);
|
||||
void ir_remove_block(struct ir *ir, struct ir_block *block);
|
||||
void ir_add_edge(struct ir *ir, struct ir_block *src, struct ir_block *dst);
|
||||
|
||||
struct ir_instr *ir_append_instr(struct ir *ir, enum ir_op op,
|
||||
enum ir_type result_type);
|
||||
void ir_set_instr_label(struct ir *ir, struct ir_instr *instr,
|
||||
const char *format, ...);
|
||||
void ir_remove_instr(struct ir *ir, struct ir_instr *instr);
|
||||
|
||||
struct ir_value *ir_alloc_int(struct ir *ir, int64_t c, enum ir_type type);
|
||||
|
|
|
@ -16,7 +16,7 @@ struct ir_reference {
|
|||
struct ir_instr *instr;
|
||||
int arg;
|
||||
enum ir_type type;
|
||||
char name[IR_MAX_LABEL];
|
||||
int label;
|
||||
struct list_node it;
|
||||
};
|
||||
|
||||
|
@ -29,9 +29,14 @@ struct ir_lexeme {
|
|||
|
||||
struct ir_parser {
|
||||
FILE *input;
|
||||
struct ir *ir;
|
||||
|
||||
enum ir_token tok;
|
||||
struct ir_lexeme val;
|
||||
struct list refs;
|
||||
|
||||
int *labels;
|
||||
int next_label;
|
||||
};
|
||||
|
||||
static const char *typenames[] = {"", "i8", "i16", "i32", "i64",
|
||||
|
@ -154,40 +159,62 @@ static void ir_lex_next(struct ir_parser *p) {
|
|||
}
|
||||
|
||||
static void ir_destroy_parser(struct ir_parser *p) {
|
||||
free(p->labels);
|
||||
|
||||
list_for_each_entry_safe(ref, &p->refs, struct ir_reference, it) {
|
||||
free(ref);
|
||||
}
|
||||
}
|
||||
|
||||
static int ir_resolve_references(struct ir_parser *p, struct ir *ir) {
|
||||
static void ir_insert_block_label(struct ir_parser *p,
|
||||
const struct ir_block *block, int label) {
|
||||
p->labels[(uint8_t *)block - p->ir->buffer] = label;
|
||||
}
|
||||
|
||||
static void ir_insert_instr_label(struct ir_parser *p,
|
||||
const struct ir_instr *instr, int label) {
|
||||
p->labels[(uint8_t *)instr - p->ir->buffer] = label;
|
||||
}
|
||||
|
||||
static int ir_get_block_label(struct ir_parser *p,
|
||||
const struct ir_block *block) {
|
||||
return p->labels[(uint8_t *)block - p->ir->buffer];
|
||||
}
|
||||
|
||||
static int ir_get_instr_label(struct ir_parser *p,
|
||||
const struct ir_instr *instr) {
|
||||
return p->labels[(uint8_t *)instr - p->ir->buffer];
|
||||
}
|
||||
|
||||
static int ir_resolve_references(struct ir_parser *p) {
|
||||
list_for_each_entry(ref, &p->refs, struct ir_reference, it) {
|
||||
struct ir_value *value = NULL;
|
||||
|
||||
if (ref->type == VALUE_BLOCK) {
|
||||
struct ir_block *found = NULL;
|
||||
|
||||
list_for_each_entry(block, &ir->blocks, struct ir_block, it) {
|
||||
if (block->label && !strcmp(block->label, ref->name)) {
|
||||
list_for_each_entry(block, &p->ir->blocks, struct ir_block, it) {
|
||||
if (ir_get_block_label(p, block) == ref->label) {
|
||||
found = block;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LOG_INFO("Failed to resolve reference for %%%s", ref->name);
|
||||
LOG_INFO("failed to resolve reference for %%%d", ref->label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = ir_alloc_block_ref(ir, found);
|
||||
value = ir_alloc_block_ref(p->ir, found);
|
||||
} else {
|
||||
struct ir_instr *found = NULL;
|
||||
list_for_each_entry(block, &ir->blocks, struct ir_block, it) {
|
||||
list_for_each_entry(block, &p->ir->blocks, struct ir_block, it) {
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_entry(instr, &block->instrs, struct ir_instr, it) {
|
||||
if (instr->label && !strcmp(instr->label, ref->name)) {
|
||||
if (ir_get_instr_label(p, instr) == ref->label) {
|
||||
found = instr;
|
||||
break;
|
||||
}
|
||||
|
@ -195,33 +222,32 @@ static int ir_resolve_references(struct ir_parser *p, struct ir *ir) {
|
|||
}
|
||||
|
||||
if (!found) {
|
||||
LOG_INFO("Failed to resolve reference for %%%s", ref->name);
|
||||
LOG_INFO("failed to resolve reference for %%%d", ref->label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = found->result;
|
||||
}
|
||||
|
||||
ir_set_arg(ir, ref->instr, ref->arg, value);
|
||||
ir_set_arg(p->ir, ref->instr, ref->arg, value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ir_defer_reference(struct ir_parser *p, struct ir_instr *instr,
|
||||
int arg, enum ir_type type, const char *name) {
|
||||
int arg, enum ir_type type, int label) {
|
||||
struct ir_reference *ref = calloc(1, sizeof(struct ir_reference));
|
||||
ref->instr = instr;
|
||||
ref->arg = arg;
|
||||
ref->type = type;
|
||||
strncpy(ref->name, name, sizeof(ref->name));
|
||||
ref->label = label;
|
||||
list_add(&p->refs, &ref->it);
|
||||
}
|
||||
|
||||
static int ir_parse_type(struct ir_parser *p, struct ir *ir,
|
||||
enum ir_type *type) {
|
||||
static int ir_parse_type(struct ir_parser *p, enum ir_type *type) {
|
||||
if (p->tok != TOK_TYPE) {
|
||||
LOG_INFO("Unexpected token %d when parsing type", p->tok);
|
||||
LOG_INFO("unexpected token %d when parsing type", p->tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -233,9 +259,9 @@ static int ir_parse_type(struct ir_parser *p, struct ir *ir,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ir_parse_op(struct ir_parser *p, struct ir *ir, enum ir_op *op) {
|
||||
static int ir_parse_op(struct ir_parser *p, enum ir_op *op) {
|
||||
if (p->tok != TOK_OP) {
|
||||
LOG_INFO("Unexpected token %d when parsing op", p->tok);
|
||||
LOG_INFO("unexpected token %d when parsing op", p->tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -247,11 +273,11 @@ static int ir_parse_op(struct ir_parser *p, struct ir *ir, enum ir_op *op) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ir_parse_operator(struct ir_parser *p, struct ir *ir) {
|
||||
static int ir_parse_operator(struct ir_parser *p) {
|
||||
const char *op_str = p->val.s;
|
||||
|
||||
if (strcmp(op_str, "=")) {
|
||||
LOG_INFO("Unexpected operator '%s'", op_str);
|
||||
LOG_INFO("unexpected operator '%s'", op_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -263,28 +289,28 @@ static int ir_parse_operator(struct ir_parser *p, struct ir *ir) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ir_parse_label(struct ir_parser *p, struct ir *ir, char *label) {
|
||||
static int ir_parse_label(struct ir_parser *p, int *label) {
|
||||
if (p->tok != TOK_IDENTIFIER) {
|
||||
LOG_INFO("Unexpected token %d when parsing label", p->tok);
|
||||
LOG_INFO("unexpected token %d when parsing label", p->tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ident = p->val.s;
|
||||
if (ident[0] != '%') {
|
||||
LOG_INFO("Expected label '%s' to begin with %%", ident);
|
||||
LOG_INFO("expected label '%s' to begin with %%", ident);
|
||||
return 0;
|
||||
}
|
||||
strcpy(label, &ident[1]);
|
||||
|
||||
*label = strtol(&ident[1], NULL, 10);
|
||||
ir_lex_next(p);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ir_parse_arg(struct ir_parser *p, struct ir *ir,
|
||||
struct ir_instr *instr, int arg) {
|
||||
static int ir_parse_arg(struct ir_parser *p, struct ir_instr *instr, int arg) {
|
||||
/* parse value type */
|
||||
enum ir_type type;
|
||||
if (!ir_parse_type(p, ir, &type)) {
|
||||
if (!ir_parse_type(p, &type)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -293,53 +319,53 @@ static int ir_parse_arg(struct ir_parser *p, struct ir *ir,
|
|||
const char *ident = p->val.s;
|
||||
|
||||
if (ident[0] != '%') {
|
||||
LOG_INFO("Expected identifier to begin with %%");
|
||||
LOG_INFO("expected identifier to begin with %%");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* label reference, defer resolution until after all blocks / values have
|
||||
been parsed */
|
||||
const char *name = &ident[1];
|
||||
ir_defer_reference(p, instr, arg, type, name);
|
||||
int id = strtol(&ident[1], NULL, 10);
|
||||
ir_defer_reference(p, instr, arg, type, id);
|
||||
} else if (p->tok == TOK_INTEGER || p->tok == TOK_STRING) {
|
||||
struct ir_value *value = NULL;
|
||||
|
||||
switch (type) {
|
||||
case VALUE_I8: {
|
||||
uint8_t v = (uint8_t)p->val.i;
|
||||
value = ir_alloc_i8(ir, v);
|
||||
value = ir_alloc_i8(p->ir, v);
|
||||
} break;
|
||||
case VALUE_I16: {
|
||||
uint16_t v = (uint16_t)p->val.i;
|
||||
value = ir_alloc_i16(ir, v);
|
||||
value = ir_alloc_i16(p->ir, v);
|
||||
} break;
|
||||
case VALUE_I32: {
|
||||
uint32_t v = (uint32_t)p->val.i;
|
||||
value = ir_alloc_i32(ir, v);
|
||||
value = ir_alloc_i32(p->ir, v);
|
||||
} break;
|
||||
case VALUE_I64: {
|
||||
uint64_t v = (uint64_t)p->val.i;
|
||||
value = ir_alloc_i64(ir, v);
|
||||
value = ir_alloc_i64(p->ir, v);
|
||||
} break;
|
||||
case VALUE_F32: {
|
||||
uint32_t v = (uint32_t)p->val.i;
|
||||
value = ir_alloc_f32(ir, *(float *)&v);
|
||||
value = ir_alloc_f32(p->ir, *(float *)&v);
|
||||
} break;
|
||||
case VALUE_F64: {
|
||||
uint64_t v = (uint64_t)p->val.i;
|
||||
value = ir_alloc_f64(ir, *(double *)&v);
|
||||
value = ir_alloc_f64(p->ir, *(double *)&v);
|
||||
} break;
|
||||
case VALUE_STRING: {
|
||||
value = ir_alloc_str(ir, p->val.s);
|
||||
value = ir_alloc_str(p->ir, p->val.s);
|
||||
} break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected value type");
|
||||
LOG_FATAL("unexpected value type");
|
||||
break;
|
||||
}
|
||||
|
||||
ir_set_arg(ir, instr, arg, value);
|
||||
ir_set_arg(p->ir, instr, arg, value);
|
||||
} else {
|
||||
LOG_INFO("Unexpected token %d when parsing value: %s", p->tok, p->val.s);
|
||||
LOG_INFO("unexpected token %d when parsing value: %s", p->tok, p->val.s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -349,38 +375,38 @@ static int ir_parse_arg(struct ir_parser *p, struct ir *ir,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ir_parse_instr(struct ir_parser *p, struct ir *ir) {
|
||||
static int ir_parse_instr(struct ir_parser *p) {
|
||||
enum ir_type type = VALUE_V;
|
||||
char label[IR_MAX_LABEL] = {0};
|
||||
int label = 0;
|
||||
|
||||
/* parse result type and label */
|
||||
if (p->tok == TOK_TYPE) {
|
||||
if (!ir_parse_type(p, ir, &type)) {
|
||||
if (!ir_parse_type(p, &type)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ir_parse_label(p, ir, label)) {
|
||||
if (!ir_parse_label(p, &label)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ir_parse_operator(p, ir)) {
|
||||
if (!ir_parse_operator(p)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* parse op */
|
||||
enum ir_op op;
|
||||
if (!ir_parse_op(p, ir, &op)) {
|
||||
if (!ir_parse_op(p, &op)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create instruction */
|
||||
struct ir_instr *instr = ir_append_instr(ir, op, type);
|
||||
struct ir_instr *instr = ir_append_instr(p->ir, op, type);
|
||||
|
||||
/* parse arguments */
|
||||
if (p->tok == TOK_TYPE) {
|
||||
for (int i = 0; i < IR_MAX_ARGS; i++) {
|
||||
if (!ir_parse_arg(p, ir, instr, i)) {
|
||||
if (!ir_parse_arg(p, instr, i)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -393,33 +419,31 @@ static int ir_parse_instr(struct ir_parser *p, struct ir *ir) {
|
|||
}
|
||||
}
|
||||
|
||||
if (label[0]) {
|
||||
ir_set_instr_label(ir, instr, label);
|
||||
}
|
||||
ir_insert_instr_label(p, instr, p->next_label++);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ir_parse_block(struct ir_parser *p, struct ir *ir) {
|
||||
static int ir_parse_block(struct ir_parser *p) {
|
||||
if (p->tok != TOK_IDENTIFIER) {
|
||||
LOG_INFO("Unexpected token %d when parsing block", p->tok);
|
||||
LOG_INFO("unexpected token %d when parsing block", p->tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char label[IR_MAX_LABEL];
|
||||
if (!ir_parse_label(p, ir, label)) {
|
||||
int label;
|
||||
if (!ir_parse_label(p, &label)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (p->tok != TOK_OPERATOR || p->val.s[0] != ':') {
|
||||
LOG_INFO("Expected label to be followed by : operator");
|
||||
LOG_INFO("expected label to be followed by : operator");
|
||||
return 0;
|
||||
}
|
||||
ir_lex_next(p);
|
||||
|
||||
struct ir_block *block = ir_append_block(ir);
|
||||
ir_set_block_label(ir, block, label);
|
||||
ir_set_current_block(ir, block);
|
||||
struct ir_block *block = ir_append_block(p->ir);
|
||||
ir_insert_block_label(p, block, p->next_label++);
|
||||
ir_set_current_block(p->ir, block);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -427,6 +451,8 @@ static int ir_parse_block(struct ir_parser *p, struct ir *ir) {
|
|||
int ir_read(FILE *input, struct ir *ir) {
|
||||
struct ir_parser p = {0};
|
||||
p.input = input;
|
||||
p.ir = ir;
|
||||
p.labels = malloc(sizeof(int) * ir->capacity);
|
||||
|
||||
int res = 1;
|
||||
|
||||
|
@ -434,19 +460,19 @@ int ir_read(FILE *input, struct ir *ir) {
|
|||
ir_lex_next(&p);
|
||||
|
||||
if (p.tok == TOK_EOF) {
|
||||
if (!ir_resolve_references(&p, ir)) {
|
||||
if (!ir_resolve_references(&p)) {
|
||||
res = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (p.tok == TOK_IDENTIFIER) {
|
||||
if (!ir_parse_block(&p, ir)) {
|
||||
if (!ir_parse_block(&p)) {
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!ir_parse_instr(&p, ir)) {
|
||||
if (!ir_parse_instr(&p)) {
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,37 @@
|
|||
#include "core/string.h"
|
||||
#include "jit/ir/ir.h"
|
||||
|
||||
static void ir_write_type(enum ir_type type, FILE *output) {
|
||||
struct ir_writer {
|
||||
struct ir *ir;
|
||||
int *labels;
|
||||
};
|
||||
|
||||
static void ir_destroy_writer(struct ir_writer *w) {
|
||||
free(w->labels);
|
||||
}
|
||||
|
||||
static void ir_insert_block_label(struct ir_writer *w,
|
||||
const struct ir_block *block, int label) {
|
||||
w->labels[(uint8_t *)block - w->ir->buffer] = label;
|
||||
}
|
||||
|
||||
static void ir_insert_instr_label(struct ir_writer *w,
|
||||
const struct ir_instr *instr, int label) {
|
||||
w->labels[(uint8_t *)instr - w->ir->buffer] = label;
|
||||
}
|
||||
|
||||
static int ir_get_block_label(struct ir_writer *w,
|
||||
const struct ir_block *block) {
|
||||
return w->labels[(uint8_t *)block - w->ir->buffer];
|
||||
}
|
||||
|
||||
static int ir_get_instr_label(struct ir_writer *w,
|
||||
const struct ir_instr *instr) {
|
||||
return w->labels[(uint8_t *)instr - w->ir->buffer];
|
||||
}
|
||||
|
||||
static void ir_write_type(struct ir_writer *w, enum ir_type type,
|
||||
FILE *output) {
|
||||
switch (type) {
|
||||
case VALUE_I8:
|
||||
fprintf(output, "i8");
|
||||
|
@ -32,12 +62,12 @@ static void ir_write_type(enum ir_type type, FILE *output) {
|
|||
fprintf(output, "blk");
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected value type");
|
||||
LOG_FATAL("unexpected value type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_write_op(enum ir_op op, FILE *output) {
|
||||
static void ir_write_op(struct ir_writer *w, enum ir_op op, FILE *output) {
|
||||
const struct ir_opdef *def = &ir_opdefs[op];
|
||||
const char *name = def->name;
|
||||
|
||||
|
@ -47,8 +77,9 @@ static void ir_write_op(enum ir_op op, FILE *output) {
|
|||
}
|
||||
}
|
||||
|
||||
static void ir_write_value(const struct ir_value *value, FILE *output) {
|
||||
ir_write_type(value->type, output);
|
||||
static void ir_write_value(struct ir_writer *w, const struct ir_value *value,
|
||||
FILE *output) {
|
||||
ir_write_type(w, value->type, output);
|
||||
|
||||
fprintf(output, " ");
|
||||
|
||||
|
@ -79,26 +110,27 @@ static void ir_write_value(const struct ir_value *value, FILE *output) {
|
|||
fprintf(output, "'%s'", value->str);
|
||||
} break;
|
||||
case VALUE_BLOCK:
|
||||
fprintf(output, "%%%s", value->blk->label);
|
||||
fprintf(output, "%%%d", ir_get_block_label(w, value->blk));
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected value type");
|
||||
LOG_FATAL("unexpected value type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf(output, "%%%s", value->def->label);
|
||||
fprintf(output, "%%%d", ir_get_instr_label(w, value->def));
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_write_instr(const struct ir_instr *instr, FILE *output) {
|
||||
static void ir_write_instr(struct ir_writer *w, const struct ir_instr *instr,
|
||||
FILE *output) {
|
||||
/* print result value if it exists */
|
||||
if (instr->result) {
|
||||
ir_write_value(instr->result, output);
|
||||
ir_write_value(w, instr->result, output);
|
||||
fprintf(output, " = ");
|
||||
}
|
||||
|
||||
/* print the actual op */
|
||||
ir_write_op(instr->op, output);
|
||||
ir_write_op(w, instr->op, output);
|
||||
fprintf(output, " ");
|
||||
|
||||
/* print each argument */
|
||||
|
@ -116,7 +148,7 @@ static void ir_write_instr(const struct ir_instr *instr, FILE *output) {
|
|||
need_comma = 0;
|
||||
}
|
||||
|
||||
ir_write_value(arg, output);
|
||||
ir_write_value(w, arg, output);
|
||||
|
||||
need_comma = 1;
|
||||
}
|
||||
|
@ -129,36 +161,40 @@ static void ir_write_instr(const struct ir_instr *instr, FILE *output) {
|
|||
fprintf(output, "\n");
|
||||
}
|
||||
|
||||
static void ir_write_block(const struct ir_block *block, FILE *output) {
|
||||
fprintf(output, "%%%s:\n", block->label);
|
||||
static void ir_write_block(struct ir_writer *w, const struct ir_block *block,
|
||||
FILE *output) {
|
||||
fprintf(output, "%%%d:\n", ir_get_block_label(w, block));
|
||||
|
||||
list_for_each_entry(instr, &block->instrs, struct ir_instr, it) {
|
||||
ir_write_instr(instr, output);
|
||||
ir_write_instr(w, instr, output);
|
||||
}
|
||||
|
||||
fprintf(output, "\n");
|
||||
}
|
||||
|
||||
static void ir_assign_default_labels(struct ir *ir) {
|
||||
int id = 0;
|
||||
static void ir_assign_labels(struct ir_writer *w) {
|
||||
int label = 0;
|
||||
|
||||
list_for_each_entry(block, &ir->blocks, struct ir_block, it) {
|
||||
if (!block->label) {
|
||||
ir_set_block_label(ir, block, "%d", id++);
|
||||
}
|
||||
w->labels = malloc(sizeof(int) * w->ir->capacity);
|
||||
|
||||
list_for_each_entry(block, &w->ir->blocks, struct ir_block, it) {
|
||||
ir_insert_block_label(w, block, label++);
|
||||
|
||||
list_for_each_entry(instr, &block->instrs, struct ir_instr, it) {
|
||||
if (!instr->label) {
|
||||
ir_set_instr_label(ir, instr, "%d", id++);
|
||||
}
|
||||
ir_insert_instr_label(w, instr, label++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ir_write(struct ir *ir, FILE *output) {
|
||||
ir_assign_default_labels(ir);
|
||||
struct ir_writer w = {0};
|
||||
w.ir = ir;
|
||||
|
||||
ir_assign_labels(&w);
|
||||
|
||||
list_for_each_entry(block, &ir->blocks, struct ir_block, it) {
|
||||
ir_write_block(block, output);
|
||||
ir_write_block(&w, block, output);
|
||||
}
|
||||
|
||||
ir_destroy_writer(&w);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue