131 lines
3.3 KiB
C
131 lines
3.3 KiB
C
|
|
#include <mie/ctx.h>
|
||
|
|
#include <mie/ir/op.h>
|
||
|
|
#include <mie/ir/region.h>
|
||
|
|
#include <mie/ir/resolve.h>
|
||
|
|
#include <mie/ir/walk.h>
|
||
|
|
#include <stdbool.h>
|
||
|
|
|
||
|
|
#if 0
|
||
|
|
static bool resolve_op(struct mie_op *op, struct mie_ctx *ctx)
|
||
|
|
{
|
||
|
|
if (mie_op_has_trait(op, "func", "function-like")) {
|
||
|
|
struct mie_region *region = mie_op_get_first_region(op);
|
||
|
|
mie_region_refresh_dominance(region);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!mie_op_resolve_references(op, ctx)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static bool resolve_self_and_successors(struct mie_op *op, struct mie_ctx *ctx)
|
||
|
|
{
|
||
|
|
char op_name[128];
|
||
|
|
enum mie_walker_flags walk_flags
|
||
|
|
= MIE_WALKER_F_INCLUDE_OPS | MIE_WALKER_F_PREORDER
|
||
|
|
| MIE_WALKER_F_FORWARD | MIE_WALKER_F_RECURSIVE;
|
||
|
|
struct mie_walker walker;
|
||
|
|
mie_walker_begin(&walker, op, walk_flags);
|
||
|
|
bool result = true;
|
||
|
|
|
||
|
|
do {
|
||
|
|
const struct mie_walk_item *item = mie_walker_get(&walker);
|
||
|
|
struct mie_op *op = item->i_op;
|
||
|
|
mie_op_get_name(op, op_name, sizeof op_name);
|
||
|
|
// printf("resolving op: %p %s... ", item->i_op, op_name);
|
||
|
|
bool ok = mie_resolve_op_self(op, ctx);
|
||
|
|
// printf("%s\n", ok ? "OK" : "FAIL");
|
||
|
|
|
||
|
|
ok = mie_resolve_op_successors(item->i_op, ctx);
|
||
|
|
if (!ok) {
|
||
|
|
result = false;
|
||
|
|
}
|
||
|
|
} while (mie_walker_step(&walker) == MIE_SUCCESS);
|
||
|
|
mie_walker_end(&walker);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool resolve_args(struct mie_op *op, struct mie_ctx *ctx)
|
||
|
|
{
|
||
|
|
char op_name[128];
|
||
|
|
enum mie_walker_flags walk_flags
|
||
|
|
= MIE_WALKER_F_INCLUDE_OPS | MIE_WALKER_F_PREORDER
|
||
|
|
| MIE_WALKER_F_FORWARD | MIE_WALKER_F_RECURSIVE;
|
||
|
|
struct mie_walker walker;
|
||
|
|
mie_walker_begin(&walker, op, walk_flags);
|
||
|
|
bool result = true;
|
||
|
|
|
||
|
|
do {
|
||
|
|
const struct mie_walk_item *item = mie_walker_get(&walker);
|
||
|
|
struct mie_op *op = item->i_op;
|
||
|
|
mie_op_get_name(op, op_name, sizeof op_name);
|
||
|
|
|
||
|
|
// printf("resolving args: %p %s... ", item->i_op, op_name);
|
||
|
|
bool ok = mie_resolve_op_args(op, ctx);
|
||
|
|
// printf("%s\n", ok ? "OK" : "FAIL");
|
||
|
|
|
||
|
|
if (!ok) {
|
||
|
|
result = false;
|
||
|
|
}
|
||
|
|
} while (mie_walker_step(&walker) == MIE_SUCCESS);
|
||
|
|
mie_walker_end(&walker);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool refresh_function_dominance_trees(struct mie_op *op, struct mie_ctx *ctx)
|
||
|
|
{
|
||
|
|
char op_name[128];
|
||
|
|
enum mie_walker_flags walk_flags
|
||
|
|
= MIE_WALKER_F_INCLUDE_OPS | MIE_WALKER_F_POSTORDER
|
||
|
|
| MIE_WALKER_F_FORWARD | MIE_WALKER_F_RECURSIVE;
|
||
|
|
struct mie_walker walker;
|
||
|
|
mie_walker_begin(&walker, op, walk_flags);
|
||
|
|
bool result = true;
|
||
|
|
|
||
|
|
do {
|
||
|
|
const struct mie_walk_item *item = mie_walker_get(&walker);
|
||
|
|
struct mie_op *op = item->i_op;
|
||
|
|
if (!mie_op_has_trait(op, "func", "function-like")) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
mie_op_get_name(op, op_name, sizeof op_name);
|
||
|
|
|
||
|
|
// printf("calculating dom-tree: %p %s...\n", item->i_op, op_name);
|
||
|
|
struct mie_region *region = mie_op_get_first_region(op);
|
||
|
|
if (!region) {
|
||
|
|
/* TODO diagnostic message */
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
mie_region_refresh_dominance(region);
|
||
|
|
} while (mie_walker_step(&walker) == MIE_SUCCESS);
|
||
|
|
mie_walker_end(&walker);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool resolve_op(struct mie_op *op, struct mie_ctx *ctx)
|
||
|
|
{
|
||
|
|
/* first, resolve the op-definitions and block references */
|
||
|
|
if (!resolve_self_and_successors(op, ctx)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* next, calculation the block dominator tree for all function-like
|
||
|
|
* ops. */
|
||
|
|
refresh_function_dominance_trees(op, ctx);
|
||
|
|
|
||
|
|
/* next, resolve all op arguments */
|
||
|
|
if (!resolve_args(op, ctx)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|