diff --git a/README.md b/README.md deleted file mode 100644 index ead72c5..0000000 --- a/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# VXCC (v3) -How is this different from VXCC v1 and v2? - -Int vxcc-opt, I started with the IR but it was too high level. -In v1, I started with macro expansion codegen but unsuccessfully because the structure was messed up. -In v2, I did the same thing in Kotin and got reasonably far, but not having an SSA IR was very limiting. -So here I started again but with an SSA and with the optimizations firsts. \ No newline at end of file diff --git a/common.h b/common.h index b5968be..eb0a4a3 100644 --- a/common.h +++ b/common.h @@ -7,24 +7,25 @@ typedef struct { size_t *ids; size_t len; -} OpPath; +} vx_OpPath; + +vx_OpPath vx_OpPath_copy_add(vx_OpPath path, size_t id); typedef struct { - OpPath path; + vx_OpPath path; const char *error; const char *additional; -} VerifyError; +} vx_Error; typedef struct { - VerifyError *items; + vx_Error *items; size_t len; -} VerifyErrors; +} vx_Errors; -void verifyerrors_free(VerifyErrors errors); -void verifyerrors_print(VerifyErrors errors, FILE *dest); -OpPath oppath_copy_add(OpPath path, size_t id); -void verifyerrors_add(VerifyErrors *errors, const VerifyError *error); -void verifyerrors_add_all_and_free(VerifyErrors *dest, VerifyErrors *src); +void vx_Errors_add(vx_Errors *errors, const vx_Error *error); +void vx_Errors_add_all_and_free(vx_Errors *dest, vx_Errors *src); +void vx_Errors_free(vx_Errors errors); +void vx_Errors_print(vx_Errors errors, FILE *dest); #endif //COMMON_H diff --git a/common/verify.c b/common/verify.c index a1b1d70..4ef8c90 100644 --- a/common/verify.c +++ b/common/verify.c @@ -3,37 +3,37 @@ #include "../common.h" -void verifyerrors_free(const VerifyErrors errors) { +void vx_Errors_free(const vx_Errors errors) { for (size_t i = 0; i < errors.len; i ++) { free(errors.items[i].path.ids); } free(errors.items); } -OpPath oppath_copy_add(const OpPath path, const size_t id) { - OpPath new_path = path; +vx_OpPath vx_OpPath_copy_add(const vx_OpPath path, const size_t id) { + vx_OpPath new_path = path; new_path.ids = malloc(sizeof(size_t) * (new_path.len + 1)); memcpy(new_path.ids, path.ids, sizeof(size_t) * new_path.len); new_path.ids[new_path.len++] = id; return new_path; } -void verifyerrors_add(VerifyErrors *errors, const VerifyError *error) { - errors->items = realloc(errors->items, sizeof(VerifyError) * (errors->len + 1)); - memcpy(&errors->items[errors->len ++], error, sizeof(VerifyError)); +void vx_Errors_add(vx_Errors *errors, const vx_Error *error) { + errors->items = realloc(errors->items, sizeof(vx_Error) * (errors->len + 1)); + memcpy(&errors->items[errors->len ++], error, sizeof(vx_Error)); } -void verifyerrors_add_all_and_free(VerifyErrors *dest, VerifyErrors *src) { +void vx_Errors_add_all_and_free(vx_Errors *dest, vx_Errors *src) { for (size_t i = 0; i < src->len; i++) { - verifyerrors_add(dest, &src->items[i]); + vx_Errors_add(dest, &src->items[i]); } free(src->items); // we don't free path on purpose! } -void verifyerrors_print(const VerifyErrors errors, FILE *dest) { +void vx_Errors_print(const vx_Errors errors, FILE *dest) { for (size_t i = 0; i < errors.len; i ++) { - const VerifyError err = errors.items[i]; + const vx_Error err = errors.items[i]; fputs("In operation ", dest); for (size_t j = 0; j < err.path.len; j ++) { diff --git a/ir/analysis.c b/ir/analysis.c index f5675a1..1e86825 100644 --- a/ir/analysis.c +++ b/ir/analysis.c @@ -1,6 +1,11 @@ +#include + #include "ir.h" -bool irview_find(SsaView *view, const SsaOpType type) { +bool vx_IrView_find(view, type) + vx_IrView *view; + const vx_IrOpType type; +{ for (size_t i = view->start; i < view->end; i ++) { if (view->block->ops[i].id == type) { view->start = i; @@ -11,24 +16,27 @@ bool irview_find(SsaView *view, const SsaOpType type) { return false; } -/** You should use `irblock_root(block)->as_root.vars[id].decl` instead! */ -SsaOp *irblock_finddecl_var(const SsaBlock *block, const SsaVar var) { +/** You should use `vx_IrBlock_root(block)->as_root.vars[id].decl` instead! */ +vx_IrOp *vx_IrBlock_find_var_decl(block, var) + const vx_IrBlock *block; + const vx_IrVar var; +{ for (size_t i = 0; i < block->ops_len; i ++) { - SsaOp *op = &block->ops[i]; + vx_IrOp *op = &block->ops[i]; for (size_t j = 0; j < op->outs_len; j ++) if (op->outs[j].var == var) return op; for (size_t j = 0; j < op->params_len; j ++) { - const SsaValue param = op->params[j].val; + const vx_IrValue param = op->params[j].val; - if (param.type == SSA_VAL_BLOCK) { + if (param.type == VX_IR_VALBLOCK) { for (size_t k = 0; k < param.block->ins_len; k ++) if (param.block->ins[k] == var) return op; - SsaOp *res = irblock_finddecl_var(param.block, var); + vx_IrOp *res = vx_IrBlock_find_var_decl(param.block, var); if (res != NULL) return res; } @@ -39,19 +47,22 @@ SsaOp *irblock_finddecl_var(const SsaBlock *block, const SsaVar var) { } -bool irblock_var_used(const SsaBlock *block, const SsaVar var) { +bool vx_IrBlock_var_used(block, var) + const vx_IrBlock *block; + const vx_IrVar var; +{ for (size_t i = 0; i < block->outs_len; i++) if (block->outs[i] == var) return true; for (long int i = block->ops_len - 1; i >= 0; i--) { - const SsaOp *op = &block->ops[i]; + const vx_IrOp *op = &block->ops[i]; for (size_t j = 0; j < op->params_len; j++) { - if (op->params[j].val.type == SSA_VAL_BLOCK) { - if (irblock_var_used(op->params[j].val.block, var)) { + if (op->params[j].val.type == VX_IR_VALBLOCK) { + if (vx_IrBlock_var_used(op->params[j].val.block, var)) { return true; } - } else if (op->params[j].val.type == SSA_VAL_VAR) { + } else if (op->params[j].val.type == VX_IR_VALVAR) { if (op->params[j].val.var == var) { return true; } @@ -62,17 +73,13 @@ bool irblock_var_used(const SsaBlock *block, const SsaVar var) { return false; } -// TODO: search more paths -bool irop_anyparam_hasvar(SsaOp *op, SsaVar var) { - for (size_t i = 0; i < op->params_len; i ++) - if (op->params[i].val.type == SSA_VAL_VAR && op->params[i].val.var == var) - return true; - return false; -} - -SsaOp *irblock_inside_out_vardecl_before(const SsaBlock *block, const SsaVar var, size_t before) { +vx_IrOp *vx_IrBlock_inside_out_vardecl_before(block, var, before) + const vx_IrBlock *block; + const vx_IrVar var; + size_t before; +{ while (before --> 0) { - SsaOp *op = &block->ops[before]; + vx_IrOp *op = &block->ops[before]; for (size_t i = 0; i < op->outs_len; i ++) if (op->outs[i].var == var) @@ -82,63 +89,74 @@ SsaOp *irblock_inside_out_vardecl_before(const SsaBlock *block, const SsaVar var if (block->parent == NULL) return NULL; - return irblock_inside_out_vardecl_before(block->parent, var, block->parent_index); + return vx_IrBlock_inside_out_vardecl_before(block->parent, var, block->parent_index); } -bool irop_is_pure(SsaOp *op) { +bool vx_IrOp_is_volatile(op) + vx_IrOp *op; +{ switch (op->id) { - case SSA_OP_NOP: - case SSA_OP_IMM: - case SSA_OP_REINTERPRET: - case SSA_OP_ZEROEXT: - case SSA_OP_SIGNEXT: - case SSA_OP_TOFLT: - case SSA_OP_FROMFLT: - case SSA_OP_BITCAST: - case SSA_OP_ADD: - case SSA_OP_SUB: - case SSA_OP_MUL: - case SSA_OP_DIV: - case SSA_OP_MOD: - case SSA_OP_GT: - case SSA_OP_GTE: - case SSA_OP_LT: - case SSA_OP_LTE: - case SSA_OP_EQ: - case SSA_OP_NEQ: - case SSA_OP_NOT: - case SSA_OP_AND: - case SSA_OP_OR: - case SSA_OP_BITWISE_NOT: - case SSA_OP_BITWISE_AND: - case SSA_OP_BITIWSE_OR: - case SSA_OP_SHL: - case SSA_OP_SHR: - case SSA_OP_FOR: - return true; + case VX_IR_OP_NOP: + case VX_IR_OP_IMM: + case VX_IR_OP_REINTERPRET: + case VX_IR_OP_ZEROEXT: + case VX_IR_OP_SIGNEXT: + case VX_IR_OP_TOFLT: + case VX_IR_OP_FROMFLT: + case VX_IR_OP_BITCAST: + case VX_IR_OP_ADD: + case VX_IR_OP_SUB: + case VX_IR_OP_MUL: + case VX_IR_OP_DIV: + case VX_IR_OP_MOD: + case VX_IR_OP_GT: + case VX_IR_OP_GTE: + case VX_IR_OP_LT: + case VX_IR_OP_LTE: + case VX_IR_OP_EQ: + case VX_IR_OP_NEQ: + case VX_IR_OP_NOT: + case VX_IR_OP_AND: + case VX_IR_OP_OR: + case VX_IR_OP_BITWISE_NOT: + case VX_IR_OP_BITWISE_AND: + case VX_IR_OP_BITIWSE_OR: + case VX_IR_OP_SHL: + case VX_IR_OP_SHR: + case VX_IR_OP_FOR: + case VX_IR_OP_LOAD: + case VX_IR_OP_STORE: + case VX_IR_OP_PLACE: + return false; - case SSA_OP_REPEAT: - case CIR_OP_CFOR: - case SSA_OP_IF: - case SSA_OP_FLATTEN_PLEASE: - case SSA_OP_INFINITE: - case SSA_OP_WHILE: - case SSA_OP_FOREACH: - case SSA_OP_FOREACH_UNTIL: - for (size_t i = 0; i < op->params_len; i ++) - if (op->params[i].val.type == SSA_VAL_BLOCK) - if (!irblock_is_pure(op->params[i].val.block)) - return false; + case VX_IR_OP_LOAD_VOLATILE: + case VX_IR_OP_STORE_VOLATILE: return true; + + case VX_IR_OP_REPEAT: + case CVX_IR_OP_CFOR: + case VX_IR_OP_IF: + case VX_IR_OP_FLATTEN_PLEASE: + case VX_IR_OP_INFINITE: + case VX_IR_OP_WHILE: + case VX_IR_OP_FOREACH: + case VX_IR_OP_FOREACH_UNTIL: + for (size_t i = 0; i < op->params_len; i ++) + if (op->params[i].val.type == VX_IR_VALBLOCK) + if (vx_IrBlock_is_volatile(op->params[i].val.block)) + return true; + return false; default: - return false; + assert(false); } } -bool irblock_is_pure(const SsaBlock *block) { +bool vx_IrBlock_is_volatile(block) + const vx_IrBlock *block; +{ for (size_t j = 0; j < block->ops_len; j ++) - if (!irop_is_pure(&block->ops[j])) - return false; - return true; + if (vx_IrOp_is_volatile(&block->ops[j])) + return true; + return false; } diff --git a/ir/builder.c b/ir/builder.c index f810e6f..fcca8af 100644 --- a/ir/builder.c +++ b/ir/builder.c @@ -7,7 +7,11 @@ #include "../utils.h" -void irblock_init(SsaBlock *block, SsaBlock *parent, size_t parent_index) { +void vx_IrBlock_init(block, parent, parent_index) + vx_IrBlock *block; + vx_IrBlock *parent; + size_t parent_index; +{ block->parent = parent; block->parent_index = parent_index; @@ -25,16 +29,22 @@ void irblock_init(SsaBlock *block, SsaBlock *parent, size_t parent_index) { block->should_free = false; } -SsaBlock *irblock_heapalloc(SsaBlock *parent, size_t parent_index) { - SsaBlock *new = malloc(sizeof(SsaBlock)); +vx_IrBlock *vx_IrBlock_init_heap(parent, parent_index) + vx_IrBlock *parent; + size_t parent_index; +{ + vx_IrBlock *new = malloc(sizeof(vx_IrBlock)); if (new == NULL) return NULL; - irblock_init(new, parent, parent_index); + vx_IrBlock_init(new, parent, parent_index); new->should_free = true; return new; } -void irblock_make_root(SsaBlock *block, const size_t total_vars) { +void vx_IrBlock_make_root(block, total_vars) + vx_IrBlock *block; + const size_t total_vars; +{ assert(block->parent == NULL); block->is_root = true; @@ -42,39 +52,53 @@ void irblock_make_root(SsaBlock *block, const size_t total_vars) { block->as_root.vars = malloc(sizeof(*block->as_root.vars) * total_vars); for (size_t i = 0; i < total_vars; i ++) { - SsaOp *decl = irblock_finddecl_var(block, i); + vx_IrOp *decl = vx_IrBlock_find_var_decl(block, i); // decl can be null! block->as_root.vars[i].decl = decl; } } -void irblock_add_in(SsaBlock *block, const SsaVar var) { - block->ins = realloc(block->ins, sizeof(SsaVar) * (block->ins_len + 1)); +void vx_IrBlock_add_in(block, var) + vx_IrBlock *block; + const vx_IrVar var; +{ + block->ins = realloc(block->ins, sizeof(vx_IrVar) * (block->ins_len + 1)); block->ins[block->ins_len ++] = var; } -void irblock_add_op(SsaBlock *block, const SsaOp *op) { - block->ops = realloc(block->ops, sizeof(SsaOp) * (block->ops_len + 1)); +void vx_IrBlock_add_op(block, op) + vx_IrBlock *block; + const vx_IrOp *op; +{ + block->ops = realloc(block->ops, sizeof(vx_IrOp) * (block->ops_len + 1)); block->ops[block->ops_len ++] = *op; } -void irblock_add_all_op(SsaBlock *dest, const SsaBlock *src) { - dest->ops = realloc(dest->ops, sizeof(SsaOp) * (dest->ops_len + src->ops_len)); +void vx_IrBlock_add_all_op(dest, src) + vx_IrBlock *dest; + const vx_IrBlock *src; +{ + dest->ops = realloc(dest->ops, sizeof(vx_IrOp) * (dest->ops_len + src->ops_len)); memcpy(dest->ops + dest->ops_len, src->ops, src->ops_len); dest->ops_len += src->ops_len; } -void irblock_add_out(SsaBlock *block, SsaVar out) { - block->outs = realloc(block->outs, sizeof(SsaVar) * (block->outs_len + 1)); +void vx_IrBlock_add_out(block, out) + vx_IrBlock *block; + vx_IrVar out; +{ + block->outs = realloc(block->outs, sizeof(vx_IrVar) * (block->outs_len + 1)); block->outs[block->outs_len ++] = out; } -void irblock_destroy(SsaBlock *block) { +void vx_IrBlock_destroy(block) + vx_IrBlock *block; +{ if (block == NULL) return; free(block->ins); for (size_t i = 0; i < block->ops_len; i ++) - irop_destroy(&block->ops[i]); + vx_IrOp_destroy(&block->ops[i]); free(block->ops); free(block->outs); if (block->is_root) @@ -83,7 +107,10 @@ void irblock_destroy(SsaBlock *block) { free(block); } -SsaValue *irop_param(const SsaOp *op, SsaName name) { +vx_IrValue *vx_IrOp_param(op, name) + const vx_IrOp *op; + vx_IrName name; +{ for (size_t i = 0; i < op->params_len; i ++) if (op->params[i].name == name) return &op->params[i].val; @@ -91,12 +118,18 @@ SsaValue *irop_param(const SsaOp *op, SsaName name) { return NULL; } -void irnamedvalue_destroy(SsaNamedValue v) { - if (v.val.type == SSA_VAL_BLOCK) - irblock_destroy(v.val.block); +void vx_IrNamedValue_destroy(value) + vx_IrNamedValue value; +{ + if (value.val.type == VX_IR_VALBLOCK) + vx_IrBlock_destroy(value.val.block); } -void irop_init(SsaOp *op, const SsaOpType type, SsaBlock *parent) { +void vx_IrOp_init(op, type, parent) + vx_IrOp *op; + const vx_IrOpType type; + vx_IrBlock *parent; +{ op->types = NULL; op->types_len = 0; @@ -114,81 +147,113 @@ void irop_init(SsaOp *op, const SsaOpType type, SsaBlock *parent) { op->states_len = 0; } -void irop_add_type(SsaOp *op, SsaType type) { - op->types = realloc(op->types, sizeof(SsaType) * (op->types_len + 1)); +void vx_IrOp_add_type(op, type) + vx_IrOp *op; + vx_IrType type; +{ + op->types = realloc(op->types, sizeof(vx_IrType) * (op->types_len + 1)); op->types[op->types_len ++] = type; } -void irop_add_out(SsaOp *op, SsaVar v, SsaType t) { - op->outs = realloc(op->outs, sizeof(SsaTypedVar) * (op->outs_len + 1)); - op->outs[op->outs_len ++] = (SsaTypedVar) { .var = v, .type = t }; +void vx_IrOp_add_out(op, var, type) + vx_IrOp *op; + vx_IrVar var; + vx_IrType type; +{ + op->outs = realloc(op->outs, sizeof(vx_IrTypedVar) * (op->outs_len + 1)); + op->outs[op->outs_len ++] = (vx_IrTypedVar) { .var = var, .type = type }; } -void irop_add_param(SsaOp *op, SsaNamedValue p) { - op->params = realloc(op->params, sizeof(SsaNamedValue) * (op->params_len + 1)); +void vx_IrOp_add_param(op, p) + vx_IrOp *op; + vx_IrNamedValue p; +{ + op->params = realloc(op->params, sizeof(vx_IrNamedValue) * (op->params_len + 1)); op->params[op->params_len ++] = p; } -void irnamedvalue_rename(SsaNamedValue *value, SsaName newn) { - value->name = newn; +void vx_IrOp_add_param_s(op, name, val) + vx_IrOp *op; + vx_IrName name; + const vx_IrValue val; +{ + vx_IrOp_add_param(op, vx_IrNamedValue_create(name, val)); } -void irop_add_param_s(SsaOp *op, SsaName name, const SsaValue val) { - irop_add_param(op, irnamedvalue_create(name, val)); -} - -void irop_destroy(SsaOp *op) { - irop_remove_params(op); +void vx_IrOp_destroy(op) + vx_IrOp *op; +{ + vx_IrOp_remove_params(op); free(op->types); free(op->outs); free(op->states); } -void irop_remove_params(SsaOp *op) { +void vx_IrOp_remove_params(op) + vx_IrOp *op; +{ for (size_t i = 0; i < op->params_len; i ++) - irnamedvalue_destroy(op->params[i]); + vx_IrNamedValue_destroy(op->params[i]); free(op->params); op->params = NULL; op->params_len = 0; } -void irop_steal_outs(SsaOp *dest, const SsaOp *src) { +void vx_IrOp_steal_outs(dest, src) + vx_IrOp *dest; + const vx_IrOp *src; +{ for (size_t i = 0; i < src->outs_len; i ++) { - irop_add_out(dest, src->outs[i].var, src->outs[i].type); + vx_IrOp_add_out(dest, src->outs[i].var, src->outs[i].type); } } -void irop_remove_out_at(SsaOp *op, const size_t id) { - memmove(op->outs + id, op->outs + id + 1, sizeof(SsaTypedVar) * (op->outs_len - id - 1)); +void vx_IrOp_remove_out_at(op, id) + vx_IrOp *op; + const size_t id; +{ + memmove(op->outs + id, op->outs + id + 1, sizeof(vx_IrTypedVar) * (op->outs_len - id - 1)); op->outs_len --; } -void irblock_remove_out_at(SsaBlock *block, size_t id) { - memmove(block->outs + id, block->outs + id + 1, sizeof(SsaVar) * (block->outs_len - id - 1)); +void vx_IrBlock_remove_out_at(block, id) + vx_IrBlock *block; + size_t id; +{ + memmove(block->outs + id, block->outs + id + 1, sizeof(vx_IrVar) * (block->outs_len - id - 1)); block->outs_len --; } -void irop_remove_param_at(SsaOp *op, const size_t id) { - memmove(op->params + id, op->params + id + 1, sizeof(SsaNamedValue) * (op->params_len - id - 1)); +void vx_IrOp_remove_param_at(op, id) + vx_IrOp *op; + const size_t id; +{ + memmove(op->params + id, op->params + id + 1, sizeof(vx_IrNamedValue) * (op->params_len - id - 1)); op->params_len --; } -void irop_remove_state_at(SsaOp *op, const size_t id) { - memmove(op->states + id, op->states + id + 1, sizeof(SsaNamedValue) * (op->states_len - id - 1)); +void vx_IrOp_remove_state_at(op, id) + vx_IrOp *op; + const size_t id; +{ + memmove(op->states + id, op->states + id + 1, sizeof(vx_IrNamedValue) * (op->states_len - id - 1)); op->states_len --; } -SsaValue irvalue_clone(const SsaValue value) { +vx_IrValue vx_IrValue_clone(const vx_IrValue value) { // TODO return value; } -void irop_steal_states(SsaOp *dest, const SsaOp *src) { +void vx_IrOp_steal_states(dest, src) + vx_IrOp *dest; + const vx_IrOp *src; +{ free(dest->states); - dest->states = malloc(sizeof(SsaValue) * src->states_len); + dest->states = malloc(sizeof(vx_IrValue) * src->states_len); for (size_t i = 0; i < src->states_len; i ++) - dest->states[i] = irvalue_clone(src->states[i]); + dest->states[i] = vx_IrValue_clone(src->states[i]); dest->states_len = src->states_len; } diff --git a/ir/cir.h b/ir/cir.h index ed26460..debe2e8 100644 --- a/ir/cir.h +++ b/ir/cir.h @@ -4,21 +4,20 @@ #include "ir.h" /** transform cfor to c ir primitives that are representable in ir ir */ -void cirblock_normalize(SsaBlock *block); +void vx_CIrBlock_normalize(vx_IrBlock *block); -OptSsaVar cirblock_mksa_states(SsaBlock *block); +vx_OptIrVar vx_CIrBlock_mksa_states(vx_IrBlock *block); +void vx_CIrBlock_mksa_final(vx_IrBlock *block); -void cirblock_mksa_final(SsaBlock *block); +vx_Errors vx_CIrBlock_verify(const vx_IrBlock *block, vx_OpPath path); -VerifyErrors cirblock_verify(const SsaBlock *block, OpPath path); - -static int cir_verify(const SsaBlock *block) { - OpPath path; +static int vx_cir_verify(const vx_IrBlock *block) { + vx_OpPath path; path.ids = NULL; path.len = 0; - const VerifyErrors errs = cirblock_verify(block, path); - verifyerrors_print(errs, stderr); - verifyerrors_free(errs); + const vx_Errors errs = vx_CIrBlock_verify(block, path); + vx_Errors_print(errs, stderr); + vx_Errors_free(errs); return errs.len > 0; } diff --git a/ir/dump.c b/ir/dump.c index 7fa9940..c480cfc 100644 --- a/ir/dump.c +++ b/ir/dump.c @@ -1,106 +1,117 @@ #include "ir.h" -const char *iroptype_names[SSAOPTYPE_LEN] = { - [SSA_OP_NOP] = "nop", - [SSA_OP_IMM] = "imm", - [SSA_OP_FLATTEN_PLEASE] = ".", +const char *vx_IrOpType_names[SSAOPTYPE_LEN] = { + [VX_IR_OP_NOP] = "nop", + [VX_IR_OP_IMM] = "imm", + [VX_IR_OP_FLATTEN_PLEASE] = ".", - [SSA_OP_REINTERPRET] = "reinterpret", - [SSA_OP_ZEROEXT] = "zext", - [SSA_OP_SIGNEXT] = "sext", - [SSA_OP_TOFLT] = "toflt", - [SSA_OP_FROMFLT] = "fromflt", - [SSA_OP_BITCAST] = "bitcast", - - [SSA_OP_ADD] = "add", - [SSA_OP_SUB] = "sub", - [SSA_OP_MUL] = "mul", - [SSA_OP_DIV] = "div", - [SSA_OP_MOD] = "mod", - - [SSA_OP_GT] = "gt", - [SSA_OP_GTE] = "gte", - [SSA_OP_LT] = "lt", - [SSA_OP_LTE] = "lte", - [SSA_OP_EQ] = "eq", - [SSA_OP_NEQ] = "neq", - - [SSA_OP_NOT] = "not", - [SSA_OP_AND] = "and", - [SSA_OP_OR] = "or", - - [SSA_OP_BITWISE_NOT] = "bwnot", - [SSA_OP_BITWISE_AND] = "bwand", - [SSA_OP_BITIWSE_OR] = "bwor", - - [SSA_OP_SHL] = "shl", - [SSA_OP_SHR] = "shr", - - [SSA_OP_FOR] = "for", - [SSA_OP_INFINITE] = "infinite", - [SSA_OP_WHILE] = "while", - [SSA_OP_CONTINUE] = "continue", - [SSA_OP_BREAK] = "break", - - [SSA_OP_FOREACH] = "foreach", - [SSA_OP_FOREACH_UNTIL] = "foreach_until", - [SSA_OP_REPEAT] = "repeat", - [CIR_OP_CFOR] = "cfor", - - [SSA_OP_IF] = "if" + [VX_IR_OP_REINTERPRET] = "reinterpret", + [VX_IR_OP_ZEROEXT] = "zext", + [VX_IR_OP_SIGNEXT] = "sext", + [VX_IR_OP_TOFLT] = "toflt", + [VX_IR_OP_FROMFLT] = "fromflt", + [VX_IR_OP_BITCAST] = "bitcast", + + [VX_IR_OP_LOAD] = "load", + [VX_IR_OP_LOAD_VOLATILE] = "load-v", + [VX_IR_OP_STORE] = "store", + [VX_IR_OP_STORE_VOLATILE] = "store-v", + [VX_IR_OP_PLACE] = "place", + + [VX_IR_OP_ADD] = "add", + [VX_IR_OP_SUB] = "sub", + [VX_IR_OP_MUL] = "mul", + [VX_IR_OP_DIV] = "div", + [VX_IR_OP_MOD] = "mod", + + [VX_IR_OP_GT] = "gt", + [VX_IR_OP_GTE] = "gte", + [VX_IR_OP_LT] = "lt", + [VX_IR_OP_LTE] = "lte", + [VX_IR_OP_EQ] = "eq", + [VX_IR_OP_NEQ] = "neq", + + [VX_IR_OP_NOT] = "not", + [VX_IR_OP_AND] = "and", + [VX_IR_OP_OR] = "or", + + [VX_IR_OP_BITWISE_NOT] = "bwnot", + [VX_IR_OP_BITWISE_AND] = "bwand", + [VX_IR_OP_BITIWSE_OR] = "bwor", + + [VX_IR_OP_SHL] = "shl", + [VX_IR_OP_SHR] = "shr", + + [VX_IR_OP_FOR] = "for", + [VX_IR_OP_INFINITE] = "infinite", + [VX_IR_OP_WHILE] = "while", + [VX_IR_OP_CONTINUE] = "continue", + [VX_IR_OP_BREAK] = "break", + + [VX_IR_OP_FOREACH] = "foreach", + [VX_IR_OP_FOREACH_UNTIL] = "foreach_until", + [VX_IR_OP_REPEAT] = "repeat", + [CVX_IR_OP_CFOR] = "cfor", + + [VX_IR_OP_IF] = "if" }; -const char *irname_str[] = { - [SSA_NAME_OPERAND_A] = "a", - [SSA_NAME_OPERAND_B] = "b", +const char *vx_IrName_str[] = { + [VX_IR_NAME_OPERAND_A] = "a", + [VX_IR_NAME_OPERAND_B] = "b", - [SSA_NAME_BLOCK] = "block", - [SSA_NAME_VALUE] = "val", - [SSA_NAME_COND] = "cond", + [VX_IR_NAME_BLOCK] = "block", + [VX_IR_NAME_VALUE] = "val", + [VX_IR_NAME_COND] = "cond", - [SSA_NAME_COND_THEN] = "then", - [SSA_NAME_COND_ELSE] = "else", + [VX_IR_NAME_COND_THEN] = "then", + [VX_IR_NAME_COND_ELSE] = "else", - [SSA_NAME_LOOP_DO] = "do", - [SSA_NAME_LOOP_START] = "start", - [SSA_NAME_LOOP_ENDEX] = "endex", - [SSA_NAME_LOOP_STRIDE] = "stride", + [VX_IR_NAME_LOOP_DO] = "do", + [VX_IR_NAME_LOOP_START] = "start", + [VX_IR_NAME_LOOP_ENDEX] = "endex", + [VX_IR_NAME_LOOP_STRIDE] = "stride", - [SSA_NAME_ALTERNATIVE_A] = "a", - [SSA_NAME_ALTERNATIVE_B] = "b", + [VX_IR_NAME_ALTERNATIVE_A] = "a", + [VX_IR_NAME_ALTERNATIVE_B] = "b", }; -void irvalue_dump(SsaValue value, FILE *out, const size_t indent) { +void vx_IrValue_dump(vx_IrValue value, FILE *out, const size_t indent) { switch (value.type) { - case SSA_VAL_IMM_INT: { + case VX_IR_VALUNINIT: { + fprintf(out, "uninit"); + } + break; + + case VX_IR_VALIMM_INT: { fprintf(out, "%lld", value.imm_int); } break; - case SSA_VAL_IMM_FLT: { + case VX_IR_VALIMM_FLT: { fprintf(out, "%f", value.imm_flt); } break; - case SSA_VAL_VAR: { + case VX_IR_VALVAR: { fprintf(out, "%%%zu", value.var); } break; - case SSA_VAL_BLOCK: { - const SsaBlock *block = value.block; + case VX_IR_VALBLOCK: { + const vx_IrBlock *block = value.block; fputc('(', out); for (size_t i = 0; i < block->ins_len; i ++) { if (i > 0) fputc(',', out); - const SsaVar in = block->ins[i]; + const vx_IrVar in = block->ins[i]; fprintf(out, "%%%zu", in); } fputs("){\n", out); for (size_t i = 0; i < block->ops_len; i ++) { - irop_dump(block->ops + i, out, indent + 1); + vx_IrOp_dump(block->ops + i, out, indent + 1); } if (block->outs_len > 0) { @@ -127,21 +138,21 @@ void irvalue_dump(SsaValue value, FILE *out, const size_t indent) { } } -void irop_dump(const SsaOp *op, FILE *out, size_t indent) { +void vx_IrOp_dump(const vx_IrOp *op, FILE *out, size_t indent) { for (size_t j = 0; j < indent; j ++) fputs(" ", out); for (size_t j = 0; j < op->outs_len; j ++) { if (j > 0) fputc(',', out); - const SsaTypedVar var = op->outs[j]; + const vx_IrTypedVar var = op->outs[j]; fprintf(out, "%s %%%zu", var.type, var.var); } if (op->outs_len > 0) fputs(" = ", out); - fprintf(out, "%s ", iroptype_names[op->id]); + fprintf(out, "%s ", vx_IrOpType_names[op->id]); if (op->types_len > 0) { fputc('<', out); @@ -158,27 +169,27 @@ void irop_dump(const SsaOp *op, FILE *out, size_t indent) { for (size_t j = 0; j < op->params_len; j ++) { if (j > 0) fputc(' ', out); - const SsaNamedValue param = op->params[j]; - fprintf(out, "%s=", irname_str[param.name]); - irvalue_dump(param.val, out, indent); + const vx_IrNamedValue param = op->params[j]; + fprintf(out, "%s=", vx_IrName_str[param.name]); + vx_IrValue_dump(param.val, out, indent); } fputs(";\n", out); } -void irblock_dump(const SsaBlock *block, FILE *out, const size_t indent) { +void vx_IrBlock_dump(const vx_IrBlock *block, FILE *out, const size_t indent) { for (size_t i = 0; i < indent; i ++) fputs(" ", out); fputs("BLOCK", out); for (size_t i = 0; i < block->ins_len; i ++) { - const SsaVar in = block->ins[i]; + const vx_IrVar in = block->ins[i]; fprintf(out, " %%%zu", in); } fputc('\n', out); for (size_t i = 0; i < block->ops_len; i ++) { - irop_dump(block->ops + i, out, indent + 1); + vx_IrOp_dump(block->ops + i, out, indent + 1); } for (size_t i = 0; i < indent; i ++) @@ -186,7 +197,7 @@ void irblock_dump(const SsaBlock *block, FILE *out, const size_t indent) { fputs("return", out); for (size_t i = 0; i < block->outs_len; i ++) { - const SsaVar var = block->outs[i]; + const vx_IrVar var = block->outs[i]; fprintf(out, " %%%zu", var); } fputc('\n', out); diff --git a/ir/eval.c b/ir/eval.c index 69f5859..cb17a0d 100644 --- a/ir/eval.c +++ b/ir/eval.c @@ -6,18 +6,18 @@ #include "../utils.h" -bool irblock_staticeval_var(const SsaBlock *block, const SsaVar var, SsaValue *dest) { - const SsaOp *decl = irblock_root(block)->as_root.vars[var].decl; +bool vx_IrBlock_eval_var(const vx_IrBlock *block, const vx_IrVar var, vx_IrValue *dest) { + const vx_IrOp *decl = vx_IrBlock_root(block)->as_root.vars[var].decl; if (decl == NULL) return false; - if (decl->id == SSA_OP_IMM) { - const SsaValue *value = irop_param(decl, SSA_NAME_VALUE); + if (decl->id == VX_IR_OP_IMM) { + const vx_IrValue *value = vx_IrOp_param(decl, VX_IR_NAME_VALUE); if (value == NULL) return false; - if (value->type == SSA_VAL_VAR) - return irblock_staticeval_var(block, value->var, dest); + if (value->type == VX_IR_VALVAR) + return vx_IrBlock_eval_var(block, value->var, dest); *dest = *value; return true; @@ -26,52 +26,52 @@ bool irblock_staticeval_var(const SsaBlock *block, const SsaVar var, SsaValue *d return false; } -bool irblock_mightbe_var(const SsaBlock *block, SsaVar var, SsaValue v) { - SsaValue is; - if (irblock_staticeval_var(block, var, &is)) { - return memcmp(&is, &v, sizeof(SsaValue)) == 0; +bool vx_Irblock_mightbe_var(const vx_IrBlock *block, vx_IrVar var, vx_IrValue v) { + vx_IrValue is; + if (vx_IrBlock_eval_var(block, var, &is)) { + return memcmp(&is, &v, sizeof(vx_IrValue)) == 0; } return true; } -bool irblock_alwaysis_var(const SsaBlock *block, SsaVar var, SsaValue v) { - SsaValue is; - if (!irblock_staticeval_var(block, var, &is)) +bool vx_Irblock_alwaysis_var(const vx_IrBlock *block, vx_IrVar var, vx_IrValue v) { + vx_IrValue is; + if (!vx_IrBlock_eval_var(block, var, &is)) return false; - return memcmp(&is, &v, sizeof(SsaValue)) == 0; + return memcmp(&is, &v, sizeof(vx_IrValue)) == 0; } -void irblock_staticeval(SsaBlock *block, SsaValue *v) { - if (v->type == SSA_VAL_VAR) - while (irblock_staticeval_var(block, v->var, v)) {} +void vx_Irblock_eval(vx_IrBlock *block, vx_IrValue *v) { + if (v->type == VX_IR_VALVAR) + while (vx_IrBlock_eval_var(block, v->var, v)) {} } -struct SsaStaticIncrement irop_detect_static_increment(const SsaOp *op) { - if (op->id != SSA_OP_ADD && op->id != SSA_OP_SUB) - return (struct SsaStaticIncrement) { .detected = false }; +struct IrStaticIncrement vx_IrOp_detect_static_increment(const vx_IrOp *op) { + if (op->id != VX_IR_OP_ADD && op->id != VX_IR_OP_SUB) + return (struct IrStaticIncrement) { .detected = false }; - const SsaValue a = *irop_param(op, SSA_NAME_OPERAND_A); - const SsaValue b = *irop_param(op, SSA_NAME_OPERAND_B); + const vx_IrValue a = *vx_IrOp_param(op, VX_IR_NAME_OPERAND_A); + const vx_IrValue b = *vx_IrOp_param(op, VX_IR_NAME_OPERAND_B); - if (a.type == SSA_VAL_VAR && b.type == SSA_VAL_IMM_INT) { + if (a.type == VX_IR_VALVAR && b.type == VX_IR_VALIMM_INT) { long long by = b.imm_int; - if (op->id == SSA_OP_SUB) + if (op->id == VX_IR_OP_SUB) by = -by; - return (struct SsaStaticIncrement) { + return (struct IrStaticIncrement) { .detected = false, .var = a.var, .by = by }; } - if (b.type == SSA_VAL_VAR && a.type == SSA_VAL_IMM_INT && op->id == SSA_OP_ADD) { - return (struct SsaStaticIncrement) { + if (b.type == VX_IR_VALVAR && a.type == VX_IR_VALIMM_INT && op->id == VX_IR_OP_ADD) { + return (struct IrStaticIncrement) { .detected = false, .var = b.var, .by = a.imm_int }; } - return (struct SsaStaticIncrement) { .detected = false }; + return (struct IrStaticIncrement) { .detected = false }; } diff --git a/ir/ir.c b/ir/ir.c index 7150468..6f1722b 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -2,68 +2,52 @@ #include #include -#include - -SsaOp *irblock_traverse(SsaView *current) { - if (irview_has_next(*current)) { - SsaOp *op = ¤t->block->ops[current->start]; - *current = irview_drop(*current, 1); - return op; - } - - if (current->block->parent == NULL) - return NULL; - - *current = irview_of_all(current->block->parent); - - return irblock_traverse(current); -} // TODO: add boolean to stop traverse -void irview_deep_traverse(SsaView top, void (*callback)(SsaOp *op, void *data), void *data) { +void vx_IrView_deep_traverse(vx_IrView top, void (*callback)(vx_IrOp *op, void *data), void *data) { for (size_t i = top.start; i < top.end; i ++) { - SsaOp *op = &top.block->ops[i]; + vx_IrOp *op = &top.block->ops[i]; for (size_t j = 0; j < op->params_len; j ++) - if (op->params[j].val.type == SSA_VAL_BLOCK) - irview_deep_traverse(irview_of_all(op->params[j].val.block), callback, data); + if (op->params[j].val.type == VX_IR_VALBLOCK) + vx_IrView_deep_traverse(vx_IrView_of_all(op->params[j].val.block), callback, data); callback(op, data); } } -const SsaBlock *irblock_root(const SsaBlock *block) { +const vx_IrBlock *vx_IrBlock_root(const vx_IrBlock *block) { while (block != NULL && !block->is_root) { block = block->parent; } return block; } -void irblock_swap_in_at(SsaBlock *block, const size_t a, const size_t b) { +void vx_IrBlock_swap_in_at(vx_IrBlock *block, const size_t a, const size_t b) { if (a == b) return; - const SsaVar va = block->ins[a]; + const vx_IrVar va = block->ins[a]; block->ins[a] = block->ins[b]; block->ins[b] = va; } -void irblock_swap_out_at(SsaBlock *block, size_t a, size_t b) { +void vx_IrBlock_swap_out_at(vx_IrBlock *block, size_t a, size_t b) { if (a == b) return; - const SsaVar va = block->outs[a]; + const vx_IrVar va = block->outs[a]; block->outs[a] = block->outs[b]; block->outs[b] = va; } -SsaVar irblock_new_var(SsaBlock *block, SsaOp *decl) { +vx_IrVar vx_IrBlock_new_var(vx_IrBlock *block, vx_IrOp *decl) { assert(block != NULL); assert(decl != NULL); - SsaBlock *root = (SsaBlock *) irblock_root(block); + vx_IrBlock *root = (vx_IrBlock *) vx_IrBlock_root(block); assert(root != NULL); root->as_root.vars = realloc(root->as_root.vars, (root->as_root.vars_len + 1) * sizeof(*root->as_root.vars)); - SsaVar new = root->as_root.vars_len ++; + vx_IrVar new = root->as_root.vars_len ++; root->as_root.vars[new].decl = decl; return new; } diff --git a/ir/ir.h b/ir/ir.h index 2e021f0..fcdf1eb 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -1,5 +1,5 @@ -#ifndef SSA_H -#define SSA_H +#ifndef IR_H +#define IR_H #include #include @@ -7,316 +7,320 @@ #include "../common.h" -struct SsaOp_s; -typedef struct SsaOp_s SsaOp; +struct vx_IrOp_s; +typedef struct vx_IrOp_s vx_IrOp; -typedef size_t SsaVar; +typedef size_t vx_IrVar; typedef struct { - SsaVar var; + vx_IrVar var; bool present; -} OptSsaVar; +} vx_OptIrVar; -#define SSAVAR_OPT_NONE (OptSsaVar) {.present = false,.var = 0} -#define SSAVAR_OPT_SOME(v) (OptSsaVar) {.present = true,.var = v} +#define VX_IRVAR_OPT_NONE (vx_OptIrVar) {.present = false,.var = 0} +#define VX_IRVAR_OPT_SOME(v) (vx_OptIrVar) {.present = true,.var = v} -typedef const char *SsaType; +typedef const char *vx_IrType; -struct SsaBlock_s; -typedef struct SsaBlock_s SsaBlock; +struct vx_IrBlock_s; +typedef struct vx_IrBlock_s vx_IrBlock; -struct SsaBlock_s { - SsaBlock *parent; +struct vx_IrBlock_s { + vx_IrBlock *parent; size_t parent_index; bool is_root; struct { struct { - SsaOp *decl; + vx_IrOp *decl; } *vars; size_t vars_len; } as_root; - SsaVar *ins; - size_t ins_len; + vx_IrVar *ins; + size_t ins_len; - SsaOp *ops; - size_t ops_len; + vx_IrOp *ops; + size_t ops_len; - SsaVar *outs; - size_t outs_len; + vx_IrVar *outs; + size_t outs_len; bool should_free; }; -const SsaBlock *irblock_root(const SsaBlock *block); +const vx_IrBlock *vx_IrBlock_root(const vx_IrBlock *block); -VerifyErrors irblock_verify(const SsaBlock *block, OpPath path); +// TODO: do differently -static int ir_verify(const SsaBlock *block) { - OpPath path; +vx_Errors vx_IrBlock_verify(const vx_IrBlock *block, vx_OpPath path); + +static int vx_ir_verify(const vx_IrBlock *block) { + vx_OpPath path; path.ids = NULL; path.len = 0; - const VerifyErrors errs = irblock_verify(block, path); - verifyerrors_print(errs, stderr); - verifyerrors_free(errs); + const vx_Errors errs = vx_IrBlock_verify(block, path); + vx_Errors_print(errs, stderr); + vx_Errors_free(errs); return errs.len > 0; } +// TODO: move builder functions into separate header + /** DON'T RUN INIT AFTERWARDS */ -SsaBlock *irblock_heapalloc(SsaBlock *parent, size_t parent_index); -void irblock_init(SsaBlock *block, SsaBlock *parent, size_t parent_index); +vx_IrBlock *vx_IrBlock_init_heap(vx_IrBlock *parent, size_t parent_index); +void vx_IrBlock_init(vx_IrBlock *block, vx_IrBlock *parent, size_t parent_index); /** run AFTER you finished building it! */ -void irblock_make_root(SsaBlock *block, size_t total_vars); -void irblock_add_in(SsaBlock *block, SsaVar var); -void irblock_add_op(SsaBlock *block, const SsaOp *op); -void irblock_add_all_op(SsaBlock *dest, const SsaBlock *src); -void irblock_add_out(SsaBlock *block, SsaVar out); -void irblock_destroy(SsaBlock *block); - -SsaVar irblock_new_var(SsaBlock *block, SsaOp *decl); -void irblock_flatten(SsaBlock *block); -void irblock_swap_in_at(SsaBlock *block, size_t a, size_t b); -void irblock_swap_out_at(SsaBlock *block, size_t a, size_t b); -static void irblock_swap_state_at(SsaBlock *block, size_t a, size_t b) { - irblock_swap_in_at(block, a, b); - irblock_swap_out_at(block, a, b); -} -void irblock_remove_out_at(SsaBlock *block, size_t id); +void vx_IrBlock_make_root(vx_IrBlock *block, size_t total_vars); +void vx_IrBlock_add_in(vx_IrBlock *block, vx_IrVar var); +void vx_IrBlock_add_op(vx_IrBlock *block, const vx_IrOp *op); +void vx_IrBlock_add_all_op(vx_IrBlock *dest, const vx_IrBlock *src); +void vx_IrBlock_add_out(vx_IrBlock *block, vx_IrVar out); +void vx_IrBlock_destroy(vx_IrBlock *block); + +vx_IrVar vx_IrBlock_new_var(vx_IrBlock *block, vx_IrOp *decl); +void vx_IrBlock_flatten(vx_IrBlock *block); +void vx_IrBlock_swap_in_at(vx_IrBlock *block, size_t a, size_t b); +void vx_IrBlock_swap_out_at(vx_IrBlock *block, size_t a, size_t b); +void vx_IrBlock_remove_out_at(vx_IrBlock *block, size_t id); -bool irblock_var_used(const SsaBlock *block, SsaVar var); +bool vx_IrBlock_var_used(const vx_IrBlock *block, vx_IrVar var); -void irblock_dump(const SsaBlock *block, FILE *out, size_t indent); +void vx_IrBlock_dump(const vx_IrBlock *block, FILE *out, size_t indent); typedef struct { enum { - SSA_VAL_IMM_INT, - SSA_VAL_IMM_FLT, - SSA_VAL_VAR, - SSA_VAL_BLOCK, + VX_IR_VALIMM_INT, + VX_IR_VALIMM_FLT, + VX_IR_VALVAR, + VX_IR_VALBLOCK, + VX_IR_VALUNINIT, } type; union { long long imm_int; double imm_flt; - SsaVar var; - SsaBlock *block; + vx_IrVar var; + vx_IrBlock *block; }; -} SsaValue; +} vx_IrValue; -SsaValue irvalue_clone(SsaValue value); -void irvalue_dump(SsaValue value, FILE *out, size_t indent); +vx_IrValue vx_IrValue_clone(vx_IrValue value); +void vx_IrValue_dump(vx_IrValue value, FILE *out, size_t indent); -SsaOp *irblock_finddecl_var(const SsaBlock *block, SsaVar var); +vx_IrOp *vx_IrBlock_find_var_decl(const vx_IrBlock *block, vx_IrVar var); /** returns true if static eval ok; only touches dest if true */ -bool irblock_staticeval_var(const SsaBlock *block, SsaVar var, SsaValue *dest); -bool irblock_mightbe_var(const SsaBlock *block, SsaVar var, SsaValue v); -bool irblock_alwaysis_var(const SsaBlock *block, SsaVar var, SsaValue v); -void irblock_staticeval(SsaBlock *block, SsaValue *v); +bool vx_IrBlock_eval_var(const vx_IrBlock *block, vx_IrVar var, vx_IrValue *dest); +bool vx_Irblock_mightbe_var(const vx_IrBlock *block, vx_IrVar var, vx_IrValue v); +bool vx_Irblock_alwaysis_var(const vx_IrBlock *block, vx_IrVar var, vx_IrValue v); +void vx_Irblock_eval(vx_IrBlock *block, vx_IrValue *v); typedef enum { - SSA_NAME_OPERAND_A, - SSA_NAME_OPERAND_B, + VX_IR_NAME_OPERAND_A, + VX_IR_NAME_OPERAND_B, - SSA_NAME_BLOCK, - SSA_NAME_VALUE, - SSA_NAME_COND, + VX_IR_NAME_BLOCK, + VX_IR_NAME_VALUE, + VX_IR_NAME_ADDR, + VX_IR_NAME_COND, + VX_IR_NAME_VAR, - SSA_NAME_COND_THEN, - SSA_NAME_COND_ELSE, + VX_IR_NAME_COND_THEN, + VX_IR_NAME_COND_ELSE, - SSA_NAME_LOOP_DO, - SSA_NAME_LOOP_START, - SSA_NAME_LOOP_ENDEX, - SSA_NAME_LOOP_STRIDE, + VX_IR_NAME_LOOP_DO, + VX_IR_NAME_LOOP_START, + VX_IR_NAME_LOOP_ENDEX, + VX_IR_NAME_LOOP_STRIDE, - SSA_NAME_ALTERNATIVE_A, - SSA_NAME_ALTERNATIVE_B, -} SsaName; + VX_IR_NAME_ALTERNATIVE_A, + VX_IR_NAME_ALTERNATIVE_B, +} vx_IrName; -extern const char *irname_str[]; +extern const char *vx_IrName_str[]; typedef struct { - SsaName name; - SsaValue val; -} SsaNamedValue; + vx_IrName name; + vx_IrValue val; +} vx_IrNamedValue; -static SsaNamedValue irnamedvalue_create(SsaName name, SsaValue v) { - return (SsaNamedValue) { +static vx_IrNamedValue vx_IrNamedValue_create(vx_IrName name, vx_IrValue v) { + return (vx_IrNamedValue) { .name = name, .val = v, }; } -static SsaNamedValue irnamedvalue_clone(SsaNamedValue val) { - return irnamedvalue_create(val.name, irvalue_clone(val.val)); -} -void irnamedvalue_rename(SsaNamedValue *value, SsaName newn); -void irnamedvalue_destroy(SsaNamedValue v); +void vx_IrNamedValue_destroy(vx_IrNamedValue v); typedef enum { - SSA_OP_NOP = 0, - SSA_OP_IMM, // "val" - SSA_OP_FLATTEN_PLEASE, // "block" + VX_IR_OP_NOP = 0, + VX_IR_OP_IMM, // "val" + VX_IR_OP_FLATTEN_PLEASE, // "block" // convert /** for pointers only! */ - SSA_OP_REINTERPRET, // "val" - SSA_OP_ZEROEXT, // "val" - SSA_OP_SIGNEXT, // "val" - SSA_OP_TOFLT, // "val" - SSA_OP_FROMFLT, // "val" - SSA_OP_BITCAST, // "val" - + VX_IR_OP_REINTERPRET, // "val" + VX_IR_OP_ZEROEXT, // "val" + VX_IR_OP_SIGNEXT, // "val" + VX_IR_OP_TOFLT, // "val" + VX_IR_OP_FROMFLT, // "val" + VX_IR_OP_BITCAST, // "val" + + // mem + VX_IR_OP_LOAD, // "addr" + VX_IR_OP_LOAD_VOLATILE, // "addr" + VX_IR_OP_STORE, // "addr", "val" + VX_IR_OP_STORE_VOLATILE, // "addr", "val" + VX_IR_OP_PLACE, // "var" + // arithm - SSA_OP_ADD, // "a", "b" - SSA_OP_SUB, // "a", "b" - SSA_OP_MUL, // "a", "b" - SSA_OP_DIV, // "a", "b" - SSA_OP_MOD, // "a", "b" + VX_IR_OP_ADD, // "a", "b" + VX_IR_OP_SUB, // "a", "b" + VX_IR_OP_MUL, // "a", "b" + VX_IR_OP_DIV, // "a", "b" + VX_IR_OP_MOD, // "a", "b" // compare - SSA_OP_GT, // "a", "b" - SSA_OP_GTE, // "a", "b" - SSA_OP_LT, // "a", "b" - SSA_OP_LTE, // "a", "b" - SSA_OP_EQ, // "a", "b" - SSA_OP_NEQ, // "a", "b" + VX_IR_OP_GT, // "a", "b" + VX_IR_OP_GTE, // "a", "b" + VX_IR_OP_LT, // "a", "b" + VX_IR_OP_LTE, // "a", "b" + VX_IR_OP_EQ, // "a", "b" + VX_IR_OP_NEQ, // "a", "b" // boolean - SSA_OP_NOT, // "val" - SSA_OP_AND, // "val" - SSA_OP_OR, // "val" + VX_IR_OP_NOT, // "val" + VX_IR_OP_AND, // "val" + VX_IR_OP_OR, // "val" // bitwise boolean - SSA_OP_BITWISE_NOT, // "val" - SSA_OP_BITWISE_AND, // "a", "b" - SSA_OP_BITIWSE_OR, // "a", "b" + VX_IR_OP_BITWISE_NOT, // "val" + VX_IR_OP_BITWISE_AND, // "a", "b" + VX_IR_OP_BITIWSE_OR, // "a", "b" // misc - SSA_OP_SHL, // "a", "b" - SSA_OP_SHR, // "a", "b" + VX_IR_OP_SHL, // "a", "b" + VX_IR_OP_SHR, // "a", "b" // basic loop - SSA_OP_FOR, // "start": counter, "cond": (counter,States)->continue?, "stride": int, "do": (counter, States)->States, States - SSA_OP_INFINITE, // "start": counter, "stride": int, "do": (counter, States)->States, States - SSA_OP_WHILE, // "cond": (States)->bool, "do": (counter)->States, States - SSA_OP_CONTINUE, - SSA_OP_BREAK, + VX_IR_OP_FOR, // "start": counter, "cond": (counter,States)->continue?, "stride": int, "do": (counter, States)->States, States + VX_IR_OP_INFINITE, // "start": counter, "stride": int, "do": (counter, States)->States, States + VX_IR_OP_WHILE, // "cond": (States)->bool, "do": (counter)->States, States + VX_IR_OP_CONTINUE, + VX_IR_OP_BREAK, // advanced loop - SSA_OP_FOREACH, // "arr": array[T], "start": counter, "endEx": counter, "stride": int, "do": (T, States)->States, States - SSA_OP_FOREACH_UNTIL, // "arr": array[T], "start": counter, "cond": (T,States)->break?, "stride": int, "do": (T, States)->States, States - SSA_OP_REPEAT, // "start": counter, "endEx": counter, "stride": int, "do": (counter, States)->States, States - CIR_OP_CFOR, // "start": ()->., "cond": ()->bool, "end": ()->., "do": (counter)->. + VX_IR_OP_FOREACH, // "arr": array[T], "start": counter, "endEx": counter, "stride": int, "do": (T, States)->States, States + VX_IR_OP_FOREACH_UNTIL, // "arr": array[T], "start": counter, "cond": (T,States)->break?, "stride": int, "do": (T, States)->States, States + VX_IR_OP_REPEAT, // "start": counter, "endEx": counter, "stride": int, "do": (counter, States)->States, States + CVX_IR_OP_CFOR, // "start": ()->., "cond": ()->bool, "end": ()->., "do": (counter)->. // conditional - SSA_OP_IF, // "cond": bool, "then": ()->R, ("else": ()->R) + VX_IR_OP_IF, // "cond": bool, "then": ()->R, ("else": ()->R) - SSA_OP____END, -} SsaOpType; + VX_IR_OP____END, +} vx_IrOpType; -#define SSAOPTYPE_LEN (SSA_OP____END - SSA_OP_NOP) +#define SSAOPTYPE_LEN (VX_IR_OP____END - VX_IR_OP_NOP) -extern const char *iroptype_names[SSAOPTYPE_LEN]; +extern const char *vx_IrOpType_names[SSAOPTYPE_LEN]; typedef struct { - SsaVar var; - SsaType type; -} SsaTypedVar; + vx_IrVar var; + vx_IrType type; +} vx_IrTypedVar; -struct SsaOp_s { - SsaType *types; - size_t types_len; +struct vx_IrOp_s { + vx_IrType *types; + size_t types_len; - SsaTypedVar *outs; - size_t outs_len; + vx_IrTypedVar *outs; + size_t outs_len; - SsaNamedValue *params; - size_t params_len; + vx_IrNamedValue *params; + size_t params_len; - SsaValue *states; - size_t states_len; + vx_IrValue *states; + size_t states_len; - SsaBlock *parent; - SsaOpType id; + vx_IrBlock *parent; + vx_IrOpType id; }; -void irop_dump(const SsaOp *op, FILE *out, size_t indent); +void vx_IrOp_dump(const vx_IrOp *op, FILE *out, size_t indent); typedef struct { - const SsaBlock *block; + const vx_IrBlock *block; size_t start; size_t end; -} SsaView; +} vx_IrView; -static SsaView irview_of_single(const SsaBlock *block, size_t index) { - return (SsaView) { +static vx_IrView vx_IrView_of_single(const vx_IrBlock *block, size_t index) { + return (vx_IrView) { .block = block, .start = index, .end = index + 1, }; } -static SsaView irview_of_all(const SsaBlock *block) { - return (SsaView) { +static vx_IrView vx_IrView_of_all(const vx_IrBlock *block) { + return (vx_IrView) { .block = block, .start = 0, .end = block->ops_len, }; } -static size_t irview_len(const SsaView view) { +static size_t vx_IrView_len(const vx_IrView view) { return view.end - view.start; } /** returns true if found */ -bool irview_find(SsaView *view, SsaOpType type); -SsaView irview_replace(SsaBlock *viewblock, SsaView view, const SsaOp *ops, size_t ops_len); -static SsaView irview_drop(const SsaView view, const size_t count) { - SsaView out = view; +bool vx_IrView_find(vx_IrView *view, vx_IrOpType type); +vx_IrView vx_IrView_replace(vx_IrBlock *viewblock, vx_IrView view, const vx_IrOp *ops, size_t ops_len); +static vx_IrView vx_IrView_drop(const vx_IrView view, const size_t count) { + vx_IrView out = view; out.block = view.block; out.start = view.start + count; if (out.start > out.end) out.start = out.end; return out; } -static const SsaOp *irview_take(const SsaView view) { +static const vx_IrOp *vx_IrView_take(const vx_IrView view) { return &view.block->ops[view.start]; } -void irview_rename_var(SsaView view, SsaBlock *block, SsaVar old, SsaVar newv); -void irview_substitude_var(SsaView view, SsaBlock *block, SsaVar old, SsaValue newv); -static bool irview_has_next(const SsaView view) { +void vx_IrView_rename_var(vx_IrView view, vx_IrBlock *block, vx_IrVar old, vx_IrVar newv); +void vx_IrView_substitute_var(vx_IrView view, vx_IrBlock *block, vx_IrVar old, vx_IrValue newv); +static bool vx_IrView_has_next(const vx_IrView view) { return view.start < view.end; } -SsaOp *irblock_traverse(SsaView *current); -void irview_deep_traverse(SsaView top, void (*callback)(SsaOp *op, void *data), void *data); - -SsaValue *irop_param(const SsaOp *op, SsaName name); - -void irop_init(SsaOp *op, SsaOpType type, SsaBlock *parent); -void irop_add_type(SsaOp *op, SsaType type); -void irop_add_out(SsaOp *op, SsaVar v, SsaType t); -void irop_add_param_s(SsaOp *op, SsaName name, SsaValue val); -void irop_add_param(SsaOp *op, SsaNamedValue p); -static void irop_steal_param(SsaOp *dest, const SsaOp *src, SsaName param) { - irop_add_param_s(dest, param, irvalue_clone(*irop_param(src, param))); +void vx_IrView_deep_traverse(vx_IrView top, void (*callback)(vx_IrOp *op, void *data), void *data); + +vx_IrValue *vx_IrOp_param(const vx_IrOp *op, vx_IrName name); + +void vx_IrOp_init(vx_IrOp *op, vx_IrOpType type, vx_IrBlock *parent); +void vx_IrOp_add_type(vx_IrOp *op, vx_IrType type); +void vx_IrOp_add_out(vx_IrOp *op, vx_IrVar v, vx_IrType t); +void vx_IrOp_add_param_s(vx_IrOp *op, vx_IrName name, vx_IrValue val); +void vx_IrOp_add_param(vx_IrOp *op, vx_IrNamedValue p); +static void vx_IrOp_steal_param(vx_IrOp *dest, const vx_IrOp *src, vx_IrName param) { + vx_IrOp_add_param_s(dest, param, vx_IrValue_clone(*vx_IrOp_param(src, param))); } -void irop_remove_params(SsaOp *op); -void irop_remove_out_at(SsaOp *op, size_t id); -void irop_remove_param_at(SsaOp *op, size_t id); -void irop_steal_outs(SsaOp *dest, const SsaOp *src); -void irop_destroy(SsaOp *op); -bool irop_anyparam_hasvar(SsaOp *op, SsaVar var); -void irop_remove_state_at(SsaOp *op, size_t id); -bool irop_is_pure(SsaOp *op); -void irop_steal_states(SsaOp *dest, const SsaOp *src); - -struct SsaStaticIncrement { +void vx_IrOp_remove_params(vx_IrOp *op); +void vx_IrOp_remove_out_at(vx_IrOp *op, size_t id); +void vx_IrOp_remove_param_at(vx_IrOp *op, size_t id); +void vx_IrOp_steal_outs(vx_IrOp *dest, const vx_IrOp *src); +void vx_IrOp_destroy(vx_IrOp *op); +void vx_IrOp_remove_state_at(vx_IrOp *op, size_t id); +bool vx_IrOp_is_volatile(vx_IrOp *op); +void vx_IrOp_steal_states(vx_IrOp *dest, const vx_IrOp *src); + +struct IrStaticIncrement { bool detected; - SsaVar var; + vx_IrVar var; long long by; }; -struct SsaStaticIncrement irop_detect_static_increment(const SsaOp *op); +struct IrStaticIncrement vx_IrOp_detect_static_increment(const vx_IrOp *op); -SsaOp *irblock_inside_out_vardecl_before(const SsaBlock *block, SsaVar var, size_t before); -bool irblock_is_pure(const SsaBlock *block); +vx_IrOp *vx_IrBlock_inside_out_vardecl_before(const vx_IrBlock *block, vx_IrVar var, size_t before); +bool vx_IrBlock_is_volatile(const vx_IrBlock *block); -#endif //SSA_H +#endif //IR_H diff --git a/ir/ir.md b/ir/ir.md deleted file mode 100644 index 95b77e7..0000000 --- a/ir/ir.md +++ /dev/null @@ -1,37 +0,0 @@ -# VXCC IR -SSA(-like?) IR - -## Block -Has inputs, outputs and operations - -## Operation -Has multiple inputs and a variable amount of outputs - -## Ifs -``` -u32 %0 = 1; -u32 %1, u32 %2 = if cond=%0 then=(){ - ^ 4,5; -} else=(){ - ^ 8,9; -}; -``` -Is that weird? yes - -Is that useful for optimizations? extremely - -## Loops -``` -for init=0 cond=(%0){ u32 %1 = lt a=%0 b=10; ^ %1; } stride=1 do=(%0){ - # something with %0 -} -``` -but there is also foreach and repeat -don't worry, the optimizer converts those automatically -``` -repeat start=0 end=9 stride=1 do=(%0){ - # something with %0 -} -``` - -Loops can have states. \ No newline at end of file diff --git a/ir/opt.h b/ir/opt.h index f501fb2..d0beb93 100644 --- a/ir/opt.h +++ b/ir/opt.h @@ -3,42 +3,42 @@ #include "ir.h" -void opt_loop_simplify(SsaView view, SsaBlock *block); -void opt_comparisions(SsaView view, SsaBlock *block); -void opt_constant_eval(SsaView view, SsaBlock *block); -void opt_inline_vars(SsaView view, SsaBlock *block); -void opt_join_compute(SsaView view, SsaBlock *block); -void opt_reduce_if(SsaView view, SsaBlock *block); -void opt_reduce_loops(SsaView view, SsaBlock *block); +void vx_opt_loop_simplify(vx_IrView view, vx_IrBlock *block); +void vx_opt_comparisions(vx_IrView view, vx_IrBlock *block); +void vx_opt_constant_eval(vx_IrView view, vx_IrBlock *block); +void vx_opt_inline_vars(vx_IrView view, vx_IrBlock *block); +void vx_opt_join_compute(vx_IrView view, vx_IrBlock *block); +void vx_opt_reduce_if(vx_IrView view, vx_IrBlock *block); +void vx_opt_reduce_loops(vx_IrView view, vx_IrBlock *block); -// CALL ONLY ON ROOT BLOCKS: -void opt_remove_vars(SsaBlock *block); +/** Can only be applied to root blocks */ +void vx_opt_remove_vars(vx_IrBlock *block); #define CONSTEVAL_ITER 6 -static void opt_pre(SsaBlock *block) { +static void opt_pre(vx_IrBlock *block) { // place immediates into params - opt_inline_vars(irview_of_all(block), block); + vx_opt_inline_vars(vx_IrView_of_all(block), block); for (int i = 0; i < CONSTEVAL_ITER; i ++) { // evaluate constants - opt_constant_eval(irview_of_all(block), block); + vx_opt_constant_eval(vx_IrView_of_all(block), block); // place results into params - opt_inline_vars(irview_of_all(block), block); + vx_opt_inline_vars(vx_IrView_of_all(block), block); } if (block->is_root) - opt_remove_vars(block); + vx_opt_remove_vars(block); - opt_comparisions(irview_of_all(block), block); + vx_opt_comparisions(vx_IrView_of_all(block), block); } -static void opt(SsaBlock *block) { +static void opt(vx_IrBlock *block) { opt_pre(block); - opt_join_compute(irview_of_all(block), block); - opt_reduce_if(irview_of_all(block), block); + vx_opt_join_compute(vx_IrView_of_all(block), block); + vx_opt_reduce_if(vx_IrView_of_all(block), block); opt_pre(block); - opt_reduce_loops(irview_of_all(block), block); - opt_loop_simplify(irview_of_all(block), block); + vx_opt_reduce_loops(vx_IrView_of_all(block), block); + vx_opt_loop_simplify(vx_IrView_of_all(block), block); } #endif //OPT_H diff --git a/ir/opt/comparisions.c b/ir/opt/comparisions.c index 1bd8346..5115851 100644 --- a/ir/opt/comparisions.c +++ b/ir/opt/comparisions.c @@ -6,46 +6,49 @@ * `constant < a` -> `a > constant` * `constant > a` -> `a < constant` */ -void opt_comparisions(SsaView view, SsaBlock *block) { +void vx_opt_comparisions(view, block) + vx_IrView view; + vx_IrBlock *block; +{ for (size_t i = view.start; i < view.end; i ++) { - SsaOp *op = &block->ops[i]; + vx_IrOp *op = &block->ops[i]; switch (op->id) { - case SSA_OP_LTE: { - SsaValue *b = irop_param(op, SSA_NAME_OPERAND_B); - if (b->type == SSA_VAL_IMM_INT) { + case VX_IR_OP_LTE: { + vx_IrValue *b = vx_IrOp_param(op, VX_IR_NAME_OPERAND_B); + if (b->type == VX_IR_VALIMM_INT) { b->imm_int ++; - op->id = SSA_OP_LT; + op->id = VX_IR_OP_LT; } } break; - case SSA_OP_GTE: { - SsaValue *b = irop_param(op, SSA_NAME_OPERAND_B); - if (b->type == SSA_VAL_IMM_INT) { + case VX_IR_OP_GTE: { + vx_IrValue *b = vx_IrOp_param(op, VX_IR_NAME_OPERAND_B); + if (b->type == VX_IR_VALIMM_INT) { b->imm_int --; - op->id = SSA_OP_GT; + op->id = VX_IR_OP_GT; } } break; - case SSA_OP_LT: { - SsaValue *a = irop_param(op, SSA_NAME_OPERAND_A); - SsaValue *b = irop_param(op, SSA_NAME_OPERAND_B); - if (a->type == SSA_VAL_IMM_INT) { - const SsaValue tmp = *a; + case VX_IR_OP_LT: { + vx_IrValue *a = vx_IrOp_param(op, VX_IR_NAME_OPERAND_A); + vx_IrValue *b = vx_IrOp_param(op, VX_IR_NAME_OPERAND_B); + if (a->type == VX_IR_VALIMM_INT) { + const vx_IrValue tmp = *a; *a = *b; *b = tmp; - op->id = SSA_OP_GT; + op->id = VX_IR_OP_GT; } } break; - case SSA_OP_GT: { - SsaValue *a = irop_param(op, SSA_NAME_OPERAND_A); - SsaValue *b = irop_param(op, SSA_NAME_OPERAND_B); - if (a->type == SSA_VAL_IMM_INT) { - const SsaValue tmp = *a; + case VX_IR_OP_GT: { + vx_IrValue *a = vx_IrOp_param(op, VX_IR_NAME_OPERAND_A); + vx_IrValue *b = vx_IrOp_param(op, VX_IR_NAME_OPERAND_B); + if (a->type == VX_IR_VALIMM_INT) { + const vx_IrValue tmp = *a; *a = *b; *b = tmp; - op->id = SSA_OP_LT; + op->id = VX_IR_OP_LT; } } break; diff --git a/ir/opt/constant_eval.c b/ir/opt/constant_eval.c index 4ae5a4b..0c4c9b2 100644 --- a/ir/opt/constant_eval.c +++ b/ir/opt/constant_eval.c @@ -2,136 +2,139 @@ #include -void opt_constant_eval(SsaView view, SsaBlock *block) { +void vx_opt_constant_eval(view, block) + vx_IrView view; + vx_IrBlock *block; +{ assert(view.block == block); - while (irview_has_next(view)) { + while (vx_IrView_has_next(view)) { // "unsafe", but we own the underlying block anyways - SsaOp *op = (SsaOp *) irview_take(view); + vx_IrOp *op = (vx_IrOp *) vx_IrView_take(view); #define BINARY(what) { \ - SsaValue *a = irop_param(op, SSA_NAME_OPERAND_A); \ - SsaValue *b = irop_param(op, SSA_NAME_OPERAND_B); \ - irblock_staticeval(block, a); \ - irblock_staticeval(block, b); \ - \ - if (a->type == SSA_VAL_IMM_INT && b->type == SSA_VAL_IMM_INT) { \ - op->id = SSA_OP_IMM; \ - irop_remove_params(op); \ - irop_add_param_s(op, SSA_NAME_VALUE, (SsaValue) { \ - .type = SSA_VAL_IMM_INT, \ - .imm_int = a->imm_int what b->imm_int \ - }); \ - } else if (a->type == SSA_VAL_IMM_FLT && b->type == SSA_VAL_IMM_FLT) { \ - op->id = SSA_OP_IMM; \ - irop_remove_params(op); \ - irop_add_param_s(op, SSA_NAME_VALUE, (SsaValue) { \ - .type = SSA_VAL_IMM_FLT, \ - .imm_flt = a->imm_flt + b->imm_flt \ - }); \ - } \ -} + vx_IrValue *a = vx_IrOp_param(op, VX_IR_NAME_OPERAND_A); \ + vx_IrValue *b = vx_IrOp_param(op, VX_IR_NAME_OPERAND_B); \ + vx_Irblock_eval(block, a); \ + vx_Irblock_eval(block, b); \ + \ + if (a->type == VX_IR_VALIMM_INT && b->type == VX_IR_VALIMM_INT) { \ + op->id = VX_IR_OP_IMM; \ + vx_IrOp_remove_params(op); \ + vx_IrOp_add_param_s(op, VX_IR_NAME_VALUE, (vx_IrValue) { \ + .type = VX_IR_VALIMM_INT, \ + .imm_int = a->imm_int what b->imm_int \ + }); \ + } else if (a->type == VX_IR_VALIMM_FLT && b->type == VX_IR_VALIMM_FLT) { \ + op->id = VX_IR_OP_IMM; \ + vx_IrOp_remove_params(op); \ + vx_IrOp_add_param_s(op, VX_IR_NAME_VALUE, (vx_IrValue) { \ + .type = VX_IR_VALIMM_FLT, \ + .imm_flt = a->imm_flt + b->imm_flt \ + }); \ + } \ + } #define UNARY(what) { \ - SsaValue *val = irop_param(op, SSA_NAME_VALUE); \ - irblock_staticeval(block, val); \ - if (val->type == SSA_VAL_IMM_INT) { \ - op->id = SSA_OP_IMM; \ - *val = (SsaValue) { \ - .type = SSA_VAL_IMM_INT, \ - .imm_int = what val->imm_int \ - }; \ - } else if (val->type == SSA_VAL_IMM_FLT) { \ - op->id = SSA_OP_IMM; \ - *val = (SsaValue) { \ - .type = SSA_VAL_IMM_FLT, \ - .imm_flt = what val->imm_flt \ - }; \ - } \ -} - + vx_IrValue *val = vx_IrOp_param(op, VX_IR_NAME_VALUE); \ + vx_Irblock_eval(block, val); \ + if (val->type == VX_IR_VALIMM_INT) { \ + op->id = VX_IR_OP_IMM; \ + *val = (vx_IrValue) { \ + .type = VX_IR_VALIMM_INT, \ + .imm_int = what val->imm_int \ + }; \ + } else if (val->type == VX_IR_VALIMM_FLT) { \ + op->id = VX_IR_OP_IMM; \ + *val = (vx_IrValue) { \ + .type = VX_IR_VALIMM_FLT, \ + .imm_flt = what val->imm_flt \ + }; \ + } \ + } + switch (op->id) { - case SSA_OP_ADD: + case VX_IR_OP_ADD: BINARY(+); break; - case SSA_OP_SUB: + case VX_IR_OP_SUB: BINARY(-); break; - case SSA_OP_MUL: + case VX_IR_OP_MUL: BINARY(*); break; - case SSA_OP_DIV: + case VX_IR_OP_DIV: BINARY(/); break; - case SSA_OP_MOD: + case VX_IR_OP_MOD: BINARY(%); break; - case SSA_OP_AND: + case VX_IR_OP_AND: BINARY(&&); break; - case SSA_OP_OR: + case VX_IR_OP_OR: BINARY(||); break; - case SSA_OP_BITWISE_AND: + case VX_IR_OP_BITWISE_AND: BINARY(&); break; - case SSA_OP_BITIWSE_OR: + case VX_IR_OP_BITIWSE_OR: BINARY(|); break; - case SSA_OP_SHL: + case VX_IR_OP_SHL: BINARY(<<); break; - case SSA_OP_SHR: + case VX_IR_OP_SHR: BINARY(>>); break; - case SSA_OP_NOT: + case VX_IR_OP_NOT: UNARY(!); break; - case SSA_OP_BITWISE_NOT: { - SsaValue *val = irop_param(op, SSA_NAME_VALUE); - irblock_staticeval(block, val); - if (val->type == SSA_VAL_IMM_INT) { - op->id = SSA_OP_IMM; - *val = (SsaValue) { - .type = SSA_VAL_IMM_INT, + case VX_IR_OP_BITWISE_NOT: { + vx_IrValue *val = vx_IrOp_param(op, VX_IR_NAME_VALUE); + vx_Irblock_eval(block, val); + if (val->type == VX_IR_VALIMM_INT) { + op->id = VX_IR_OP_IMM; + *val = (vx_IrValue) { + .type = VX_IR_VALIMM_INT, .imm_int = ~val->imm_int }; } } break; - case SSA_OP_EQ: + case VX_IR_OP_EQ: BINARY(==); break; - case SSA_OP_NEQ: + case VX_IR_OP_NEQ: BINARY(!=); break; - case SSA_OP_LT: + case VX_IR_OP_LT: BINARY(<); break; - case SSA_OP_LTE: + case VX_IR_OP_LTE: BINARY(<=); break; - case SSA_OP_GT: + case VX_IR_OP_GT: BINARY(>); break; - case SSA_OP_GTE: + case VX_IR_OP_GTE: BINARY(>=); break; @@ -139,6 +142,6 @@ void opt_constant_eval(SsaView view, SsaBlock *block) { break; } - view = irview_drop(view, 1); + view = vx_IrView_drop(view, 1); } } diff --git a/ir/opt/inline_vars.c b/ir/opt/inline_vars.c index 3c2eab3..9fc2542 100644 --- a/ir/opt/inline_vars.c +++ b/ir/opt/inline_vars.c @@ -1,19 +1,25 @@ #include "../opt.h" -static void trav(SsaOp *op, void *data) { - SsaBlock *block = data; +static void trav(op, data) + vx_IrOp *op; + void *data; +{ + vx_IrBlock *block = data; - if (op->id != SSA_OP_IMM) + if (op->id != VX_IR_OP_IMM) return; - const SsaValue value = *irop_param(op, SSA_NAME_VALUE); + const vx_IrValue value = *vx_IrOp_param(op, VX_IR_NAME_VALUE); for (size_t i = 0; i < op->outs_len; i ++) { - const SsaVar out = op->outs[i].var; - irview_substitude_var(irview_of_all(block), block, out, value); + const vx_IrVar out = op->outs[i].var; + vx_IrView_substitute_var(vx_IrView_of_all(block), block, out, value); } } -void opt_inline_vars(SsaView view, SsaBlock *block) { - irview_deep_traverse(view, trav, block); +void vx_opt_inline_vars(view, block) + vx_IrView view; + vx_IrBlock *block; +{ + vx_IrView_deep_traverse(view, trav, block); } diff --git a/ir/opt/join_compute.c b/ir/opt/join_compute.c index 9384ec9..5591db3 100644 --- a/ir/opt/join_compute.c +++ b/ir/opt/join_compute.c @@ -2,25 +2,31 @@ #include #include -void opt_join_compute(SsaView view, SsaBlock *block) { +/** + * Find identical computations and join them + */ +void vx_opt_join_compute(view, block) + vx_IrView view; + vx_IrBlock *block; +{ assert(view.block == block); for (size_t i = 0; i < block->ops_len; i ++) { - SsaOp *op = &block->ops[i]; + vx_IrOp *op = &block->ops[i]; size_t j = i; while (j --> 0) { - SsaOp *prev = &block->ops[j]; + vx_IrOp *prev = &block->ops[j]; - if (prev->id != op->id || !irop_is_pure(op) || prev->params_len != op->params_len || prev->outs_len == 0) + if (prev->id != op->id || vx_IrOp_is_volatile(op) || prev->params_len != op->params_len || prev->outs_len == 0) continue; - if (memcmp(prev->params, op->params, sizeof(SsaNamedValue) * op->params_len) != 0) + if (memcmp(prev->params, op->params, sizeof(vx_IrNamedValue) * op->params_len) != 0) continue; - op->id = SSA_OP_IMM; - irop_remove_params(op); - irop_add_param_s(op, SSA_NAME_VALUE, (SsaValue) { .type = SSA_VAL_VAR, .var = prev->outs[0].var }); + op->id = VX_IR_OP_IMM; + vx_IrOp_remove_params(op); + vx_IrOp_add_param_s(op, VX_IR_NAME_VALUE, (vx_IrValue) { .type = VX_IR_VALVAR, .var = prev->outs[0].var }); break; } diff --git a/ir/opt/loop_simplify.c b/ir/opt/loop_simplify.c index e906e9d..6c52b32 100644 --- a/ir/opt/loop_simplify.c +++ b/ir/opt/loop_simplify.c @@ -1,61 +1,64 @@ #include "../opt.h" -void opt_loop_simplify(SsaView view, SsaBlock *block) { - while (irview_find(&view, SSA_OP_FOR)) { - SsaOp *op = (SsaOp *) irview_take(view); +void vx_opt_loop_simplify(view, block) + vx_IrView view; + vx_IrBlock *block; +{ + while (vx_IrView_find(&view, VX_IR_OP_FOR)) { + vx_IrOp *op = (vx_IrOp *) vx_IrView_take(view); - SsaBlock *cond = irop_param(op, SSA_NAME_COND)->block; + vx_IrBlock *cond = vx_IrOp_param(op, VX_IR_NAME_COND)->block; opt(cond); // ! - const SsaVar condVar = cond->outs[0]; + const vx_IrVar condVar = cond->outs[0]; // if it will always we 0, we optimize it out - if (irblock_alwaysis_var(cond, condVar, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 0 })) { - irview_replace(block, view, NULL, 0); + if (vx_Irblock_alwaysis_var(cond, condVar, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 0 })) { + vx_IrView_replace(block, view, NULL, 0); goto next; } - opt(irop_param(op, SSA_NAME_LOOP_DO)->block); + opt(vx_IrOp_param(op, VX_IR_NAME_LOOP_DO)->block); // if it will never be 0 (not might be 0), it is always true => infinite loop - if (!irblock_mightbe_var(cond, condVar, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 0 })) { - SsaOp new; - irop_init(&new, SSA_OP_INFINITE, block); - irop_steal_param(&new, op, SSA_NAME_LOOP_START); - irop_steal_param(&new, op, SSA_NAME_LOOP_DO); - irop_steal_param(&new, op, SSA_NAME_LOOP_STRIDE); - irop_steal_states(&new, op); - irop_steal_outs(&new, op); + if (!vx_Irblock_mightbe_var(cond, condVar, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 0 })) { + vx_IrOp new; + vx_IrOp_init(&new, VX_IR_OP_INFINITE, block); + vx_IrOp_steal_param(&new, op, VX_IR_NAME_LOOP_START); + vx_IrOp_steal_param(&new, op, VX_IR_NAME_LOOP_DO); + vx_IrOp_steal_param(&new, op, VX_IR_NAME_LOOP_STRIDE); + vx_IrOp_steal_states(&new, op); + vx_IrOp_steal_outs(&new, op); - irview_replace(block, view, &new, 1); + vx_IrView_replace(block, view, &new, 1); goto next; } // if it is a less than, we can do a repeat - if (cond->ops_len > 0 && cond->ops[0].id == SSA_OP_LT) { + if (cond->ops_len > 0 && cond->ops[0].id == VX_IR_OP_LT) { bool break2 = false; do { - const SsaValue *a = irop_param(&cond->ops[0], SSA_NAME_OPERAND_A); + const vx_IrValue *a = vx_IrOp_param(&cond->ops[0], VX_IR_NAME_OPERAND_A); // require it to be the counter - if (a->type != SSA_VAL_VAR) + if (a->type != VX_IR_VALVAR) break; if (a->var != cond->ins[0]) break; if (cond->ops[0].outs[0].var != cond->outs[0]) break; - const SsaValue b = irvalue_clone(*irop_param(&cond->ops[0], SSA_NAME_OPERAND_B)); + const vx_IrValue b = vx_IrValue_clone(*vx_IrOp_param(&cond->ops[0], VX_IR_NAME_OPERAND_B)); - SsaOp new; - irop_init(&new, SSA_OP_REPEAT, block); - irop_steal_param(&new, op, SSA_NAME_LOOP_DO); - irop_steal_param(&new, op, SSA_NAME_LOOP_START); - irop_add_param_s(&new, SSA_NAME_LOOP_ENDEX, b); - irop_steal_param(&new, op, SSA_NAME_LOOP_STRIDE); - irop_steal_states(&new, op); // steal all state init params - irop_steal_outs(&new, op); + vx_IrOp new; + vx_IrOp_init(&new, VX_IR_OP_REPEAT, block); + vx_IrOp_steal_param(&new, op, VX_IR_NAME_LOOP_DO); + vx_IrOp_steal_param(&new, op, VX_IR_NAME_LOOP_START); + vx_IrOp_add_param_s(&new, VX_IR_NAME_LOOP_ENDEX, b); + vx_IrOp_steal_param(&new, op, VX_IR_NAME_LOOP_STRIDE); + vx_IrOp_steal_states(&new, op); // steal all state init params + vx_IrOp_steal_outs(&new, op); // we probably do a bit of memory leaking here... *op = new; @@ -66,6 +69,6 @@ void opt_loop_simplify(SsaView view, SsaBlock *block) { } next: - view = irview_drop(view, 1); + view = vx_IrView_drop(view, 1); } } diff --git a/ir/opt/reduce_if.c b/ir/opt/reduce_if.c index 59394b9..339ade2 100644 --- a/ir/opt/reduce_if.c +++ b/ir/opt/reduce_if.c @@ -2,57 +2,60 @@ #include "../opt.h" -void opt_reduce_if(SsaView view, SsaBlock *block) { - const SsaBlock *root = irblock_root(block); +void vx_opt_reduce_if(view, block) + vx_IrView view; + vx_IrBlock *block; +{ + const vx_IrBlock *root = vx_IrBlock_root(block); - while (irview_find(&view, SSA_OP_IF)) { - SsaOp *op = (SsaOp *) irview_take(view); + while (vx_IrView_find(&view, VX_IR_OP_IF)) { + vx_IrOp *op = (vx_IrOp *) vx_IrView_take(view); - SsaBlock *cond = irop_param(op, SSA_NAME_COND)->block; + vx_IrBlock *cond = vx_IrOp_param(op, VX_IR_NAME_COND)->block; opt(cond); // ! - const SsaVar condVar = cond->outs[0]; + const vx_IrVar condVar = cond->outs[0]; - SsaBlock *then = irop_param(op, SSA_NAME_COND_THEN)->block; + vx_IrBlock *then = vx_IrOp_param(op, VX_IR_NAME_COND_THEN)->block; opt(then); - SsaBlock *els = irop_param(op, SSA_NAME_COND_ELSE)->block; + vx_IrBlock *els = vx_IrOp_param(op, VX_IR_NAME_COND_ELSE)->block; opt(els); // if it will never be 0 (not might be 0), it is always true => only execute then block - if (!irblock_mightbe_var(cond, condVar, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 0 })) { + if (!vx_Irblock_mightbe_var(cond, condVar, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 0 })) { for (size_t i = 0; i < op->outs_len; i ++) { - const SsaVar out = op->outs[i].var; - irview_rename_var(irview_of_all(block), block, out, then->outs[i]); // does all the bookkeeping for us + const vx_IrVar out = op->outs[i].var; + vx_IrView_rename_var(vx_IrView_of_all(block), block, out, then->outs[i]); // does all the bookkeeping for us } - irview_replace(block, view, then->ops, then->ops_len); + vx_IrView_replace(block, view, then->ops, then->ops_len); free(then->ops); - view = irview_drop(view, then->ops_len); + view = vx_IrView_drop(view, then->ops_len); continue; } // if it will always we 0, only the else block will ever be executed - if (irblock_alwaysis_var(cond, condVar, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 0 })) { + if (vx_Irblock_alwaysis_var(cond, condVar, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 0 })) { for (size_t i = 0; i < op->outs_len; i ++) { - const SsaVar out = op->outs[i].var; - irview_rename_var(irview_of_all(block), block, out, els->outs[i]); // does all the bookkeeping for us + const vx_IrVar out = op->outs[i].var; + vx_IrView_rename_var(vx_IrView_of_all(block), block, out, els->outs[i]); // does all the bookkeeping for us } - irview_replace(block, view, els->ops, els->ops_len); + vx_IrView_replace(block, view, els->ops, els->ops_len); free(els->ops); - view = irview_drop(view, els->ops_len); + view = vx_IrView_drop(view, els->ops_len); continue; } for (size_t i = 0; i < op->outs_len; i ++) { - if (!irblock_var_used(root, op->outs[i].var)) { - irblock_remove_out_at(then, i); - irblock_remove_out_at(els, i); - irop_remove_out_at(op, i); + if (!vx_IrBlock_var_used(root, op->outs[i].var)) { + vx_IrBlock_remove_out_at(then, i); + vx_IrBlock_remove_out_at(els, i); + vx_IrOp_remove_out_at(op, i); i --; } } - view = irview_drop(view, 1); + view = vx_IrView_drop(view, 1); } } diff --git a/ir/opt/reduce_loops.c b/ir/opt/reduce_loops.c index e696980..f6b2cf4 100644 --- a/ir/opt/reduce_loops.c +++ b/ir/opt/reduce_loops.c @@ -29,28 +29,31 @@ * * But when the condition is always true, we need to make it an infinite loop! */ -void opt_reduce_loops(SsaView view, SsaBlock *block) { +void vx_opt_reduce_loops(view, block) + vx_IrView view; + vx_IrBlock *block; +{ assert(view.block == block); - while (irview_find(&view, SSA_OP_FOR)) { - SsaOp *op = (SsaOp *) irview_take(view); + while (vx_IrView_find(&view, VX_IR_OP_FOR)) { + vx_IrOp *op = (vx_IrOp *) vx_IrView_take(view); - if (op->id == SSA_OP_WHILE && op->outs_len > 0) { // "fast path" for when we don't even have states - SsaBlock **bdo = &irop_param(op, SSA_NAME_LOOP_DO)->block; - SsaBlock *newdo = *bdo; - SsaBlock **bcond = &irop_param(op, SSA_NAME_COND)->block; - SsaBlock *newcond = *bcond; + if (op->id == VX_IR_OP_WHILE && op->outs_len > 0) { // "fast path" for when we don't even have states + vx_IrBlock **bdo = &vx_IrOp_param(op, VX_IR_NAME_LOOP_DO)->block; + vx_IrBlock *newdo = *bdo; + vx_IrBlock **bcond = &vx_IrOp_param(op, VX_IR_NAME_COND)->block; + vx_IrBlock *newcond = *bcond; // TODO: if we detect multiple counters here, chose the one which is single present in the condition - SsaOp *incOp = NULL; + vx_IrOp *incOp = NULL; size_t stateId; - struct SsaStaticIncrement si; + struct IrStaticIncrement si; for (stateId = 0; stateId < op->outs_len; stateId ++) { bool found = false; for (size_t j = 0; j < newdo->ops_len; j ++) { incOp = &newdo->ops[j]; - si = irop_detect_static_increment(incOp); + si = vx_IrOp_detect_static_increment(incOp); if (si.detected && incOp->outs[0].var == op->outs[stateId].var && si.var == newcond->ins[stateId]) @@ -70,27 +73,28 @@ void opt_reduce_loops(SsaView view, SsaBlock *block) { *bcond = NULL; *bdo = NULL; - const SsaValue init = op->states[stateId]; + const vx_IrValue init = op->states[stateId]; // counter needs to be at pos 0 oviously - irblock_swap_state_at(newcond, stateId, 0); - irop_remove_state_at(op, stateId); + vx_IrBlock_swap_in_at(newcond, stateId, 0); + vx_IrBlock_swap_out_at(newcond, stateId, 0); + vx_IrOp_remove_state_at(op, stateId); - SsaOp new; - irop_init(&new, SSA_OP_FOR, block); - irop_add_param_s(&new, SSA_NAME_LOOP_START, init); - irop_add_param_s(&new, SSA_NAME_LOOP_STRIDE, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = si.by }); - irop_steal_states(&new, op); - irop_add_param_s(&new, SSA_NAME_COND, (SsaValue) { .type = SSA_VAL_BLOCK, .block = newcond }); - irop_add_param_s(&new, SSA_NAME_LOOP_DO, (SsaValue) { .type = SSA_VAL_BLOCK, .block = newdo }); + vx_IrOp new; + vx_IrOp_init(&new, VX_IR_OP_FOR, block); + vx_IrOp_add_param_s(&new, VX_IR_NAME_LOOP_START, init); + vx_IrOp_add_param_s(&new, VX_IR_NAME_LOOP_STRIDE, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = si.by }); + vx_IrOp_steal_states(&new, op); + vx_IrOp_add_param_s(&new, VX_IR_NAME_COND, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = newcond }); + vx_IrOp_add_param_s(&new, VX_IR_NAME_LOOP_DO, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = newdo }); - irop_destroy(incOp); - irop_init(incOp, SSA_OP_NOP, block); + vx_IrOp_destroy(incOp); + vx_IrOp_init(incOp, VX_IR_OP_NOP, block); - irop_destroy(op); - (void) irview_replace(block, view, &new, 1); + vx_IrOp_destroy(op); + (void) vx_IrView_replace(block, view, &new, 1); } - view = irview_drop(view, 1); + view = vx_IrView_drop(view, 1); } } diff --git a/ir/opt/remove_vars.c b/ir/opt/remove_vars.c index 054382c..a4d7953 100644 --- a/ir/opt/remove_vars.c +++ b/ir/opt/remove_vars.c @@ -2,16 +2,18 @@ #include "../opt.h" -void opt_remove_vars(SsaBlock *block) { +void vx_opt_remove_vars(block) + vx_IrBlock *block; +{ assert(block->is_root); for (size_t i = 0; i < block->as_root.vars_len; i ++) { - SsaOp *decl = block->as_root.vars[i].decl; + vx_IrOp *decl = block->as_root.vars[i].decl; if (decl == NULL) continue; - if (decl->id == SSA_OP_IF) - continue; // we have a specific opt_reduce_if + if (decl->id == VX_IR_OP_IF) + continue; // we have a specific vx_opt_reduce_if // TODO: optimize away states and similar @@ -29,7 +31,7 @@ void opt_remove_vars(SsaBlock *block) { // we can't optimize away if we need other results from the operation bool can_rem = true; for (size_t j = 0; j < decl->outs_len; j ++) { - if (irblock_var_used(block, decl->outs[j].var)) { + if (vx_IrBlock_var_used(block, decl->outs[j].var)) { can_rem = false; break; } @@ -39,8 +41,8 @@ void opt_remove_vars(SsaBlock *block) { continue; // in-place remove - irop_destroy(decl); - irop_init(decl, SSA_OP_NOP, decl->parent); + vx_IrOp_destroy(decl); + vx_IrOp_init(decl, VX_IR_OP_NOP, decl->parent); for (size_t j = 0; j < decl->outs_len; j ++) block->as_root.vars[decl->outs[j].var].decl = NULL; diff --git a/ir/transform.c b/ir/transform.c index 017dcfa..3a0dd1e 100644 --- a/ir/transform.c +++ b/ir/transform.c @@ -4,31 +4,31 @@ #include #include -SsaView irview_replace(SsaBlock *viewblock, const SsaView view, const SsaOp *ops, const size_t ops_len) { +vx_IrView vx_IrView_replace(vx_IrBlock *viewblock, const vx_IrView view, const vx_IrOp *ops, const size_t ops_len) { assert(viewblock == view.block); - const size_t new_size = view.block->ops_len - irview_len(view) + ops_len; - SsaOp *new = malloc(sizeof(SsaOp) * new_size); + const size_t new_size = view.block->ops_len - vx_IrView_len(view) + ops_len; + vx_IrOp *new = malloc(sizeof(vx_IrOp) * new_size); - memcpy(new, view.block->ops, view.start * sizeof(SsaOp)); - memcpy(new + view.start, ops, ops_len * sizeof(SsaOp)); - memcpy(new + view.start + ops_len, view.block->ops + view.end, (view.block->ops_len - view.end) * sizeof(SsaOp)); + memcpy(new, view.block->ops, view.start * sizeof(vx_IrOp)); + memcpy(new + view.start, ops, ops_len * sizeof(vx_IrOp)); + memcpy(new + view.start + ops_len, view.block->ops + view.end, (view.block->ops_len - view.end) * sizeof(vx_IrOp)); for (size_t i = view.start; i < view.end; i ++) - irop_destroy(&viewblock->ops[i]); + vx_IrOp_destroy(&viewblock->ops[i]); free(viewblock->ops); viewblock->ops = new; viewblock->ops_len = new_size; - return (SsaView) { + return (vx_IrView) { .block = view.block, .start = view.start, .end = view.start + ops_len, }; } -void irview_rename_var(SsaView view, SsaBlock *block, SsaVar old, SsaVar new) { +void vx_IrView_rename_var(vx_IrView view, vx_IrBlock *block, vx_IrVar old, vx_IrVar new) { assert(block == view.block); if (view.start == 0) @@ -41,43 +41,43 @@ void irview_rename_var(SsaView view, SsaBlock *block, SsaVar old, SsaVar new) { if (block->outs[j] == old) block->outs[j] = new; - irblock_root(block)->as_root.vars[old].decl = NULL; + vx_IrBlock_root(block)->as_root.vars[old].decl = NULL; for (size_t i = view.start; i < view.end; i ++) { - const SsaOp op = block->ops[i]; + const vx_IrOp op = block->ops[i]; for (size_t j = 0; j < op.outs_len; j ++) if (op.outs[j].var == old) op.outs[j].var = new; for (size_t j = 0; j < op.params_len; j ++) { - if (op.params[j].val.type == SSA_VAL_VAR && op.params[j].val.var == old) { + if (op.params[j].val.type == VX_IR_VALVAR && op.params[j].val.var == old) { op.params[j].val.var = new; } - else if (op.params[j].val.type == SSA_VAL_BLOCK) { - SsaBlock *child = op.params[j].val.block; - irview_rename_var(irview_of_all(child), child, old, new); + else if (op.params[j].val.type == VX_IR_VALBLOCK) { + vx_IrBlock *child = op.params[j].val.block; + vx_IrView_rename_var(vx_IrView_of_all(child), child, old, new); } } } } -struct irview_substitude_var__data { - SsaBlock *block; - SsaVar old; - SsaValue new; +struct vx_IrView_substitute_var__data { + vx_IrBlock *block; + vx_IrVar old; + vx_IrValue new; }; -static void irview_substitude_var__trav(SsaOp *op, void *dataIn) { - struct irview_substitude_var__data *data = dataIn; +static void vx_IrView_substitute_var__trav(vx_IrOp *op, void *dataIn) { + struct vx_IrView_substitute_var__data *data = dataIn; for (size_t i = 0; i < op->params_len; i ++) - if (op->params[i].val.type == SSA_VAL_VAR && op->params[i].val.var == data->old) + if (op->params[i].val.type == VX_IR_VALVAR && op->params[i].val.var == data->old) op->params[i].val = data->new; } -void irview_substitude_var(SsaView view, SsaBlock *block, SsaVar old, SsaValue new) { +void vx_IrView_substitute_var(vx_IrView view, vx_IrBlock *block, vx_IrVar old, vx_IrValue new) { assert(block == view.block); - struct irview_substitude_var__data data = { .block = block, .old = old, .new = new }; - irview_deep_traverse(view, irview_substitude_var__trav, &data); + struct vx_IrView_substitute_var__data data = { .block = block, .old = old, .new = new }; + vx_IrView_deep_traverse(view, vx_IrView_substitute_var__trav, &data); } diff --git a/ir/transform/flatten.c b/ir/transform/flatten.c index f42f894..0ed54b3 100644 --- a/ir/transform/flatten.c +++ b/ir/transform/flatten.c @@ -2,20 +2,26 @@ #include "../ir.h" -static void flatten_into(SsaOp *ops, size_t ops_len, SsaBlock *dest) { +static void flatten_into(ops, ops_len, dest) + vx_IrOp *ops; + size_t ops_len; + vx_IrBlock *dest; +{ for (size_t i = 0; i < ops_len; i ++) { - if (ops[i].id == SSA_OP_FLATTEN_PLEASE) { - const SsaBlock *child = irop_param(&ops[i], SSA_NAME_BLOCK)->block; + if (ops[i].id == VX_IR_OP_FLATTEN_PLEASE) { + const vx_IrBlock *child = vx_IrOp_param(&ops[i], VX_IR_NAME_BLOCK)->block; flatten_into(child->ops, child->ops_len, dest); } else { - irblock_add_op(dest, &ops[i]); + vx_IrBlock_add_op(dest, &ops[i]); } } } -void irblock_flatten(SsaBlock *block) { - SsaOp *old_ops = block->ops; +void vx_IrBlock_flatten(block) + vx_IrBlock *block; +{ + vx_IrOp *old_ops = block->ops; block->ops = NULL; const size_t old_ops_len = block->ops_len; block->ops_len = 0; diff --git a/ir/transform/normalize.c b/ir/transform/normalize.c index 58bf9d9..5999792 100644 --- a/ir/transform/normalize.c +++ b/ir/transform/normalize.c @@ -3,56 +3,58 @@ #include "../cir.h" -void cirblock_normalize(SsaBlock *block) { +void vx_CIrBlock_normalize(block) + vx_IrBlock *block; +{ assert(block->is_root); for (size_t i = 0; i < block->ins_len; i ++) { - SsaOp *op = block->ops; + vx_IrOp *op = block->ops; - if (op->id == CIR_OP_CFOR) { - SsaBlock *new = irblock_heapalloc(block, i); + if (op->id == CVX_IR_OP_CFOR) { + vx_IrBlock *new = vx_IrBlock_init_heap(block, i); - SsaBlock *b_init = irop_param(op, SSA_NAME_LOOP_START)->block; - SsaBlock *b_cond = irop_param(op, SSA_NAME_COND)->block; - SsaBlock *b_end = irop_param(op, SSA_NAME_LOOP_ENDEX)->block; - SsaBlock *b_do = irop_param(op, SSA_NAME_LOOP_DO)->block; + vx_IrBlock *b_init = vx_IrOp_param(op, VX_IR_NAME_LOOP_START)->block; + vx_IrBlock *b_cond = vx_IrOp_param(op, VX_IR_NAME_COND)->block; + vx_IrBlock *b_end = vx_IrOp_param(op, VX_IR_NAME_LOOP_ENDEX)->block; + vx_IrBlock *b_do = vx_IrOp_param(op, VX_IR_NAME_LOOP_DO)->block; // we free manually because we don't want to free blocks if should_free free(op->types); // TODO: ^ is stupid free(op->outs); free(op->states); - irop_remove_params(op); + vx_IrOp_remove_params(op); { - SsaOp opdo; - irop_init(&opdo, SSA_OP_FLATTEN_PLEASE, new); - irop_add_param_s(&opdo, SSA_NAME_BLOCK, (SsaValue) { .type = SSA_VAL_BLOCK, .block = b_init }); - irblock_add_op(new, &opdo); + vx_IrOp opdo; + vx_IrOp_init(&opdo, VX_IR_OP_FLATTEN_PLEASE, new); + vx_IrOp_add_param_s(&opdo, VX_IR_NAME_BLOCK, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = b_init }); + vx_IrBlock_add_op(new, &opdo); } - SsaOp opwhile; - irop_init(&opwhile, SSA_OP_WHILE, new); - irop_add_param_s(&opwhile, SSA_NAME_COND, (SsaValue) { .type = SSA_VAL_BLOCK, .block = b_cond }); + vx_IrOp opwhile; + vx_IrOp_init(&opwhile, VX_IR_OP_WHILE, new); + vx_IrOp_add_param_s(&opwhile, VX_IR_NAME_COND, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = b_cond }); - SsaBlock *doblock = irblock_heapalloc(new, new->ops_len); + vx_IrBlock *doblock = vx_IrBlock_init_heap(new, new->ops_len); { - SsaOp opdo; - irop_init(&opdo, SSA_OP_FLATTEN_PLEASE, new); - irop_add_param_s(&opdo, SSA_NAME_BLOCK, (SsaValue) { .type = SSA_VAL_BLOCK, .block = b_do }); - irblock_add_op(doblock, &opdo); + vx_IrOp opdo; + vx_IrOp_init(&opdo, VX_IR_OP_FLATTEN_PLEASE, new); + vx_IrOp_add_param_s(&opdo, VX_IR_NAME_BLOCK, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = b_do }); + vx_IrBlock_add_op(doblock, &opdo); } { - SsaOp opdo; - irop_init(&opdo, SSA_OP_FLATTEN_PLEASE, new); - irop_add_param_s(&opdo, SSA_NAME_BLOCK, (SsaValue) { .type = SSA_VAL_BLOCK, .block = b_end }); - irblock_add_op(doblock, &opdo); + vx_IrOp opdo; + vx_IrOp_init(&opdo, VX_IR_OP_FLATTEN_PLEASE, new); + vx_IrOp_add_param_s(&opdo, VX_IR_NAME_BLOCK, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = b_end }); + vx_IrBlock_add_op(doblock, &opdo); } - irop_add_param_s(&opwhile, SSA_NAME_LOOP_DO, (SsaValue) { .type = SSA_VAL_BLOCK, .block = doblock }); + vx_IrOp_add_param_s(&opwhile, VX_IR_NAME_LOOP_DO, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = doblock }); - irblock_add_op(new, &opwhile); + vx_IrBlock_add_op(new, &opwhile); - op->id = SSA_OP_FLATTEN_PLEASE; - irop_add_param_s(op, SSA_NAME_BLOCK, (SsaValue) { .type = SSA_VAL_BLOCK, .block = new }); + op->id = VX_IR_OP_FLATTEN_PLEASE; + vx_IrOp_add_param_s(op, VX_IR_NAME_BLOCK, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = new }); } } } diff --git a/ir/transform/single_assign.c b/ir/transform/single_assign.c index 19df46d..ba4761c 100644 --- a/ir/transform/single_assign.c +++ b/ir/transform/single_assign.c @@ -7,22 +7,24 @@ * * inside out! */ -void cirblock_mksa_final(SsaBlock *block) { +void vx_CIrBlock_mksa_final(block) + vx_IrBlock *block; +{ for (size_t i = 0; i < block->ops_len; i ++) { - SsaOp *op = &block->ops[i]; + vx_IrOp *op = &block->ops[i]; for (size_t j = 0; j < op->params_len; j ++) - if (op->params[j].val.type == SSA_VAL_BLOCK) - cirblock_mksa_final(op->params[j].val.block); + if (op->params[j].val.type == VX_IR_VALBLOCK) + vx_CIrBlock_mksa_final(op->params[j].val.block); for (size_t j = 0; j < op->outs_len; j ++) { - SsaVar *var = &op->outs[j].var; - const SsaVar old = *var; - const SsaVar new = irblock_new_var(block, op); + vx_IrVar *var = &op->outs[j].var; + const vx_IrVar old = *var; + const vx_IrVar new = vx_IrBlock_new_var(block, op); *var = new; - SsaView view = irview_of_all(block); + vx_IrView view = vx_IrView_of_all(block); view.start = i + 1; - irview_rename_var(view, block, old, new); + vx_IrView_rename_var(view, block, old, new); } } } diff --git a/ir/transform/single_assign_conditional.c b/ir/transform/single_assign_conditional.c index ae716a7..50d405e 100644 --- a/ir/transform/single_assign_conditional.c +++ b/ir/transform/single_assign_conditional.c @@ -45,20 +45,29 @@ * @param condOff the index of the assignment in conditional * @param ifOp the if op that contains the conditional block * @param var affected variable + * @param manipIn */ -static SsaVar megic(SsaBlock *outer, const size_t outerOff, SsaBlock *conditional, const size_t condOff, SsaOp *ifOp, const SsaVar var, const OptSsaVar manipIn) { +static vx_IrVar megic(outer, outerOff, conditional, condOff, ifOp, var, manipIn) + vx_IrBlock *outer; + const size_t outerOff; + vx_IrBlock *conditional; + const size_t condOff; + vx_IrOp *ifOp; + const vx_IrVar var; + const vx_OptIrVar manipIn; +{ // stage 1 - const SsaVar manipulate = irblock_new_var(outer, ifOp); + const vx_IrVar manipulate = vx_IrBlock_new_var(outer, ifOp); { - SsaView rename = irview_of_all(outer); + vx_IrView rename = vx_IrView_of_all(outer); rename.start = outerOff + 1; - irview_rename_var(rename, outer, var, manipulate); + vx_IrView_rename_var(rename, outer, var, manipulate); } // stage 2 - SsaVar last_cond_assign = manipulate; + vx_IrVar last_cond_assign = manipulate; for (size_t i = condOff; i < conditional->ops_len; i ++) { - SsaOp *op = &conditional->ops[i]; + vx_IrOp *op = &conditional->ops[i]; // make sure that we assign in this op bool found = false; @@ -73,11 +82,11 @@ static SsaVar megic(SsaBlock *outer, const size_t outerOff, SsaBlock *conditiona // we don't have to check children because megic gets called from the inside out - const SsaVar new = irblock_new_var(outer, op); + const vx_IrVar new = vx_IrBlock_new_var(outer, op); // we include the current index on purpose - SsaView rename = irview_of_all(conditional); + vx_IrView rename = vx_IrView_of_all(conditional); rename.start = i; - irview_rename_var(rename, conditional, last_cond_assign, new); + vx_IrView_rename_var(rename, conditional, last_cond_assign, new); last_cond_assign = new; } @@ -88,71 +97,73 @@ static SsaVar megic(SsaBlock *outer, const size_t outerOff, SsaBlock *conditiona // last_cond_assign <=> the conditional var that we need to return in the then block // manipulate <=> the new target var - const SsaOp *orig_assign = &outer->ops[outerOff]; - SsaType type = NULL; + const vx_IrOp *orig_assign = &outer->ops[outerOff]; + vx_IrType type = NULL; for (size_t i = 0; i < orig_assign->outs_len; i ++) if (orig_assign->outs[i].var == var) type = orig_assign->outs[i].type; - SsaBlock *then = irop_param(ifOp, SSA_NAME_COND_THEN)->block; - const SsaValue *pels = irop_param(ifOp, SSA_NAME_COND_ELSE); + vx_IrBlock *then = vx_IrOp_param(ifOp, VX_IR_NAME_COND_THEN)->block; + const vx_IrValue *pels = vx_IrOp_param(ifOp, VX_IR_NAME_COND_ELSE); - SsaBlock *els; + vx_IrBlock *els; if (pels == NULL) { - els = irblock_heapalloc(then->parent, then->parent_index); // lazyness - irop_add_param_s(ifOp, SSA_NAME_COND_ELSE, (SsaValue) { .type = SSA_VAL_BLOCK, .block = els }); + els = vx_IrBlock_init_heap(then->parent, then->parent_index); // lazyness + vx_IrOp_add_param_s(ifOp, VX_IR_NAME_COND_ELSE, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = els }); } else { els = pels->block; } if (conditional == els) { - SsaBlock *temp = then; + vx_IrBlock *temp = then; then = els; els = temp; } - irop_add_out(ifOp, manipulate, type); + vx_IrOp_add_out(ifOp, manipulate, type); if (manipIn.present) - irblock_add_out(then, manipIn.var); + vx_IrBlock_add_out(then, manipIn.var); else - irblock_add_out(then, last_cond_assign); - irblock_add_out(els, var); + vx_IrBlock_add_out(then, last_cond_assign); + vx_IrBlock_add_out(els, var); return manipulate; } // call megic somehow // detect the patter from the inside out!! -OptSsaVar cirblock_mksa_states(SsaBlock *block) { - OptSsaVar rvar = SSAVAR_OPT_NONE; +vx_OptIrVar vx_CIrBlock_mksa_states(block) + vx_IrBlock *block; +{ + vx_OptIrVar rvar = VX_IRVAR_OPT_NONE; for (size_t i = 0; i < block->ops_len; i ++) { - SsaOp *ifOp = &block->ops[i]; - if (ifOp->id != SSA_OP_IF) + vx_IrOp *ifOp = &block->ops[i]; + if (ifOp->id != VX_IR_OP_IF) continue; // inside out: assert(ifOp->params_len >= 2); assert(ifOp->params_len <= 3); for (size_t j = 0; j < ifOp->params_len; j ++) { - if (ifOp->params[j].val.type != SSA_VAL_BLOCK) + if (ifOp->params[j].val.type != VX_IR_VALBLOCK) continue; - SsaBlock *conditional = ifOp->params[j].val.block; - OptSsaVar manip = cirblock_mksa_states(conditional); + vx_IrBlock *conditional = ifOp->params[j].val.block; + vx_OptIrVar manip = vx_CIrBlock_mksa_states(conditional); // TODO: make work if we have a else block and assign there too!!!! // are we assigning any variable directly in that block that we also assign on the outside before the inst? for (size_t k = 0; k < conditional->ops_len; k ++) { - const SsaOp *condAssignOp = &conditional->ops[k]; + const vx_IrOp *condAssignOp = &conditional->ops[k]; for (size_t l = 0; l < condAssignOp->outs_len; l ++) { - const SsaVar var = condAssignOp->outs[l].var; + const vx_IrVar var = condAssignOp->outs[l].var; - const SsaOp *alwaysAssignOp = irblock_inside_out_vardecl_before(block, var, i); + const vx_IrOp *alwaysAssignOp = vx_IrBlock_inside_out_vardecl_before(block, var, i); if (alwaysAssignOp == NULL) continue; - rvar = SSAVAR_OPT_SOME(megic(alwaysAssignOp->parent, alwaysAssignOp->parent->ops - alwaysAssignOp, conditional, k, ifOp, var, manip)); + rvar = VX_IRVAR_OPT_SOME(megic(alwaysAssignOp->parent, alwaysAssignOp->parent->ops - alwaysAssignOp, conditional, k, ifOp, var, manip)); } } } diff --git a/ir/verify.h b/ir/verify.h index 75999d7..1009ec4 100644 --- a/ir/verify.h +++ b/ir/verify.h @@ -1,6 +1,11 @@ +#ifndef VERIFY_H +#define VERIFY_H + #include "ir.h" -void irblock_verify_ssa_based(VerifyErrors *dest, const SsaBlock *block, const OpPath path); +void vx_IrBlock_verify_ssa_based(vx_Errors *dest, const vx_IrBlock *block, vx_OpPath path); + +void vx_error_param_type(vx_Errors *errors, vx_OpPath path, const char *expected); +void vx_error_param_missing(vx_Errors *errors, vx_OpPath path, const char *param); -void error_param_type(VerifyErrors *errors, const OpPath path, const char *expected); -void error_param_missing(VerifyErrors *errors, const OpPath path, const char *param); +#endif \ No newline at end of file diff --git a/ir/verify_cir.c b/ir/verify_cir.c index 489e567..722b761 100644 --- a/ir/verify_cir.c +++ b/ir/verify_cir.c @@ -1,12 +1,15 @@ #include "cir.h" #include "verify.h" -VerifyErrors cirblock_verify(const SsaBlock *block, OpPath path) { - VerifyErrors errors; +vx_Errors vx_CIrBlock_verify(block, path) + const vx_IrBlock *block; + vx_OpPath path; +{ + vx_Errors errors; errors.items = NULL; errors.len = 0; - irblock_verify_ssa_based(&errors, block, path); + vx_IrBlock_verify_ssa_based(&errors, block, path); return errors; } diff --git a/ir/verify_common.c b/ir/verify_common.c index 1737d3c..1985aea 100644 --- a/ir/verify_common.c +++ b/ir/verify_common.c @@ -2,188 +2,209 @@ #include "verify.h" -void error_param_type(VerifyErrors *errors, const OpPath path, const char *expected) { +void vx_error_param_type(vx_Errors *errors, const vx_OpPath path, const char *expected) { static char buf[256]; sprintf(buf, "Expected parameter type %s", expected); - const VerifyError error = { + const vx_Error error = { .path = path, .error = "Incorrect type", .additional = buf }; - verifyerrors_add(errors, &error); + vx_Errors_add(errors, &error); } -void error_param_missing(VerifyErrors *errors, const OpPath path, const char *param) { +void vx_error_param_missing(vx_Errors *errors, const vx_OpPath path, const char *param) { static char buf[256]; sprintf(buf, "Missing required parameter %s", param); - const VerifyError error = { + const vx_Error error = { .path = path, .error = "Missing parameter", .additional = buf }; - verifyerrors_add(errors, &error); + vx_Errors_add(errors, &error); } -void irblock_verify_ssa_based(VerifyErrors *dest, const SsaBlock *block, const OpPath path) { - const SsaBlock *root = irblock_root(block); +static bool analyze_if(dest, op, i, path) + vx_Errors *dest; + const vx_IrOp *op; + size_t i; + vx_OpPath path; +{ + bool err = false; + + const vx_IrValue *vcond = vx_IrOp_param(op, VX_IR_NAME_COND); + if (vcond == NULL) { + vx_error_param_missing(dest, vx_OpPath_copy_add(path, i), "cond"); + err = true; + } else if (vcond->type != VX_IR_VALBLOCK) { + vx_error_param_type(dest, vx_OpPath_copy_add(path, i), "block"); + err = true; + } - for (size_t i = 0; i < block->ops_len; i++) { - const SsaOp *op = &block->ops[i]; + const vx_IrValue *vthen = vx_IrOp_param(op, VX_IR_NAME_COND_THEN); + if (vthen == NULL) { + vx_error_param_missing(dest, vx_OpPath_copy_add(path, i), "then"); + err = true; + } else if (vthen->type != VX_IR_VALBLOCK) { + vx_error_param_type(dest, vx_OpPath_copy_add(path, i), "block"); + err = true; + } - // TODO: implement for more types + const vx_IrValue *velse = vx_IrOp_param(op, VX_IR_NAME_COND_ELSE); + if (velse == NULL) { + vx_error_param_missing(dest, vx_OpPath_copy_add(path, i), "else"); + err = true; + } else if (velse->type != VX_IR_VALBLOCK) { + vx_error_param_type(dest, vx_OpPath_copy_add(path, i), "block"); + err = true; + } - // verify states in general - for (size_t j = 0; j < op->states_len; j ++) { - if (op->states[j].type == SSA_VAL_BLOCK) { - const OpPath newpath = oppath_copy_add(path, i); - const VerifyError error = { - .path = newpath, - .error = "Invalid state", - .additional = "States cannot be blocks!" - }; - verifyerrors_add(dest, &error); - } + if (!err) { + vx_IrBlock *bcond = vcond->block; + vx_IrBlock *bthen = vthen->block; + vx_IrBlock *belse = velse->block; + + if (bcond->outs_len != 1) { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Error error = { + .path = newpath, + .error = "If block is missing a condition", + .additional = "If block is missing a condition! Example: `cond=(){ ^ 1 }`" + }; + vx_Errors_add(dest, &error); } - // verify loop state - if (op->id == SSA_OP_FOR || - op->id == SSA_OP_FOREACH || - op->id == SSA_OP_FOREACH_UNTIL || - op->id == SSA_OP_REPEAT || - op->id == SSA_OP_INFINITE || - op->id == SSA_OP_WHILE) - { - const size_t states_count = op->outs_len; - if (states_count != op->states_len) { - const OpPath newpath = oppath_copy_add(path, i); - VerifyError error = { - .path = newpath, - .error = "Loop state not initialized", - .additional = "Loop states do not match! Example: `state0=1234`" - }; - verifyerrors_add(dest, &error); - } + if (!(bthen->outs_len == belse->outs_len && bthen->outs_len == op->outs_len)) { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Error error = { + .path = newpath, + .error = "If block invalid outputs", + .additional = "Expected every branch in the if block to have the same amount of outputs!" + }; + vx_Errors_add(dest, &error); + } + } + + return err; +} - const SsaValue *doblock_v = irop_param(op, SSA_NAME_LOOP_DO); - if (doblock_v == NULL) { - const OpPath newpath = oppath_copy_add(path, i); - VerifyError error = { +static void analyze_loops(dest, op, i, path) + vx_Errors *dest; + const vx_IrOp *op; + size_t i; + vx_OpPath path; +{ + const size_t states_count = op->outs_len; + if (states_count != op->states_len) { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Error error = { + .path = newpath, + .error = "Loop state not initialized", + .additional = "Loop states do not match! Example: `state0=1234`" + }; + vx_Errors_add(dest, &error); + } + + const vx_IrValue *doblock_v = vx_IrOp_param(op, VX_IR_NAME_LOOP_DO); + if (doblock_v == NULL) { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Error error = { + .path = newpath, + .error = "Loop is missing a do block", + .additional = "Loop is missing a `do` block. Example: `do=(%0){}`" + }; + vx_Errors_add(dest, &error); + } + else { + if (doblock_v->type != VX_IR_VALBLOCK) { + vx_error_param_type(dest, vx_OpPath_copy_add(path, i), "block"); + } else { + const vx_IrBlock *doblock = doblock_v->block; + + if (doblock->outs_len != states_count) { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Error error = { .path = newpath, - .error = "Loop is missing a do block", - .additional = "Loop is missing a `do` block. Example: `do=(%0){}`" + .error = "Do block is missing state changes", + .additional = "Loop do-block is missing state-updates for all states!" }; - verifyerrors_add(dest, &error); - } - else { - if (doblock_v->type != SSA_VAL_BLOCK) { - error_param_type(dest, oppath_copy_add(path, i), "block"); - } else { - const SsaBlock *doblock = doblock_v->block; - - if (doblock->outs_len != states_count) { - const OpPath newpath = oppath_copy_add(path, i); - VerifyError error = { - .path = newpath, - .error = "Do block is missing state changes", - .additional = "Loop do-block is missing state-updates for all states!" - }; - verifyerrors_add(dest, &error); - } - } + vx_Errors_add(dest, &error); } } + } +} - if (op->id == SSA_OP_IF) { - bool err = false; - - const SsaValue *vcond = irop_param(op, SSA_NAME_COND); - if (vcond == NULL) { - error_param_missing(dest, oppath_copy_add(path, i), "cond"); - err = true; - } else if (vcond->type != SSA_VAL_BLOCK) { - error_param_type(dest, oppath_copy_add(path, i), "block"); - err = true; - } +void vx_IrBlock_verify_ssa_based(vx_Errors *dest, const vx_IrBlock *block, const vx_OpPath path) { + const vx_IrBlock *root = vx_IrBlock_root(block); - const SsaValue *vthen = irop_param(op, SSA_NAME_COND_THEN); - if (vthen == NULL) { - error_param_missing(dest, oppath_copy_add(path, i), "then"); - err = true; - } else if (vthen->type != SSA_VAL_BLOCK) { - error_param_type(dest, oppath_copy_add(path, i), "block"); - err = true; - } + for (size_t i = 0; i < block->ops_len; i++) { + const vx_IrOp *op = &block->ops[i]; - const SsaValue *velse = irop_param(op, SSA_NAME_COND_ELSE); - if (velse == NULL) { - error_param_missing(dest, oppath_copy_add(path, i), "else"); - err = true; - } else if (velse->type != SSA_VAL_BLOCK) { - error_param_type(dest, oppath_copy_add(path, i), "block"); - err = true; + // verify states in general + for (size_t j = 0; j < op->states_len; j ++) { + if (op->states[j].type == VX_IR_VALBLOCK) { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + const vx_Error error = { + .path = newpath, + .error = "Invalid state", + .additional = "States cannot be blocks!" + }; + vx_Errors_add(dest, &error); } + } - if (!err) { - SsaBlock *bcond = vcond->block; - SsaBlock *bthen = vthen->block; - SsaBlock *belse = velse->block; - - if (bcond->outs_len != 1) { - const OpPath newpath = oppath_copy_add(path, i); - VerifyError error = { - .path = newpath, - .error = "If block is missing a condition", - .additional = "If block is missing a condition! Example: `cond=(){ ^ 1 }`" - }; - verifyerrors_add(dest, &error); - } - - if (!(bthen->outs_len == belse->outs_len && bthen->outs_len == op->outs_len)) { - const OpPath newpath = oppath_copy_add(path, i); - VerifyError error = { - .path = newpath, - .error = "If block invalid outputs", - .additional = "Expected every branch in the if block to have the same amount of outputs!" - }; - verifyerrors_add(dest, &error); - } - } + // TODO: implement for more ops + switch (op->id) { + case VX_IR_OP_FOR: + case VX_IR_OP_FOREACH: + case VX_IR_OP_FOREACH_UNTIL: + case VX_IR_OP_REPEAT: + case VX_IR_OP_INFINITE: + case VX_IR_OP_WHILE: + analyze_loops(dest, block, i, path); + break; + + case VX_IR_OP_IF: + (void) analyze_if(dest, op, i, path); + break; + + default: + break; } for (size_t j = 0; j < op->params_len; j ++) { - const SsaValue val = op->params[j].val; + const vx_IrValue val = op->params[j].val; - if (val.type == SSA_VAL_BLOCK) { - const OpPath newpath = oppath_copy_add(path, i); - VerifyErrors errs = irblock_verify(val.block, newpath); + if (val.type == VX_IR_VALBLOCK) { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Errors errs = vx_IrBlock_verify(val.block, newpath); free(newpath.ids); - verifyerrors_add_all_and_free(dest, &errs); + vx_Errors_add_all_and_free(dest, &errs); } - else if (val.type == SSA_VAL_VAR) { - const SsaVar var = val.var; + else if (val.type == VX_IR_VALVAR) { + const vx_IrVar var = val.var; if (var >= root->as_root.vars_len) { static char buf[256]; sprintf(buf, "Variable %%%zu id is bigger than root block variable count - 1!", var); - const OpPath newpath = oppath_copy_add(path, i); - VerifyError error = { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Error error = { .path = newpath, .error = "Variable out of bounds", .additional = buf }; - verifyerrors_add(dest, &error); + vx_Errors_add(dest, &error); } else if (root->as_root.vars[var].decl == NULL) { static char buf[256]; sprintf(buf, "Variable %%%zu is never declared!", var); - const OpPath newpath = oppath_copy_add(path, i); - VerifyError error = { + const vx_OpPath newpath = vx_OpPath_copy_add(path, i); + vx_Error error = { .path = newpath, .error = "Undeclared variable", .additional = buf }; - verifyerrors_add(dest, &error); + vx_Errors_add(dest, &error); } } } } - } diff --git a/ir/verify_ssa.c b/ir/verify_ssa.c index a324c0f..68a75e1 100644 --- a/ir/verify_ssa.c +++ b/ir/verify_ssa.c @@ -6,10 +6,10 @@ struct verify_vardecls_deeptraverse__data { size_t declcount; - SsaVar var; + vx_IrVar var; }; -static void verify_vardecls_deeptraverse(SsaOp *op, void *dataIn) { +static void verify_vardecls_deeptraverse(vx_IrOp *op, void *dataIn) { struct verify_vardecls_deeptraverse__data *va = dataIn; for (size_t i = 0; i < op->outs_len; i ++) @@ -17,9 +17,9 @@ static void verify_vardecls_deeptraverse(SsaOp *op, void *dataIn) { va->declcount ++; for (size_t j = 0; j < op->params_len; j ++) { - const SsaValue param = op->params[j].val; + const vx_IrValue param = op->params[j].val; - if (param.type == SSA_VAL_BLOCK) { + if (param.type == VX_IR_VALBLOCK) { for (size_t k = 0; k < param.block->ins_len; k ++) if (param.block->ins[k] == va->var) va->declcount ++; @@ -27,12 +27,12 @@ static void verify_vardecls_deeptraverse(SsaOp *op, void *dataIn) { } } -VerifyErrors irblock_verify(const SsaBlock *block, const OpPath path) { - VerifyErrors errors; +vx_Errors vx_IrBlock_verify(const vx_IrBlock *block, const vx_OpPath path) { + vx_Errors errors; errors.len = 0; errors.items = NULL; - irblock_verify_ssa_based(&errors, block, path); + vx_IrBlock_verify_ssa_based(&errors, block, path); if (block->is_root) { for (size_t i = 0; i < block->as_root.vars_len; i ++) { @@ -42,19 +42,19 @@ VerifyErrors irblock_verify(const SsaBlock *block, const OpPath path) { struct verify_vardecls_deeptraverse__data dat; dat.var = i; dat.declcount = 0; - irview_deep_traverse(irview_of_all(block), verify_vardecls_deeptraverse, &dat); + vx_IrView_deep_traverse(vx_IrView_of_all(block), verify_vardecls_deeptraverse, &dat); assert(dat.declcount > 0 /* WE REMOVED VARIABLE DECLARATION WITHOUT REMOVING IT FROM DB!!! */); if (dat.declcount > 1) { static char buf[256]; sprintf(buf, "Variable %%%zu is assigned more than once!", i); - VerifyError error = { - .path = (OpPath) { .ids = NULL, .len = 0 }, + vx_Error error = { + .path = (vx_OpPath) { .ids = NULL, .len = 0 }, .error = "Variable assigned more than once", .additional = buf }; - verifyerrors_add(&errors, &error); + vx_Errors_add(&errors, &error); } } } diff --git a/main.c b/main.c index c2e161e..51d7e32 100644 --- a/main.c +++ b/main.c @@ -3,146 +3,146 @@ #include "ir/cir.h" static int ir_test(void) { - SsaBlock block; - irblock_init(&block, NULL, 0); + vx_IrBlock block; + vx_IrBlock_init(&block, NULL, 0); - SsaOp for_op; - irop_init(&for_op, SSA_OP_FOR, &block); - irop_add_param_s(&for_op, SSA_NAME_LOOP_START, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 0 }); + vx_IrOp for_op; + vx_IrOp_init(&for_op, VX_IR_OP_FOR, &block); + vx_IrOp_add_param_s(&for_op, VX_IR_NAME_LOOP_START, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 0 }); - SsaBlock cond; - irblock_init(&cond, &block, block.ops_len); - irblock_add_in(&cond, 2); + vx_IrBlock cond; + vx_IrBlock_init(&cond, &block, block.ops_len); + vx_IrBlock_add_in(&cond, 2); { - SsaOp cmp_op; - irop_init(&cmp_op, SSA_OP_LT, &cond); - irop_add_out(&cmp_op, 1, "bool"); - irop_add_param_s(&cmp_op, SSA_NAME_OPERAND_A, (SsaValue) { .type = SSA_VAL_VAR, .var = 2 }); - irop_add_param_s(&cmp_op, SSA_NAME_OPERAND_B, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 10 }); + vx_IrOp cmp_op; + vx_IrOp_init(&cmp_op, VX_IR_OP_LT, &cond); + vx_IrOp_add_out(&cmp_op, 1, "bool"); + vx_IrOp_add_param_s(&cmp_op, VX_IR_NAME_OPERAND_A, (vx_IrValue) { .type = VX_IR_VALVAR, .var = 2 }); + vx_IrOp_add_param_s(&cmp_op, VX_IR_NAME_OPERAND_B, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 10 }); - irblock_add_op(&cond, &cmp_op); + vx_IrBlock_add_op(&cond, &cmp_op); } - irblock_add_out(&cond, 1); + vx_IrBlock_add_out(&cond, 1); - irop_add_param_s(&for_op, SSA_NAME_COND, (SsaValue) { .type = SSA_VAL_BLOCK, .block = &cond }); + vx_IrOp_add_param_s(&for_op, VX_IR_NAME_COND, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = &cond }); - SsaBlock loop; - irblock_init(&loop, &block, block.ops_len); - irblock_add_in(&loop, 0); + vx_IrBlock loop; + vx_IrBlock_init(&loop, &block, block.ops_len); + vx_IrBlock_add_in(&loop, 0); // let's assume that this block prints the number - irop_add_param_s(&for_op, SSA_NAME_LOOP_STRIDE, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 1 }); - irop_add_param_s(&for_op, SSA_NAME_LOOP_DO, (SsaValue) { .type = SSA_VAL_BLOCK, .block = &loop }); + vx_IrOp_add_param_s(&for_op, VX_IR_NAME_LOOP_STRIDE, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 1 }); + vx_IrOp_add_param_s(&for_op, VX_IR_NAME_LOOP_DO, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = &loop }); - irblock_add_op(&block, &for_op); + vx_IrBlock_add_op(&block, &for_op); - irblock_make_root(&block, 3); + vx_IrBlock_make_root(&block, 3); - if (ir_verify(&block) != 0) + if (vx_ir_verify(&block) != 0) return 1; opt(&block); - irblock_dump(&block, stdout, 0); + vx_IrBlock_dump(&block, stdout, 0); return 0; } -static SsaBlock *always_true_block(SsaBlock *parent, SsaVar temp_var) { - SsaBlock *block = irblock_heapalloc(parent, parent->ops_len); +static vx_IrBlock *always_true_block(vx_IrBlock *parent, vx_IrVar temp_var) { + vx_IrBlock *block = vx_IrBlock_init_heap(parent, parent->ops_len); - SsaOp assign; - irop_init(&assign, SSA_OP_IMM, block); - irop_add_out(&assign, temp_var, "int"); - irop_add_param_s(&assign, SSA_NAME_VALUE, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 1 }); - irblock_add_op(block, &assign); + vx_IrOp assign; + vx_IrOp_init(&assign, VX_IR_OP_IMM, block); + vx_IrOp_add_out(&assign, temp_var, "int"); + vx_IrOp_add_param_s(&assign, VX_IR_NAME_VALUE, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 1 }); + vx_IrBlock_add_op(block, &assign); - irblock_add_out(block, temp_var); + vx_IrBlock_add_out(block, temp_var); return block; } -static SsaBlock *conditional_c_assign(SsaVar dest, SsaBlock *parent, SsaVar temp_var) { - SsaOp op; - irop_init(&op, SSA_OP_IF, parent); +static vx_IrBlock *conditional_c_assign(vx_IrVar dest, vx_IrBlock *parent, vx_IrVar temp_var) { + vx_IrOp op; + vx_IrOp_init(&op, VX_IR_OP_IF, parent); - SsaBlock *then = irblock_heapalloc(parent, parent->ops_len); + vx_IrBlock *then = vx_IrBlock_init_heap(parent, parent->ops_len); { - SsaOp op2; - irop_init(&op2, SSA_OP_IMM, then); - irop_add_out(&op2, dest, "int"); - irop_add_param_s(&op2, SSA_NAME_VALUE, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 2 }); - irblock_add_op(then, &op2); + vx_IrOp op2; + vx_IrOp_init(&op2, VX_IR_OP_IMM, then); + vx_IrOp_add_out(&op2, dest, "int"); + vx_IrOp_add_param_s(&op2, VX_IR_NAME_VALUE, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 2 }); + vx_IrBlock_add_op(then, &op2); } - irop_add_param_s(&op, SSA_NAME_COND_THEN, (SsaValue) { .type = SSA_VAL_BLOCK, .block = then }); + vx_IrOp_add_param_s(&op, VX_IR_NAME_COND_THEN, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = then }); - irop_add_param_s(&op, SSA_NAME_COND, (SsaValue) { .type = SSA_VAL_BLOCK, .block = always_true_block(parent, temp_var) }); + vx_IrOp_add_param_s(&op, VX_IR_NAME_COND, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = always_true_block(parent, temp_var) }); - irblock_add_op(parent, &op); + vx_IrBlock_add_op(parent, &op); return then; } -static SsaBlock *conditional_c_assign_else(SsaVar dest, SsaBlock *parent, SsaVar temp_var) { - SsaOp op; - irop_init(&op, SSA_OP_IF, parent); +static vx_IrBlock *conditional_c_assign_else(vx_IrVar dest, vx_IrBlock *parent, vx_IrVar temp_var) { + vx_IrOp op; + vx_IrOp_init(&op, VX_IR_OP_IF, parent); - irop_add_param_s(&op, SSA_NAME_COND_THEN, (SsaValue) { .type = SSA_VAL_BLOCK, .block = irblock_heapalloc(parent, parent->ops_len) }); + vx_IrOp_add_param_s(&op, VX_IR_NAME_COND_THEN, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = vx_IrBlock_init_heap(parent, parent->ops_len) }); - SsaBlock *els = irblock_heapalloc(parent, parent->ops_len); + vx_IrBlock *els = vx_IrBlock_init_heap(parent, parent->ops_len); { - SsaOp op2; - irop_init(&op2, SSA_OP_IMM, els); - irop_add_out(&op2, dest, "int"); - irop_add_param_s(&op2, SSA_NAME_VALUE, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 2 }); - irblock_add_op(els, &op2); + vx_IrOp op2; + vx_IrOp_init(&op2, VX_IR_OP_IMM, els); + vx_IrOp_add_out(&op2, dest, "int"); + vx_IrOp_add_param_s(&op2, VX_IR_NAME_VALUE, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 2 }); + vx_IrBlock_add_op(els, &op2); } - irop_add_param_s(&op, SSA_NAME_COND_ELSE, (SsaValue) { .type = SSA_VAL_BLOCK, .block = els }); + vx_IrOp_add_param_s(&op, VX_IR_NAME_COND_ELSE, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = els }); - irop_add_param_s(&op, SSA_NAME_COND, (SsaValue) { .type = SSA_VAL_BLOCK, .block = always_true_block(parent, temp_var) }); + vx_IrOp_add_param_s(&op, VX_IR_NAME_COND, (vx_IrValue) { .type = VX_IR_VALBLOCK, .block = always_true_block(parent, temp_var) }); - irblock_add_op(parent, &op); + vx_IrBlock_add_op(parent, &op); return els; } static int cir_test(void) { - SsaBlock block; - irblock_init(&block, NULL, 0); + vx_IrBlock block; + vx_IrBlock_init(&block, NULL, 0); { - SsaOp op; - irop_init(&op, SSA_OP_IMM, &block); - irop_add_out(&op, 0, "int"); - irop_add_param_s(&op, SSA_NAME_VALUE, (SsaValue) { .type = SSA_VAL_IMM_INT, .imm_int = 1 }); - irblock_add_op(&block, &op); + vx_IrOp op; + vx_IrOp_init(&op, VX_IR_OP_IMM, &block); + vx_IrOp_add_out(&op, 0, "int"); + vx_IrOp_add_param_s(&op, VX_IR_NAME_VALUE, (vx_IrValue) { .type = VX_IR_VALIMM_INT, .imm_int = 1 }); + vx_IrBlock_add_op(&block, &op); } - SsaBlock *els = conditional_c_assign_else(0, &block, 1); + vx_IrBlock *els = conditional_c_assign_else(0, &block, 1); conditional_c_assign_else(0, els, 2); { - SsaOp op; - irop_init(&op, SSA_OP_IMM, &block); - irop_add_out(&op, 1, "int"); - irop_add_param_s(&op, SSA_NAME_VALUE, (SsaValue) { .type = SSA_VAL_VAR, .var = 0 }); - irblock_add_op(&block, &op); + vx_IrOp op; + vx_IrOp_init(&op, VX_IR_OP_IMM, &block); + vx_IrOp_add_out(&op, 1, "int"); + vx_IrOp_add_param_s(&op, VX_IR_NAME_VALUE, (vx_IrValue) { .type = VX_IR_VALVAR, .var = 0 }); + vx_IrBlock_add_op(&block, &op); } - irblock_make_root(&block, 1); + vx_IrBlock_make_root(&block, 1); - if (cir_verify(&block) != 0) + if (vx_cir_verify(&block) != 0) return 1; printf("Pre:\n"); - irblock_dump(&block, stdout, 0); + vx_IrBlock_dump(&block, stdout, 0); - cirblock_mksa_states(&block); - cirblock_mksa_final(&block); + vx_CIrBlock_mksa_states(&block); + vx_CIrBlock_mksa_final(&block); printf("Post:\n"); - irblock_dump(&block, stdout, 0); + vx_IrBlock_dump(&block, stdout, 0); - irblock_destroy(&block); + vx_IrBlock_destroy(&block); return 0; }