mie: implement block dominance calculation using lengauer-tarjan algorithm
This commit is contained in:
@@ -43,7 +43,6 @@ MIE_API void mie_ctx_destroy(struct mie_ctx *ctx);
|
|||||||
|
|
||||||
MIE_API struct mie_op *mie_ctx_create_op(
|
MIE_API struct mie_op *mie_ctx_create_op(
|
||||||
const struct mie_ctx *ctx, const char *dialect, const char *op);
|
const struct mie_ctx *ctx, const char *dialect, const char *op);
|
||||||
MIE_API bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op);
|
|
||||||
|
|
||||||
MIE_API struct mie_dialect *mie_ctx_get_dialect(
|
MIE_API struct mie_dialect *mie_ctx_get_dialect(
|
||||||
const struct mie_ctx *ctx, const char *name);
|
const struct mie_ctx *ctx, const char *name);
|
||||||
|
|||||||
@@ -6,13 +6,26 @@
|
|||||||
#include <mie/name.h>
|
#include <mie/name.h>
|
||||||
#include <mie/vector.h>
|
#include <mie/vector.h>
|
||||||
|
|
||||||
|
#define MIE_BLOCK_ID_INVALID ((size_t)0)
|
||||||
|
|
||||||
struct mie_op;
|
struct mie_op;
|
||||||
struct mie_register;
|
struct mie_register;
|
||||||
|
|
||||||
|
struct mie_block_predecessor {
|
||||||
|
struct mie_block *p_block;
|
||||||
|
};
|
||||||
|
|
||||||
struct mie_block {
|
struct mie_block {
|
||||||
struct mie_name b_name;
|
struct mie_name b_name;
|
||||||
struct mie_region *b_parent;
|
struct mie_region *b_parent;
|
||||||
|
|
||||||
|
/* immediate predecessor blocks */
|
||||||
|
MIE_VECTOR_DECLARE(struct mie_block_predecessor, b_ipred);
|
||||||
|
|
||||||
/* used by struct mie_region */
|
/* used by struct mie_region */
|
||||||
|
unsigned int b_id;
|
||||||
|
struct mie_block *b_idom;
|
||||||
|
// struct mie_block *b_sdom, *b_dfs_parent;
|
||||||
b_queue_entry b_entry;
|
b_queue_entry b_entry;
|
||||||
|
|
||||||
MIE_VECTOR_DECLARE(struct mie_register, b_params);
|
MIE_VECTOR_DECLARE(struct mie_register, b_params);
|
||||||
@@ -29,9 +42,33 @@ MIE_API struct mie_op *mie_block_get_next_op(
|
|||||||
const struct mie_block *block, const struct mie_op *after);
|
const struct mie_block *block, const struct mie_op *after);
|
||||||
MIE_API struct mie_op *mie_block_get_last_op(const struct mie_block *block);
|
MIE_API struct mie_op *mie_block_get_last_op(const struct mie_block *block);
|
||||||
|
|
||||||
|
MIE_API struct mie_op *mie_block_get_terminator(const struct mie_block *block);
|
||||||
|
|
||||||
|
MIE_API struct mie_op_successor *mie_block_get_first_successor(
|
||||||
|
const struct mie_block *block);
|
||||||
|
MIE_API struct mie_op_successor *mie_block_get_prev_successor(
|
||||||
|
const struct mie_block *block, const struct mie_op_successor *before);
|
||||||
|
MIE_API struct mie_op_successor *mie_block_get_next_successor(
|
||||||
|
const struct mie_block *block, const struct mie_op_successor *after);
|
||||||
|
MIE_API struct mie_op_successor *mie_block_get_last_successor(
|
||||||
|
const struct mie_block *block);
|
||||||
|
|
||||||
|
MIE_API struct mie_block_predecessor *mie_block_get_first_predecessor(
|
||||||
|
const struct mie_block *block);
|
||||||
|
MIE_API struct mie_block_predecessor *mie_block_get_prev_predecessor(
|
||||||
|
const struct mie_block *block, const struct mie_block_predecessor *before);
|
||||||
|
MIE_API struct mie_block_predecessor *mie_block_get_next_predecessor(
|
||||||
|
const struct mie_block *block, const struct mie_block_predecessor *after);
|
||||||
|
MIE_API struct mie_block_predecessor *mie_block_get_last_predecessor(
|
||||||
|
const struct mie_block *block);
|
||||||
|
|
||||||
MIE_API struct mie_op *mie_block_add_op(struct mie_block *block);
|
MIE_API struct mie_op *mie_block_add_op(struct mie_block *block);
|
||||||
MIE_API struct mie_op *mie_block_add_op_after(
|
MIE_API struct mie_op *mie_block_add_op_after(
|
||||||
struct mie_block *block, struct mie_op *after);
|
struct mie_block *block, struct mie_op *after);
|
||||||
MIE_API struct mie_register *mie_block_add_param(struct mie_block *block);
|
MIE_API struct mie_register *mie_block_add_param(struct mie_block *block);
|
||||||
|
|
||||||
|
MIE_API struct mie_register *mie_block_find_register(
|
||||||
|
const struct mie_block *block, const char *name,
|
||||||
|
const struct mie_op *start_point);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#include <mie/name.h>
|
#include <mie/name.h>
|
||||||
#include <mie/parse/file-span.h>
|
#include <mie/parse/file-span.h>
|
||||||
|
|
||||||
|
struct mie_ctx;
|
||||||
struct mie_type;
|
struct mie_type;
|
||||||
|
|
||||||
struct mie_value;
|
struct mie_value;
|
||||||
struct mie_block;
|
struct mie_block;
|
||||||
struct mie_region;
|
struct mie_region;
|
||||||
@@ -37,6 +37,7 @@ struct mie_op_arg {
|
|||||||
|
|
||||||
struct mie_op_successor {
|
struct mie_op_successor {
|
||||||
enum mie_op_flags s_flags;
|
enum mie_op_flags s_flags;
|
||||||
|
struct mie_file_span s_name_span;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
/* only valid if F_SUCCESSOR_RESOLVED is set in s_flags; */
|
/* only valid if F_SUCCESSOR_RESOLVED is set in s_flags; */
|
||||||
@@ -53,8 +54,8 @@ struct mie_op {
|
|||||||
/* used by struct mie_block */
|
/* used by struct mie_block */
|
||||||
b_queue_entry op_entry;
|
b_queue_entry op_entry;
|
||||||
|
|
||||||
/* these pointers are only valid if the F_OP_RESOLVED flag is set */
|
struct mie_line_source *op_src;
|
||||||
const struct mie_dialect *op_dialect;
|
/* this pointer is only valid if the F_OP_RESOLVED flag is set */
|
||||||
const struct mie_op_definition *op_info;
|
const struct mie_op_definition *op_info;
|
||||||
|
|
||||||
struct mie_block *op_container;
|
struct mie_block *op_container;
|
||||||
@@ -78,6 +79,10 @@ MIE_API void mie_op_cleanup(struct mie_op *op);
|
|||||||
|
|
||||||
MIE_API size_t mie_op_get_name(const struct mie_op *op, char *out, size_t max);
|
MIE_API size_t mie_op_get_name(const struct mie_op *op, char *out, size_t max);
|
||||||
|
|
||||||
|
MIE_API bool mie_op_resolve_self(struct mie_op *op, struct mie_ctx *ctx);
|
||||||
|
MIE_API bool mie_op_resolve_args(struct mie_op *op, struct mie_ctx *ctx);
|
||||||
|
MIE_API bool mie_op_resolve_successors(struct mie_op *op, struct mie_ctx *ctx);
|
||||||
|
|
||||||
MIE_API struct mie_op_arg *mie_op_add_arg(struct mie_op *op);
|
MIE_API struct mie_op_arg *mie_op_add_arg(struct mie_op *op);
|
||||||
MIE_API struct mie_register *mie_op_add_result(
|
MIE_API struct mie_register *mie_op_add_result(
|
||||||
struct mie_op *op, const struct mie_type *ty);
|
struct mie_op *op, const struct mie_type *ty);
|
||||||
@@ -102,6 +107,8 @@ MIE_API struct mie_region *mie_op_get_next_region(
|
|||||||
MIE_API struct mie_region *mie_op_get_last_region(const struct mie_op *op);
|
MIE_API struct mie_region *mie_op_get_last_region(const struct mie_op *op);
|
||||||
|
|
||||||
MIE_API struct mie_register *mie_op_get_arg(const struct mie_op *op, size_t index);
|
MIE_API struct mie_register *mie_op_get_arg(const struct mie_op *op, size_t index);
|
||||||
|
MIE_API struct mie_register *mie_op_get_result_with_name(
|
||||||
|
const struct mie_op *op, const char *name);
|
||||||
|
|
||||||
MIE_API struct mie_op *mie_op_get_first_child_op(const struct mie_op *op);
|
MIE_API struct mie_op *mie_op_get_first_child_op(const struct mie_op *op);
|
||||||
MIE_API struct mie_op *mie_op_get_last_child_op(const struct mie_op *op);
|
MIE_API struct mie_op *mie_op_get_last_child_op(const struct mie_op *op);
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
#ifndef MIE_IR_REGION_H_
|
#ifndef MIE_IR_REGION_H_
|
||||||
#define MIE_IR_REGION_H_
|
#define MIE_IR_REGION_H_
|
||||||
|
|
||||||
|
#include <blue/core/btree.h>
|
||||||
#include <blue/core/queue.h>
|
#include <blue/core/queue.h>
|
||||||
#include <mie/misc.h>
|
#include <mie/misc.h>
|
||||||
#include <mie/vector.h>
|
#include <mie/vector.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct mie_op;
|
struct mie_op;
|
||||||
|
struct mie_ctx;
|
||||||
struct mie_block;
|
struct mie_block;
|
||||||
|
|
||||||
struct mie_region {
|
struct mie_region {
|
||||||
@@ -16,6 +18,9 @@ struct mie_region {
|
|||||||
b_queue_entry r_entry;
|
b_queue_entry r_entry;
|
||||||
/* queue of struct mie_block */
|
/* queue of struct mie_block */
|
||||||
b_queue r_blocks;
|
b_queue r_blocks;
|
||||||
|
/* bst of struct mie_block, as numbered by a depth-first search.
|
||||||
|
* this ordering is recalculated by mie_region_refresh_dominance */
|
||||||
|
b_btree r_blocks_s;
|
||||||
};
|
};
|
||||||
|
|
||||||
MIE_API struct mie_block *mie_region_get_first_block(
|
MIE_API struct mie_block *mie_region_get_first_block(
|
||||||
@@ -29,5 +34,22 @@ MIE_API struct mie_block *mie_region_get_last_block(const struct mie_region *reg
|
|||||||
MIE_API struct mie_block *mie_region_add_block(struct mie_region *region);
|
MIE_API struct mie_block *mie_region_add_block(struct mie_region *region);
|
||||||
MIE_API struct mie_block *mie_region_add_block_after(
|
MIE_API struct mie_block *mie_region_add_block_after(
|
||||||
struct mie_region *region, struct mie_block *after);
|
struct mie_region *region, struct mie_block *after);
|
||||||
|
MIE_API struct mie_block *mie_region_find_block(
|
||||||
|
const struct mie_region *region, const char *name);
|
||||||
|
MIE_API struct mie_register *mie_region_find_register(
|
||||||
|
const struct mie_region *region, const char *name);
|
||||||
|
|
||||||
|
/* calculate the dominance-tree of all blocks in a region.
|
||||||
|
* this function populates the following attributes of every block in the
|
||||||
|
* region:
|
||||||
|
* b_id
|
||||||
|
* b_node
|
||||||
|
* b_parent
|
||||||
|
* as well as the following attributes of the region itself:
|
||||||
|
* r_blocks_s
|
||||||
|
* only top-level blocks and ops are considered by this function. if an op
|
||||||
|
* within the region itself contains one/more child regions, these are ignored.
|
||||||
|
*/
|
||||||
|
MIE_API void mie_region_refresh_dominance(struct mie_region *region);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ struct mie_register_use {
|
|||||||
|
|
||||||
struct mie_register {
|
struct mie_register {
|
||||||
enum mie_register_flags reg_flags;
|
enum mie_register_flags reg_flags;
|
||||||
|
struct mie_file_span reg_span;
|
||||||
union {
|
union {
|
||||||
/* only valid if F_VIRTUAL is set. */
|
/* only valid if F_VIRTUAL is set. */
|
||||||
struct mie_name reg_name;
|
struct mie_name reg_name;
|
||||||
|
|||||||
14
mie/include/mie/ir/resolve.h
Normal file
14
mie/include/mie/ir/resolve.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef MIE_IR_RESOLVE_H_
|
||||||
|
#define MIE_IR_RESOLVE_H_
|
||||||
|
|
||||||
|
#include <mie/misc.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct mie_op;
|
||||||
|
struct mie_ctx;
|
||||||
|
|
||||||
|
MIE_API bool mie_resolve_op_self(struct mie_op *op, struct mie_ctx *ctx);
|
||||||
|
MIE_API bool mie_resolve_op_args(struct mie_op *op, struct mie_ctx *ctx);
|
||||||
|
MIE_API bool mie_resolve_op_successors(struct mie_op *op, struct mie_ctx *ctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -59,7 +59,7 @@ struct mie_name {
|
|||||||
|
|
||||||
/* if this name was read from a file, these structs can be used to
|
/* if this name was read from a file, these structs can be used to
|
||||||
* record the location within the file where the name is found. */
|
* record the location within the file where the name is found. */
|
||||||
struct mie_file_span n_start, n_end;
|
struct mie_file_span n_span;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mie_name_map {
|
struct mie_name_map {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ MIE_API struct mie_lex *mie_lex_create(
|
|||||||
MIE_API void mie_lex_destroy(struct mie_lex *lex);
|
MIE_API void mie_lex_destroy(struct mie_lex *lex);
|
||||||
|
|
||||||
MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex);
|
MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex);
|
||||||
|
MIE_API struct mie_line_source *mie_lex_get_line_source(const struct mie_lex *lex);
|
||||||
MIE_API struct mie_token *mie_lex_peek(struct mie_lex *lex);
|
MIE_API struct mie_token *mie_lex_peek(struct mie_lex *lex);
|
||||||
MIE_API void mie_lex_advance(struct mie_lex *lex);
|
MIE_API void mie_lex_advance(struct mie_lex *lex);
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ enum mie_print_flags {
|
|||||||
MIE_PRINT_F_INCLUDE_TYPE = 0x04u,
|
MIE_PRINT_F_INCLUDE_TYPE = 0x04u,
|
||||||
MIE_PRINT_F_EXCLUDE_BLOCK_HEADER = 0x08u,
|
MIE_PRINT_F_EXCLUDE_BLOCK_HEADER = 0x08u,
|
||||||
MIE_PRINT_F_EXCLUDE_FIRST_BLOCK_HEADER = 0x10u,
|
MIE_PRINT_F_EXCLUDE_FIRST_BLOCK_HEADER = 0x10u,
|
||||||
|
|
||||||
|
MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS = 0x20u,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mie_printer {
|
struct mie_printer {
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ struct mie_vector_ops {
|
|||||||
&(vector.max), ops)
|
&(vector.max), ops)
|
||||||
#define mie_vector_pop_back(vector, ops) \
|
#define mie_vector_pop_back(vector, ops) \
|
||||||
__mie_vector_pop_back( \
|
__mie_vector_pop_back( \
|
||||||
(void **)&(vector), sizeof *vector, &(vector.count), \
|
(void **)&(vector.items), sizeof *vector.items, \
|
||||||
&(vector.max), ops)
|
&(vector.count), &(vector.max), ops)
|
||||||
#define mie_vector_emplace_back(vector, ops) \
|
#define mie_vector_emplace_back(vector, ops) \
|
||||||
__mie_vector_emplace_back( \
|
__mie_vector_emplace_back( \
|
||||||
(void **)&(vector.items), sizeof *vector.items, \
|
(void **)&(vector.items), sizeof *vector.items, \
|
||||||
@@ -86,6 +86,10 @@ struct mie_vector_ops {
|
|||||||
__mie_vector_destroy( \
|
__mie_vector_destroy( \
|
||||||
(void **)(vector), sizeof **vector, (vector##_count), \
|
(void **)(vector), sizeof **vector, (vector##_count), \
|
||||||
(vector##_max), ops)
|
(vector##_max), ops)
|
||||||
|
#define mie_vector_ref_get_item(vector, index) (*vector)[index]
|
||||||
|
#define mie_vector_ref_get_item_ptr(vector, index) (&(*vector)[index])
|
||||||
|
#define mie_vector_ref_get_count(vector) *(vector##_count)
|
||||||
|
#define mie_vector_ref_get_max(vector) *(vector##_count)
|
||||||
|
|
||||||
/* don't use these functions */
|
/* don't use these functions */
|
||||||
MIE_API int __mie_vector_push_back(
|
MIE_API int __mie_vector_push_back(
|
||||||
|
|||||||
166
mie/ir/block.c
166
mie/ir/block.c
@@ -52,6 +52,144 @@ struct mie_op *mie_block_get_last_op(const struct mie_block *block)
|
|||||||
return b_unbox(struct mie_op, entry, op_entry);
|
return b_unbox(struct mie_op, entry, op_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mie_op *mie_block_get_terminator(const struct mie_block *block)
|
||||||
|
{
|
||||||
|
b_queue_entry *op_entry = b_queue_last(&block->b_ops);
|
||||||
|
return b_unbox(struct mie_op, op_entry, op_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_op_successor *mie_block_get_first_successor(const struct mie_block *block)
|
||||||
|
{
|
||||||
|
struct mie_op *op = mie_block_get_terminator(block);
|
||||||
|
if (!op) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MIE_VECTOR_COUNT(op->op_successors) == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &op->op_successors.items[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_op_successor *mie_block_get_prev_successor(
|
||||||
|
const struct mie_block *block, const struct mie_op_successor *before)
|
||||||
|
{
|
||||||
|
struct mie_op *op = mie_block_get_terminator(block);
|
||||||
|
if (!op) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MIE_VECTOR_COUNT(op->op_successors) == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = before - &op->op_successors.items[0];
|
||||||
|
if (i == 0 || i >= MIE_VECTOR_COUNT(op->op_successors)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &op->op_successors.items[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_op_successor *mie_block_get_next_successor(
|
||||||
|
const struct mie_block *block, const struct mie_op_successor *after)
|
||||||
|
{
|
||||||
|
struct mie_op *op = mie_block_get_terminator(block);
|
||||||
|
if (!op) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MIE_VECTOR_COUNT(op->op_successors) == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = after - &op->op_successors.items[0];
|
||||||
|
if (i >= MIE_VECTOR_COUNT(op->op_successors)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 >= MIE_VECTOR_COUNT(op->op_successors)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &op->op_successors.items[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_op_successor *mie_block_get_last_successor(const struct mie_block *block)
|
||||||
|
{
|
||||||
|
struct mie_op *op = mie_block_get_terminator(block);
|
||||||
|
if (!op) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nr_successors = MIE_VECTOR_COUNT(op->op_successors);
|
||||||
|
|
||||||
|
if (nr_successors == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &op->op_successors.items[nr_successors - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_block_predecessor *mie_block_get_first_predecessor(
|
||||||
|
const struct mie_block *block)
|
||||||
|
{
|
||||||
|
size_t nr_predecessors = MIE_VECTOR_COUNT(block->b_ipred);
|
||||||
|
|
||||||
|
if (nr_predecessors == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &block->b_ipred.items[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_block_predecessor *mie_block_get_prev_predecessor(
|
||||||
|
const struct mie_block *block, const struct mie_block_predecessor *before)
|
||||||
|
{
|
||||||
|
if (MIE_VECTOR_COUNT(block->b_ipred) == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = before - &block->b_ipred.items[0];
|
||||||
|
if (i == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &block->b_ipred.items[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_block_predecessor *mie_block_get_next_predecessor(
|
||||||
|
const struct mie_block *block, const struct mie_block_predecessor *after)
|
||||||
|
{
|
||||||
|
if (MIE_VECTOR_COUNT(block->b_ipred) == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = after - &block->b_ipred.items[0];
|
||||||
|
if (i >= MIE_VECTOR_COUNT(block->b_ipred)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 >= MIE_VECTOR_COUNT(block->b_ipred)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &block->b_ipred.items[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_block_predecessor *mie_block_get_last_predecessor(
|
||||||
|
const struct mie_block *block)
|
||||||
|
{
|
||||||
|
size_t nr_predecessors = MIE_VECTOR_COUNT(block->b_ipred);
|
||||||
|
|
||||||
|
if (nr_predecessors == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &block->b_ipred.items[nr_predecessors - 1];
|
||||||
|
}
|
||||||
|
|
||||||
struct mie_op *mie_block_add_op(struct mie_block *block)
|
struct mie_op *mie_block_add_op(struct mie_block *block)
|
||||||
{
|
{
|
||||||
struct mie_op *op = malloc(sizeof *op);
|
struct mie_op *op = malloc(sizeof *op);
|
||||||
@@ -100,3 +238,31 @@ struct mie_register *mie_block_add_param(struct mie_block *block)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mie_register *mie_block_find_register(
|
||||||
|
const struct mie_block *block, const char *name,
|
||||||
|
const struct mie_op *start_point)
|
||||||
|
{
|
||||||
|
const b_queue_entry *entry = b_queue_last(&block->b_ops);
|
||||||
|
if (start_point) {
|
||||||
|
entry = &start_point->op_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MIE_VECTOR_COUNT(block->b_params); i++) {
|
||||||
|
if (!strcmp(block->b_params.items[i].reg_name.n_str, name)) {
|
||||||
|
return &block->b_params.items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (entry) {
|
||||||
|
struct mie_op *op = b_unbox(struct mie_op, entry, op_entry);
|
||||||
|
struct mie_register *reg = mie_op_get_result_with_name(op, name);
|
||||||
|
if (reg) {
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = b_queue_prev(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
16
mie/ir/op.c
16
mie/ir/op.c
@@ -1,4 +1,8 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <mie/ctx.h>
|
||||||
|
#include <mie/diag/diag.h>
|
||||||
|
#include <mie/diag/highlight.h>
|
||||||
|
#include <mie/dialect/builtin.h>
|
||||||
#include <mie/dialect/dialect.h>
|
#include <mie/dialect/dialect.h>
|
||||||
#include <mie/ir/block.h>
|
#include <mie/ir/block.h>
|
||||||
#include <mie/ir/op-definition.h>
|
#include <mie/ir/op-definition.h>
|
||||||
@@ -260,6 +264,18 @@ struct mie_register *mie_op_get_arg(const struct mie_op *op, size_t index)
|
|||||||
return arg->arg_value.u_reg;
|
return arg->arg_value.u_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mie_register *mie_op_get_result_with_name(
|
||||||
|
const struct mie_op *op, const char *name)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
|
||||||
|
if (!strcmp(op->op_result.items[i].reg_name.n_str, name)) {
|
||||||
|
return &op->op_result.items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct mie_op *mie_op_get_first_child_op(const struct mie_op *op)
|
struct mie_op *mie_op_get_first_child_op(const struct mie_op *op)
|
||||||
{
|
{
|
||||||
struct mie_region *first_region = mie_op_get_first_region(op);
|
struct mie_region *first_region = mie_op_get_first_region(op);
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
#include <limits.h>
|
||||||
|
#include <mie/ctx.h>
|
||||||
|
#include <mie/diag/diag.h>
|
||||||
|
#include <mie/dialect/builtin.h>
|
||||||
#include <mie/ir/block.h>
|
#include <mie/ir/block.h>
|
||||||
|
#include <mie/ir/op.h>
|
||||||
#include <mie/ir/region.h>
|
#include <mie/ir/region.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -63,6 +68,7 @@ struct mie_block *mie_region_add_block(struct mie_region *region)
|
|||||||
|
|
||||||
memset(block, 0x0, sizeof *block);
|
memset(block, 0x0, sizeof *block);
|
||||||
block->b_parent = region;
|
block->b_parent = region;
|
||||||
|
block->b_id = MIE_BLOCK_ID_INVALID;
|
||||||
|
|
||||||
b_queue_push_back(®ion->r_blocks, &block->b_entry);
|
b_queue_push_back(®ion->r_blocks, &block->b_entry);
|
||||||
|
|
||||||
@@ -89,3 +95,38 @@ struct mie_block *mie_region_add_block_after(
|
|||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mie_block *mie_region_find_block(
|
||||||
|
const struct mie_region *region, const char *name)
|
||||||
|
{
|
||||||
|
b_queue_entry *cur = b_queue_first(®ion->r_blocks);
|
||||||
|
while (cur) {
|
||||||
|
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
|
||||||
|
if (!strcmp(block->b_name.n_str, name)) {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = b_queue_next(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_register *mie_region_find_register(
|
||||||
|
const struct mie_region *region, const char *name)
|
||||||
|
{
|
||||||
|
b_queue_entry *cur = b_queue_first(®ion->r_blocks);
|
||||||
|
|
||||||
|
while (cur) {
|
||||||
|
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
|
||||||
|
struct mie_register *reg
|
||||||
|
= mie_block_find_register(block, name, NULL);
|
||||||
|
if (reg) {
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = b_queue_next(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
264
mie/ir/resolve.c
Normal file
264
mie/ir/resolve.c
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
#include <mie/ctx.h>
|
||||||
|
#include <mie/diag/diag.h>
|
||||||
|
#include <mie/diag/highlight.h>
|
||||||
|
#include <mie/dialect/builtin.h>
|
||||||
|
#include <mie/dialect/dialect.h>
|
||||||
|
#include <mie/ir/block.h>
|
||||||
|
#include <mie/ir/op.h>
|
||||||
|
#include <mie/ir/region.h>
|
||||||
|
#include <mie/ir/register.h>
|
||||||
|
|
||||||
|
enum register_find_result {
|
||||||
|
REG_FIND_NONE = 0,
|
||||||
|
REG_FIND_USE_BEFORE_DEFINE,
|
||||||
|
REG_FIND_UNDOMINATED,
|
||||||
|
REG_FIND_ISOLATED,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mie_op_resolve_self(struct mie_op *op, struct mie_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (op->op_flags & MIE_OP_F_OP_RESOLVED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dialect_name = NULL, *op_name = NULL;
|
||||||
|
|
||||||
|
char *dot = strchr(op->op_name, '.');
|
||||||
|
if (dot) {
|
||||||
|
*dot = 0;
|
||||||
|
dialect_name = op->op_name;
|
||||||
|
op_name = dot + 1;
|
||||||
|
} else {
|
||||||
|
dialect_name = NULL;
|
||||||
|
op_name = op->op_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct mie_dialect *dialect = mie_ctx_get_dialect(ctx, dialect_name);
|
||||||
|
if (dot) {
|
||||||
|
*dot = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dialect_name is no longer valid after this point */
|
||||||
|
dialect_name = NULL;
|
||||||
|
|
||||||
|
if (!dialect) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct mie_op_definition *op_info
|
||||||
|
= mie_dialect_get_op(dialect, op_name);
|
||||||
|
if (!op_info) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
op->op_info = op_info;
|
||||||
|
|
||||||
|
free(op->op_name);
|
||||||
|
op->op_name = NULL;
|
||||||
|
|
||||||
|
op->op_flags |= MIE_OP_F_OP_RESOLVED;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum register_find_result find_register_wide(
|
||||||
|
struct mie_op *op, const char *name, struct mie_register **out)
|
||||||
|
{
|
||||||
|
struct mie_region *region = op->op_container->b_parent;
|
||||||
|
enum register_find_result result = REG_FIND_UNDOMINATED;
|
||||||
|
struct mie_register *reg = NULL;
|
||||||
|
|
||||||
|
while (region) {
|
||||||
|
reg = mie_region_find_register(region, name);
|
||||||
|
if (reg) {
|
||||||
|
*out = reg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_op *op = region->r_parent;
|
||||||
|
if (mie_op_has_trait(op, "builtin", "isolated-from-above")) {
|
||||||
|
result = REG_FIND_ISOLATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
region = op->op_container ? op->op_container->b_parent : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reg) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg->reg_block == op->op_container) {
|
||||||
|
return REG_FIND_USE_BEFORE_DEFINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool resolve_arg(
|
||||||
|
struct mie_op *op, struct mie_op_arg *arg, struct mie_ctx *ctx)
|
||||||
|
{
|
||||||
|
const char *arg_name = arg->arg_unresolved.reg_name;
|
||||||
|
struct mie_block *block = op->op_container;
|
||||||
|
struct mie_op *search_start = op;
|
||||||
|
struct mie_register *reg = NULL;
|
||||||
|
|
||||||
|
while (block) {
|
||||||
|
reg = mie_block_find_register(block, arg_name, search_start);
|
||||||
|
if (reg) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
search_start = NULL;
|
||||||
|
block = block->b_idom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg) {
|
||||||
|
free(arg->arg_unresolved.reg_name);
|
||||||
|
arg->arg_flags |= MIE_OP_F_ARG_RESOLVED;
|
||||||
|
|
||||||
|
memset(&arg->arg_value, 0x0, sizeof arg->arg_value);
|
||||||
|
arg->arg_value.u_reg = reg;
|
||||||
|
arg->arg_value.u_user = op;
|
||||||
|
b_queue_push_back(®->reg_use, &arg->arg_value.u_entry);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum register_find_result find_result
|
||||||
|
= find_register_wide(op, arg_name, ®);
|
||||||
|
|
||||||
|
struct mie_diag *diag = mie_ctx_push_diag(
|
||||||
|
ctx, op->op_src, &arg->arg_span.s_start, "builtin",
|
||||||
|
MIE_BUILTIN_E_UNRESOLVED_VALUE);
|
||||||
|
mie_diag_push_msg(diag, ctx, "builtin", MIE_BUILTIN_MSG_UNRESOLVED_VALUE);
|
||||||
|
|
||||||
|
struct mie_diag_highlight hl[] = {
|
||||||
|
{
|
||||||
|
.hl_type = MIE_DIAG_HIGHLIGHT_ERROR,
|
||||||
|
.hl_span = arg->arg_span,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mie_diag_push_snippet(
|
||||||
|
diag, arg->arg_span.s_start.c_row, arg->arg_span.s_end.c_row,
|
||||||
|
NULL, 0, hl, 1);
|
||||||
|
|
||||||
|
if (!reg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_block *reg_container = reg->reg_block;
|
||||||
|
|
||||||
|
switch (find_result) {
|
||||||
|
case REG_FIND_ISOLATED:
|
||||||
|
mie_diag_push_msg(
|
||||||
|
diag, ctx, "builtin",
|
||||||
|
MIE_BUILTIN_MSG_VALUE_DEFINED_OUTSIDE_ISOLATED_REGION);
|
||||||
|
break;
|
||||||
|
case REG_FIND_UNDOMINATED:
|
||||||
|
mie_diag_push_msg(
|
||||||
|
diag, ctx, "builtin",
|
||||||
|
MIE_BUILTIN_MSG_VALUE_DEFINED_IN_NON_DOMINANT_BLOCK);
|
||||||
|
break;
|
||||||
|
case REG_FIND_USE_BEFORE_DEFINE:
|
||||||
|
mie_diag_push_msg(
|
||||||
|
diag, ctx, "builtin",
|
||||||
|
MIE_BUILTIN_MSG_VALUE_DEFINED_AFTER_USE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hl[0].hl_type = MIE_DIAG_HIGHLIGHT_HINT;
|
||||||
|
hl[0].hl_span = reg->reg_span;
|
||||||
|
|
||||||
|
mie_diag_push_snippet(
|
||||||
|
diag, reg->reg_span.s_start.c_row, reg->reg_span.s_end.c_row,
|
||||||
|
NULL, 0, hl, 1);
|
||||||
|
|
||||||
|
if (!reg_container) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hl[0].hl_span = reg_container->b_name.n_span;
|
||||||
|
|
||||||
|
mie_diag_push_snippet(
|
||||||
|
diag, reg_container->b_name.n_span.s_start.c_row,
|
||||||
|
reg_container->b_name.n_span.s_end.c_row, NULL, 0, hl, 1);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool resolve_successor(
|
||||||
|
struct mie_op *op, struct mie_op_successor *s, struct mie_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (s->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_block *container = op->op_container;
|
||||||
|
struct mie_region *region = container ? container->b_parent : NULL;
|
||||||
|
if (!region) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_diag *diag = NULL;
|
||||||
|
struct mie_block *dest = mie_region_find_block(region, s->s_block_name);
|
||||||
|
if (!dest) {
|
||||||
|
diag = mie_ctx_push_diag(
|
||||||
|
ctx, op->op_src, &s->s_name_span.s_start, "builtin",
|
||||||
|
MIE_BUILTIN_E_UNRESOLVED_SUCCESSOR);
|
||||||
|
mie_diag_push_msg(
|
||||||
|
diag, ctx, "builtin", MIE_BUILTIN_MSG_CANNOT_FIND_BLOCK);
|
||||||
|
const struct mie_diag_highlight hl[] = {
|
||||||
|
{
|
||||||
|
.hl_type = MIE_DIAG_HIGHLIGHT_ERROR,
|
||||||
|
.hl_span = s->s_name_span,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
mie_diag_push_snippet(
|
||||||
|
diag, s->s_name_span.s_start.c_row,
|
||||||
|
s->s_name_span.s_end.c_row, NULL, 0, hl, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(s->s_block_name);
|
||||||
|
s->s_block = dest;
|
||||||
|
s->s_flags |= MIE_OP_F_SUCCESSOR_RESOLVED;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mie_op_resolve_args(struct mie_op *op, struct mie_ctx *ctx)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
|
||||||
|
if (!resolve_arg(op, &op->op_args.items[i], ctx)) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) {
|
||||||
|
struct mie_op_successor *s = &op->op_successors.items[i];
|
||||||
|
for (size_t k = 0; k < MIE_VECTOR_COUNT(s->s_args); k++) {
|
||||||
|
if (!resolve_arg(op, &s->s_args.items[k], ctx)) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mie_op_resolve_successors(struct mie_op *op, struct mie_ctx *ctx)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) {
|
||||||
|
if (!resolve_successor(op, &op->op_successors.items[i], ctx)) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
254
mie/lt-idom.c
Normal file
254
mie/lt-idom.c
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
#include <mie/ir/block.h>
|
||||||
|
#include <mie/ir/op.h>
|
||||||
|
#include <mie/ir/region.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct set {
|
||||||
|
MIE_VECTOR_DECLARE(unsigned int, v);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dfs_stack_item {
|
||||||
|
struct mie_block *i_parent, *i_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lt_ctx {
|
||||||
|
size_t nr_nodes;
|
||||||
|
struct mie_block **vertex;
|
||||||
|
struct set *bucket;
|
||||||
|
unsigned int *semi;
|
||||||
|
unsigned int *idom;
|
||||||
|
unsigned int *samedom;
|
||||||
|
unsigned int *parent;
|
||||||
|
unsigned int *ancestor;
|
||||||
|
unsigned int *label;
|
||||||
|
|
||||||
|
MIE_VECTOR_DECLARE(struct dfs_stack_item, dfstack);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static B_BTREE_DEFINE_SIMPLE_INSERT(struct mie_block, b_node, b_id, put_block_by_id);
|
||||||
|
static B_BTREE_DEFINE_SIMPLE_GET(
|
||||||
|
struct mie_block, size_t, b_node, b_id, get_block_by_id);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void set_add(struct set *set, unsigned int val)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < MIE_VECTOR_COUNT(set->v); i++) {
|
||||||
|
if (set->v.items[i] == val) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mie_vector_push_back(set->v, &val, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mie_block *pop_block_successor(
|
||||||
|
MIE_VECTOR_REF_PARAM(struct mie_block *, successors))
|
||||||
|
{
|
||||||
|
size_t count = mie_vector_ref_get_count(successors);
|
||||||
|
if (count == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mie_block *out = mie_vector_ref_get_item(successors, count - 1);
|
||||||
|
mie_vector_ref_pop_back(successors, NULL);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enqueue_block_successors(
|
||||||
|
struct mie_block *block,
|
||||||
|
MIE_VECTOR_REF_PARAM(struct mie_block *, successors))
|
||||||
|
{
|
||||||
|
struct mie_op_successor *s = mie_block_get_first_successor(block);
|
||||||
|
struct mie_block_predecessor pred = {.p_block = block};
|
||||||
|
|
||||||
|
while (s) {
|
||||||
|
if (s->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
|
||||||
|
mie_vector_ref_push_back(successors, &s->s_block, NULL);
|
||||||
|
mie_vector_push_back(s->s_block->b_ipred, &pred, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = mie_block_get_next_successor(block, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dfs_stack_pop(
|
||||||
|
struct lt_ctx *ctx, struct mie_block **parent, struct mie_block **node)
|
||||||
|
{
|
||||||
|
size_t nr = MIE_VECTOR_COUNT(ctx->dfstack);
|
||||||
|
if (!nr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dfs_stack_item *item = &ctx->dfstack.items[nr - 1];
|
||||||
|
*parent = item->i_parent;
|
||||||
|
*node = item->i_node;
|
||||||
|
mie_vector_pop_back(ctx->dfstack, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dfs_stack_push(
|
||||||
|
struct lt_ctx *ctx, struct mie_block *parent, struct mie_block *node)
|
||||||
|
{
|
||||||
|
struct dfs_stack_item item = {.i_node = node, .i_parent = parent};
|
||||||
|
mie_vector_push_back(ctx->dfstack, &item, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dfs(struct lt_ctx *ctx, struct mie_block *root)
|
||||||
|
{
|
||||||
|
dfs_stack_push(ctx, NULL, root);
|
||||||
|
unsigned int id = 1;
|
||||||
|
|
||||||
|
while (MIE_VECTOR_COUNT(ctx->dfstack) > 0) {
|
||||||
|
struct mie_block *p, *n;
|
||||||
|
dfs_stack_pop(ctx, &p, &n);
|
||||||
|
|
||||||
|
if (n->b_id != MIE_BLOCK_ID_INVALID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("dfs(p=%s, n=%s)\n", p ? p->b_name.n_str : "NA",
|
||||||
|
n->b_name.n_str);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
n->b_id = id++;
|
||||||
|
ctx->vertex[n->b_id] = n;
|
||||||
|
ctx->semi[n->b_id] = n->b_id;
|
||||||
|
ctx->parent[n->b_id] = p ? p->b_id : MIE_BLOCK_ID_INVALID;
|
||||||
|
|
||||||
|
struct mie_op_successor *s = mie_block_get_first_successor(n);
|
||||||
|
while (s) {
|
||||||
|
dfs_stack_push(ctx, n, s->s_block);
|
||||||
|
mie_vector_push_back(s->s_block->b_ipred, &n, NULL);
|
||||||
|
s = mie_block_get_next_successor(n, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void link(struct lt_ctx *ctx, unsigned int parent, unsigned int node)
|
||||||
|
{
|
||||||
|
ctx->ancestor[node] = parent;
|
||||||
|
ctx->label[node] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int eval(struct lt_ctx *ctx, unsigned int v)
|
||||||
|
{
|
||||||
|
unsigned int a = ctx->ancestor[v];
|
||||||
|
if (ctx->ancestor[a] > MIE_BLOCK_ID_INVALID) {
|
||||||
|
unsigned int b = eval(ctx, a);
|
||||||
|
ctx->ancestor[v] = ctx->ancestor[a];
|
||||||
|
if (ctx->semi[b] < ctx->semi[ctx->label[v]]) {
|
||||||
|
ctx->label[v] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->label[v];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_block_relationship_metadata(struct mie_region *region)
|
||||||
|
{
|
||||||
|
b_queue_entry *cur = b_queue_first(®ion->r_blocks);
|
||||||
|
while (cur) {
|
||||||
|
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
|
||||||
|
|
||||||
|
block->b_id = MIE_BLOCK_ID_INVALID;
|
||||||
|
block->b_idom = NULL;
|
||||||
|
// block->b_sdom = block->b_dfs_parent = NULL;
|
||||||
|
mie_vector_destroy(block->b_ipred, NULL);
|
||||||
|
|
||||||
|
cur = b_queue_next(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(®ion->r_blocks_s, 0x0, sizeof region->r_blocks_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lt_ctx_init(struct lt_ctx *ctx, size_t nr_nodes)
|
||||||
|
{
|
||||||
|
memset(ctx, 0x0, sizeof *ctx);
|
||||||
|
ctx->idom = calloc(nr_nodes + 1, sizeof(unsigned int));
|
||||||
|
ctx->samedom = calloc(nr_nodes + 1, sizeof(unsigned int));
|
||||||
|
ctx->vertex = calloc(nr_nodes + 1, sizeof(struct mie_block *));
|
||||||
|
ctx->bucket = calloc(nr_nodes + 1, sizeof(struct set));
|
||||||
|
ctx->semi = calloc(nr_nodes + 1, sizeof(unsigned int));
|
||||||
|
ctx->parent = calloc(nr_nodes + 1, sizeof(unsigned int));
|
||||||
|
ctx->ancestor = calloc(nr_nodes + 1, sizeof(unsigned int));
|
||||||
|
ctx->label = calloc(nr_nodes + 1, sizeof(unsigned int));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lt_ctx_cleanup(struct lt_ctx *ctx)
|
||||||
|
{
|
||||||
|
free(ctx->idom);
|
||||||
|
free(ctx->samedom);
|
||||||
|
free(ctx->vertex);
|
||||||
|
free(ctx->bucket);
|
||||||
|
free(ctx->semi);
|
||||||
|
free(ctx->parent);
|
||||||
|
free(ctx->ancestor);
|
||||||
|
free(ctx->label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mie_region_refresh_dominance(struct mie_region *region)
|
||||||
|
{
|
||||||
|
struct lt_ctx ctx;
|
||||||
|
size_t nr_nodes = b_queue_length(®ion->r_blocks);
|
||||||
|
lt_ctx_init(&ctx, nr_nodes);
|
||||||
|
|
||||||
|
struct mie_block *root = mie_region_get_first_block(region);
|
||||||
|
|
||||||
|
reset_block_relationship_metadata(region);
|
||||||
|
dfs(&ctx, root);
|
||||||
|
|
||||||
|
for (size_t i = nr_nodes; i > 0; i--) {
|
||||||
|
struct mie_block *n = ctx.vertex[i];
|
||||||
|
unsigned int p = ctx.parent[i];
|
||||||
|
unsigned int s = p;
|
||||||
|
|
||||||
|
struct mie_block_predecessor *pred
|
||||||
|
= mie_block_get_first_predecessor(n);
|
||||||
|
while (pred) {
|
||||||
|
struct mie_block *v = pred->p_block;
|
||||||
|
unsigned int s_prime = MIE_BLOCK_ID_INVALID;
|
||||||
|
|
||||||
|
if (v->b_id <= n->b_id) {
|
||||||
|
s_prime = v->b_id;
|
||||||
|
} else {
|
||||||
|
s_prime = eval(&ctx, v->b_id);
|
||||||
|
s_prime = ctx.semi[s_prime];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_prime < s) {
|
||||||
|
s = s_prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
pred = mie_block_get_next_predecessor(n, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.semi[n->b_id] = s;
|
||||||
|
set_add(&ctx.bucket[s], n->b_id);
|
||||||
|
link(&ctx, p, n->b_id);
|
||||||
|
|
||||||
|
for (size_t k = 0; k < MIE_VECTOR_COUNT(ctx.bucket[p].v); k++) {
|
||||||
|
unsigned int v = ctx.bucket[p].v.items[k];
|
||||||
|
unsigned int y = eval(&ctx, v);
|
||||||
|
if (ctx.semi[y] == ctx.semi[p]) {
|
||||||
|
ctx.idom[v] = p;
|
||||||
|
} else {
|
||||||
|
ctx.samedom[v] = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 1; i <= nr_nodes; i++) {
|
||||||
|
struct mie_block *n = ctx.vertex[i];
|
||||||
|
if (ctx.samedom[i] > 0) {
|
||||||
|
ctx.idom[i] = ctx.idom[ctx.samedom[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
n->b_idom = ctx.vertex[ctx.idom[i]];
|
||||||
|
// n->b_sdom = ctx.vertex[ctx.semi[i]];
|
||||||
|
// n->b_dfs_parent = ctx.vertex[ctx.parent[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
lt_ctx_cleanup(&ctx);
|
||||||
|
}
|
||||||
@@ -211,6 +211,11 @@ enum mie_status mie_lex_get_status(const struct mie_lex *lex)
|
|||||||
return lex->lex_status;
|
return lex->lex_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mie_line_source *mie_lex_get_line_source(const struct mie_lex *lex)
|
||||||
|
{
|
||||||
|
return lex->lex_source;
|
||||||
|
}
|
||||||
|
|
||||||
static bool char_can_begin_symbol(char c)
|
static bool char_can_begin_symbol(char c)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < nr_symbols; i++) {
|
for (size_t i = 0; i < nr_symbols; i++) {
|
||||||
@@ -774,8 +779,10 @@ static enum mie_status pump_tokens(struct mie_lex *lex)
|
|||||||
= mie_line_source_get_cursor(lex->lex_source);
|
= mie_line_source_get_cursor(lex->lex_source);
|
||||||
unsigned long line = cursor->c_row;
|
unsigned long line = cursor->c_row;
|
||||||
const struct mie_diag_highlight hl[] = {
|
const struct mie_diag_highlight hl[] = {
|
||||||
{.hl_type = MIE_DIAG_HIGHLIGHT_ERROR,
|
{
|
||||||
.hl_span = {.s_start = *cursor, .s_end = *cursor}},
|
.hl_type = MIE_DIAG_HIGHLIGHT_ERROR,
|
||||||
|
.hl_span = {.s_start = *cursor, .s_end = *cursor},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const size_t nr_hl = sizeof hl / sizeof hl[0];
|
const size_t nr_hl = sizeof hl / sizeof hl[0];
|
||||||
mie_diag_push_snippet(diag, line, line, NULL, 0, hl, nr_hl);
|
mie_diag_push_snippet(diag, line, line, NULL, 0, hl, nr_hl);
|
||||||
|
|||||||
@@ -543,6 +543,8 @@ bool mie_parser_parse_operand(struct mie_parser *ctx, struct mie_op_arg *out)
|
|||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out->arg_span = loc;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,6 +613,8 @@ bool mie_parser_parse_parameter(struct mie_parser *ctx, struct mie_op_arg *out)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out->arg_span = loc;
|
||||||
|
|
||||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
|
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -710,6 +714,7 @@ bool mie_parser_parse_register(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out->reg_span = tok->tok_location;
|
||||||
mie_parser_advance(ctx);
|
mie_parser_advance(ctx);
|
||||||
|
|
||||||
return name != NULL;
|
return name != NULL;
|
||||||
@@ -927,6 +932,8 @@ bool mie_parser_parse_block(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(&block->b_name.n_span, &span, sizeof span);
|
||||||
|
|
||||||
if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN
|
if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN
|
||||||
&& !parse_block_parameters(ctx, names, block)) {
|
&& !parse_block_parameters(ctx, names, block)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -964,9 +971,8 @@ bool mie_parser_parse_successor(struct mie_parser *ctx, struct mie_op_successor
|
|||||||
memset(out, 0x0, sizeof *out);
|
memset(out, 0x0, sizeof *out);
|
||||||
b_string *str = get_temp_string(ctx);
|
b_string *str = get_temp_string(ctx);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
struct mie_file_span span;
|
|
||||||
|
|
||||||
if (!mie_parser_parse_blockname(ctx, str, &span)) {
|
if (!mie_parser_parse_blockname(ctx, str, &out->s_name_span)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1159,6 +1165,15 @@ bool mie_parser_parse_op(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MIE_VECTOR_COUNT(dest->op_result); i++) {
|
||||||
|
struct mie_register *reg = &dest->op_result.items[i];
|
||||||
|
reg->reg_flags |= MIE_REGISTER_F_OP_RESULT;
|
||||||
|
reg->reg_op = dest;
|
||||||
|
reg->reg_block = dest->op_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->op_src = mie_lex_get_line_source(ctx->p_lex);
|
||||||
|
|
||||||
if (mie_parser_check_type(ctx, MIE_TOK_NAME)) {
|
if (mie_parser_check_type(ctx, MIE_TOK_NAME)) {
|
||||||
/* custom-format operation */
|
/* custom-format operation */
|
||||||
return parse_custom_op(ctx, names, dest);
|
return parse_custom_op(ctx, names, dest);
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ void mie_printer_print_op_arg(
|
|||||||
enum mie_register_flags arg_flags = 0;
|
enum mie_register_flags arg_flags = 0;
|
||||||
const char *arg_name = NULL;
|
const char *arg_name = NULL;
|
||||||
const struct mie_type *arg_type = NULL;
|
const struct mie_type *arg_type = NULL;
|
||||||
|
bool resolved = false;
|
||||||
|
|
||||||
if (MIE_TEST_FLAGS(arg->arg_flags, MIE_OP_F_ARG_RESOLVED)) {
|
if (MIE_TEST_FLAGS(arg->arg_flags, MIE_OP_F_ARG_RESOLVED)) {
|
||||||
|
resolved = true;
|
||||||
|
|
||||||
if (!arg->arg_value.u_reg) {
|
if (!arg->arg_value.u_reg) {
|
||||||
|
/* this should only be caused by an internal parser/rewriter bug */
|
||||||
arg_flags = 0;
|
arg_flags = 0;
|
||||||
arg_name = "<NULL>";
|
arg_name = "<NULL>";
|
||||||
arg_type = NULL;
|
arg_type = NULL;
|
||||||
@@ -36,6 +40,12 @@ void mie_printer_print_op_arg(
|
|||||||
|
|
||||||
b_stream_write_string(printer->p_stream, arg_name, NULL);
|
b_stream_write_string(printer->p_stream, arg_name, NULL);
|
||||||
|
|
||||||
|
if (!resolved
|
||||||
|
&& MIE_TEST_FLAGS(
|
||||||
|
printer->p_flags, MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS)) {
|
||||||
|
b_stream_write_char(printer->p_stream, '?');
|
||||||
|
}
|
||||||
|
|
||||||
if (!include_type || !arg_type) {
|
if (!include_type || !arg_type) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -50,14 +60,23 @@ void mie_printer_print_op_successor(
|
|||||||
bool compact)
|
bool compact)
|
||||||
{
|
{
|
||||||
b_stream_write_char(printer->p_stream, '^');
|
b_stream_write_char(printer->p_stream, '^');
|
||||||
|
bool resolved = false;
|
||||||
|
|
||||||
if (successor->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
|
if (successor->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
|
||||||
b_stream_write_string(
|
b_stream_write_string(
|
||||||
printer->p_stream, successor->s_block->b_name.n_str, NULL);
|
printer->p_stream, successor->s_block->b_name.n_str, NULL);
|
||||||
|
resolved = true;
|
||||||
} else {
|
} else {
|
||||||
b_stream_write_string(
|
b_stream_write_string(
|
||||||
printer->p_stream, successor->s_block_name, NULL);
|
printer->p_stream, successor->s_block_name, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!resolved
|
||||||
|
&& MIE_TEST_FLAGS(
|
||||||
|
printer->p_flags, MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS)) {
|
||||||
|
b_stream_write_char(printer->p_stream, '?');
|
||||||
|
}
|
||||||
|
|
||||||
if (MIE_VECTOR_COUNT(successor->s_args) == 0) {
|
if (MIE_VECTOR_COUNT(successor->s_args) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -210,6 +229,11 @@ static void print_generic_op(struct mie_printer *printer, const struct mie_op *o
|
|||||||
op->op_info->op_parent->d_name, op->op_info->op_name);
|
op->op_info->op_parent->d_name, op->op_info->op_name);
|
||||||
} else {
|
} else {
|
||||||
b_stream_write_string(printer->p_stream, op->op_name, NULL);
|
b_stream_write_string(printer->p_stream, op->op_name, NULL);
|
||||||
|
|
||||||
|
if (MIE_TEST_FLAGS(
|
||||||
|
printer->p_flags, MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS)) {
|
||||||
|
b_stream_write_char(printer->p_stream, '?');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b_stream_write_char(printer->p_stream, '(');
|
b_stream_write_char(printer->p_stream, '(');
|
||||||
|
|||||||
Reference in New Issue
Block a user