diff --git a/mie/builder.c b/mie/builder.c index 2078fba..6fb237c 100644 --- a/mie/builder.c +++ b/mie/builder.c @@ -478,7 +478,33 @@ struct mie_value *mie_builder_br_if( struct mie_builder *builder, struct mie_value *cond, struct mie_block *if_true, struct mie_block *if_false) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_branch_if *br = malloc(sizeof *br); + if (!br) { + return NULL; + } + + memset(br, 0x0, sizeof *br); + + mie_instr_init(&br->b_base, MIE_INSTR_BR_IF); + + br->b_cond = cond; + br->b_true_block = if_true; + br->b_false_block = if_false; + + if (!mie_block_add_instr(builder->b_current_block, &br->b_base)) { + free(br); + return NULL; + } + + return MIE_VALUE(br); } struct mie_value *mie_builder_msg( @@ -533,35 +559,216 @@ struct mie_value *mie_builder_cmp_eq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_binary_op *sub = malloc(sizeof *sub); + if (!sub) { + return NULL; + } + + memset(sub, 0x0, sizeof *sub); + + mie_instr_init(&sub->op_base, MIE_INSTR_CMP_EQ); + + sub->op_left = left; + sub->op_right = right; + sub->op_type = mie_value_get_type(left, builder->b_ctx); + + if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) { + free(sub); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(sub), name); + + return MIE_VALUE(sub); +} + +struct mie_value *mie_builder_cmp_neq( + struct mie_builder *builder, struct mie_value *left, + struct mie_value *right, const char *name) +{ + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_binary_op *sub = malloc(sizeof *sub); + if (!sub) { + return NULL; + } + + memset(sub, 0x0, sizeof *sub); + + mie_instr_init(&sub->op_base, MIE_INSTR_CMP_NEQ); + + sub->op_left = left; + sub->op_right = right; + sub->op_type = mie_value_get_type(left, builder->b_ctx); + + if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) { + free(sub); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(sub), name); + + return MIE_VALUE(sub); } struct mie_value *mie_builder_cmp_lt( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_binary_op *sub = malloc(sizeof *sub); + if (!sub) { + return NULL; + } + + memset(sub, 0x0, sizeof *sub); + + mie_instr_init(&sub->op_base, MIE_INSTR_CMP_LT); + + sub->op_left = left; + sub->op_right = right; + sub->op_type = mie_value_get_type(left, builder->b_ctx); + + if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) { + free(sub); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(sub), name); + + return MIE_VALUE(sub); } struct mie_value *mie_builder_cmp_gt( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_binary_op *sub = malloc(sizeof *sub); + if (!sub) { + return NULL; + } + + memset(sub, 0x0, sizeof *sub); + + mie_instr_init(&sub->op_base, MIE_INSTR_CMP_GT); + + sub->op_left = left; + sub->op_right = right; + sub->op_type = mie_value_get_type(left, builder->b_ctx); + + if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) { + free(sub); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(sub), name); + + return MIE_VALUE(sub); } struct mie_value *mie_builder_cmp_leq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_binary_op *sub = malloc(sizeof *sub); + if (!sub) { + return NULL; + } + + memset(sub, 0x0, sizeof *sub); + + mie_instr_init(&sub->op_base, MIE_INSTR_CMP_LEQ); + + sub->op_left = left; + sub->op_right = right; + sub->op_type = mie_value_get_type(left, builder->b_ctx); + + if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) { + free(sub); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(sub), name); + + return MIE_VALUE(sub); } struct mie_value *mie_builder_cmp_geq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_binary_op *sub = malloc(sizeof *sub); + if (!sub) { + return NULL; + } + + memset(sub, 0x0, sizeof *sub); + + mie_instr_init(&sub->op_base, MIE_INSTR_CMP_GEQ); + + sub->op_left = left; + sub->op_right = right; + sub->op_type = mie_value_get_type(left, builder->b_ctx); + + if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) { + free(sub); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(sub), name); + + return MIE_VALUE(sub); } struct mie_value *mie_builder_getelementptr( diff --git a/mie/convert/text-write.c b/mie/convert/text-write.c index 080d6bd..5dea2d4 100644 --- a/mie/convert/text-write.c +++ b/mie/convert/text-write.c @@ -593,6 +593,18 @@ static b_status write_instr( write_operand(converter, MIE_VALUE(br->b_dest), F_INCLUDE_TYPE); break; } + case MIE_INSTR_BR_IF: { + struct mie_branch_if *br = (struct mie_branch_if *)instr; + write_string(converter, "br "); + write_operand(converter, MIE_VALUE(br->b_cond), F_INCLUDE_TYPE); + write_string(converter, ", "); + write_operand( + converter, MIE_VALUE(br->b_true_block), F_INCLUDE_TYPE); + write_string(converter, ", "); + write_operand( + converter, MIE_VALUE(br->b_false_block), F_INCLUDE_TYPE); + break; + } case MIE_INSTR_MSG: { struct mie_msg *msg = (struct mie_msg *)instr; mie_type_to_string(msg->msg_ret_type, type, sizeof type); @@ -617,21 +629,60 @@ static b_status write_instr( break; } - case MIE_INSTR_CMP_EQ: - write_string(converter, "cmp eq"); + case MIE_INSTR_CMP_EQ: { + struct mie_binary_op *op = (struct mie_binary_op *)instr; + mie_type_to_string(op->op_type, type, sizeof type); + write_string_f(converter, "cmp eq %s ", type); + write_operand(converter, op->op_left, 0); + write_string(converter, ", "); + write_operand(converter, op->op_right, 0); break; - case MIE_INSTR_CMP_LT: - write_string(converter, "cmp lt"); + } + case MIE_INSTR_CMP_NEQ: { + struct mie_binary_op *op = (struct mie_binary_op *)instr; + mie_type_to_string(op->op_type, type, sizeof type); + write_string_f(converter, "cmp neq %s ", type); + write_operand(converter, op->op_left, 0); + write_string(converter, ", "); + write_operand(converter, op->op_right, 0); break; - case MIE_INSTR_CMP_GT: - write_string(converter, "cmp gt"); + } + case MIE_INSTR_CMP_LT: { + struct mie_binary_op *op = (struct mie_binary_op *)instr; + mie_type_to_string(op->op_type, type, sizeof type); + write_string_f(converter, "cmp lt %s ", type); + write_operand(converter, op->op_left, 0); + write_string(converter, ", "); + write_operand(converter, op->op_right, 0); break; - case MIE_INSTR_CMP_LEQ: - write_string(converter, "cmp leq"); + } + case MIE_INSTR_CMP_LEQ: { + struct mie_binary_op *op = (struct mie_binary_op *)instr; + mie_type_to_string(op->op_type, type, sizeof type); + write_string_f(converter, "cmp leq %s ", type); + write_operand(converter, op->op_left, 0); + write_string(converter, ", "); + write_operand(converter, op->op_right, 0); break; - case MIE_INSTR_CMP_GEQ: - write_string(converter, "cmp geq"); + } + case MIE_INSTR_CMP_GT: { + struct mie_binary_op *op = (struct mie_binary_op *)instr; + mie_type_to_string(op->op_type, type, sizeof type); + write_string_f(converter, "cmp gt %s ", type); + write_operand(converter, op->op_left, 0); + write_string(converter, ", "); + write_operand(converter, op->op_right, 0); break; + } + case MIE_INSTR_CMP_GEQ: { + struct mie_binary_op *op = (struct mie_binary_op *)instr; + mie_type_to_string(op->op_type, type, sizeof type); + write_string_f(converter, "cmp geq %s ", type); + write_operand(converter, op->op_left, 0); + write_string(converter, ", "); + write_operand(converter, op->op_right, 0); + break; + } case MIE_INSTR_GETELEMENTPTR: write_string(converter, "getelementptr"); break; diff --git a/mie/include/mie/builder.h b/mie/include/mie/builder.h index eda6f95..46423f0 100644 --- a/mie/include/mie/builder.h +++ b/mie/include/mie/builder.h @@ -90,6 +90,9 @@ extern struct mie_value *mie_builder_msg( extern struct mie_value *mie_builder_cmp_eq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name); +extern struct mie_value *mie_builder_cmp_neq( + struct mie_builder *builder, struct mie_value *left, + struct mie_value *right, const char *name); extern struct mie_value *mie_builder_cmp_lt( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name); diff --git a/mie/include/mie/instr.h b/mie/include/mie/instr.h index 937eb45..ce0b17d 100644 --- a/mie/include/mie/instr.h +++ b/mie/include/mie/instr.h @@ -17,8 +17,10 @@ enum mie_instr_type { MIE_INSTR_ALLOCA, MIE_INSTR_SWITCH, MIE_INSTR_BR, + MIE_INSTR_BR_IF, MIE_INSTR_MSG, MIE_INSTR_CMP_EQ, + MIE_INSTR_CMP_NEQ, MIE_INSTR_CMP_LT, MIE_INSTR_CMP_GT, MIE_INSTR_CMP_LEQ, diff --git a/mie/instr.c b/mie/instr.c index 8ba98e9..4d3a6e2 100644 --- a/mie/instr.c +++ b/mie/instr.c @@ -27,6 +27,13 @@ static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx) struct mie_binary_op *op = (struct mie_binary_op *)instr; return op->op_type; } + case MIE_INSTR_CMP_EQ: + case MIE_INSTR_CMP_NEQ: + case MIE_INSTR_CMP_LT: + case MIE_INSTR_CMP_LEQ: + case MIE_INSTR_CMP_GT: + case MIE_INSTR_CMP_GEQ: + return mie_ctx_get_int_type(ctx, 1); case MIE_INSTR_LOAD: { struct mie_load *load = (struct mie_load *)instr; return load->l_type;