diff --git a/mie/dialect/arith/arith.c b/mie/dialect/arith/arith.c index 0f73af6..4138a05 100644 --- a/mie/dialect/arith/arith.c +++ b/mie/dialect/arith/arith.c @@ -1,9 +1,16 @@ #include +#include +#include #include #include #include +MIE_DIAG_CLASS_LIST_EXTERN(mie_arith_diag); +MIE_DIAG_MSG_LIST_EXTERN(mie_arith_msg); + MIE_DIALECT_BEGIN(mie_arith, struct mie_dialect, "arith") + MIE_DIALECT_DIAG_CLASS_LIST(mie_arith_diag); + MIE_DIALECT_DIAG_MSG_LIST(mie_arith_msg); MIE_DIALECT_ADD_OP(mie_arith_addi); MIE_DIALECT_ADD_OP(mie_arith_cmpi); MIE_DIALECT_ADD_OP(mie_arith_addf); diff --git a/mie/dialect/arith/diag.c b/mie/dialect/arith/diag.c new file mode 100644 index 0000000..6c85f71 --- /dev/null +++ b/mie/dialect/arith/diag.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +#define MIE_DIAG_CLASS_PREFIX MIE_ARITH_E +#define MIE_DIAG_MSG_PREFIX MIE_ARITH_MSG + +MIE_DIAG_CLASS_LIST_BEGIN(mie_arith_diag) + MIE_DIAG_CLASS(INVALID_INTEGER_TYPE, ERROR, "Invalid integer type") + MIE_DIAG_CLASS(INVALID_FLOAT_TYPE, ERROR, "Invalid floating-point type") + MIE_DIAG_CLASS( + INVALID_COMPARISON_PREDICATE, ERROR, + "Invalid comparison predicate") +MIE_DIAG_CLASS_LIST_END(mie_arith_diag) + +MIE_DIAG_MSG_LIST_BEGIN(mie_arith_msg) + MIE_DIAG_MSG(EXPECTED_INTEGER_TYPE, "expected an integer or index type.") + MIE_DIAG_MSG(EXPECTED_FLOAT_TYPE, "expected a floating-point type.") + MIE_DIAG_MSG( + INVALID_COMPARISON_PREDICATE, + "this is not a valid comparison predicate.") + MIE_DIAG_MSG( + VALID_COMPARISON_PREDICATES, + "valid comparison predicates include: [blue]eq[reset], " + "[blue]ne[reset], [blue]slt[reset], [blue]sle[reset], " + "[blue]sgt[reset], [blue]sge[reset], [blue]ult[reset], " + "[blue]ule[reset], [blue]ugt[reset], [blue]uge[reset]") +MIE_DIAG_MSG_LIST_END(mie_arith_msg) diff --git a/mie/dialect/arith/op/addf.c b/mie/dialect/arith/op/addf.c index 44a990e..6d8d474 100644 --- a/mie/dialect/arith/op/addf.c +++ b/mie/dialect/arith/op/addf.c @@ -1,8 +1,12 @@ +#include +#include #include #include #include #include +#include #include +#include static enum mie_status print(struct mie_printer *printer, const struct mie_op *op) { @@ -23,8 +27,60 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) { + struct mie_file_span span; + if (MIE_VECTOR_COUNT(out->op_result) != 1) { + mie_op_get_results_span(out, &span); + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_RESULTS, + MIE_BUILTIN_MSG_OP_INCORRECT_NUMBER_OF_RESULTS, &span); + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_parameter_list( + parser, false, MIE_VECTOR_REF(out->op_args), + "arithmetic operation arguments")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (MIE_VECTOR_COUNT(out->op_args) != 2) { + mie_op_get_args_span(out, &span); + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_ARGUMENTS, + MIE_BUILTIN_MSG_OP_INCORRECT_NUMBER_OF_ARGS, &span); + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COLON)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COLON, "arithmetic operation type"); + return MIE_ERR_BAD_SYNTAX; + } + + const struct mie_type *type = NULL; + if (!mie_parser_parse_type( + parser, "arithmetic operation type", &type, &span)) { + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_type_is(type, "builtin", "float")) { + mie_parser_report_error_simple( + parser, "arith", MIE_ARITH_E_INVALID_FLOAT_TYPE, + MIE_ARITH_MSG_EXPECTED_FLOAT_TYPE, &span); + return MIE_ERR_BAD_SYNTAX; + } + + for (size_t i = 0; i < MIE_VECTOR_COUNT(out->op_args); i++) { + out->op_args.items[i].arg_unresolved.reg_type = type; + } + + out->op_result.items[0].reg_type = type; + return MIE_SUCCESS; } diff --git a/mie/dialect/arith/op/addi.c b/mie/dialect/arith/op/addi.c index 98cfe38..fa98a3e 100644 --- a/mie/dialect/arith/op/addi.c +++ b/mie/dialect/arith/op/addi.c @@ -1,10 +1,12 @@ #include +#include #include #include #include #include #include #include +#include #include #include @@ -27,8 +29,63 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) { + struct mie_file_span span; + if (MIE_VECTOR_COUNT(out->op_result) != 1) { + mie_op_get_results_span(out, &span); + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_RESULTS, + MIE_BUILTIN_MSG_OP_INCORRECT_NUMBER_OF_RESULTS, &span); + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_parameter_list( + parser, false, MIE_VECTOR_REF(out->op_args), + "arithmetic operation arguments")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (MIE_VECTOR_COUNT(out->op_args) != 2) { + mie_op_get_args_span(out, &span); + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_ARGUMENTS, + MIE_BUILTIN_MSG_OP_INCORRECT_NUMBER_OF_ARGS, &span); + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COLON)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COLON, "arithmetic operation type"); + return MIE_ERR_BAD_SYNTAX; + } + + const struct mie_type *type = NULL; + if (!mie_parser_parse_type( + parser, "arithmetic operation type", &type, &span)) { + return MIE_ERR_BAD_SYNTAX; + } + + bool is_int_type = mie_type_is(type, "builtin", "int") + || mie_type_is(type, "builtin", "index"); + + if (!is_int_type) { + mie_parser_report_error_simple( + parser, "arith", MIE_ARITH_E_INVALID_INTEGER_TYPE, + MIE_ARITH_MSG_EXPECTED_INTEGER_TYPE, &span); + return MIE_ERR_BAD_SYNTAX; + } + + for (size_t i = 0; i < MIE_VECTOR_COUNT(out->op_args); i++) { + out->op_args.items[i].arg_unresolved.reg_type = type; + } + + out->op_result.items[0].reg_type = type; + return MIE_SUCCESS; } diff --git a/mie/dialect/arith/op/cmpi.c b/mie/dialect/arith/op/cmpi.c index 70fcffb..df9f20f 100644 --- a/mie/dialect/arith/op/cmpi.c +++ b/mie/dialect/arith/op/cmpi.c @@ -1,9 +1,34 @@ +#include +#include #include #include +#include #include #include #include +#include #include +#include + +#define PREDICATE(id, str) [MIE_ARITH_CMPI_##id] = str +static const char *predicates[] = { + PREDICATE(EQ, "eq"), PREDICATE(NE, "ne"), PREDICATE(SLT, "slt"), + PREDICATE(SLE, "sle"), PREDICATE(SGT, "sgt"), PREDICATE(SGE, "sge"), + PREDICATE(ULT, "ult"), PREDICATE(ULE, "ule"), PREDICATE(UGT, "ugt"), + PREDICATE(UGE, "uge"), +}; +static const size_t nr_predicates = sizeof predicates / sizeof predicates[0]; + +static int find_predicate(const char *pred) +{ + for (size_t i = 0; i < nr_predicates; i++) { + if (!strcmp(pred, predicates[i])) { + return i; + } + } + + return -1; +} static enum mie_status print(struct mie_printer *printer, const struct mie_op *op) { @@ -24,41 +49,12 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o b_stream_write_char(printer->p_stream, ' '); - switch (pred) { - case 0: - b_stream_write_string(printer->p_stream, "eq", NULL); - break; - case 1: - b_stream_write_string(printer->p_stream, "ne", NULL); - break; - case 2: - b_stream_write_string(printer->p_stream, "slt", NULL); - break; - case 3: - b_stream_write_string(printer->p_stream, "sle", NULL); - break; - case 4: - b_stream_write_string(printer->p_stream, "sgt", NULL); - break; - case 5: - b_stream_write_string(printer->p_stream, "sge", NULL); - break; - case 6: - b_stream_write_string(printer->p_stream, "ult", NULL); - break; - case 7: - b_stream_write_string(printer->p_stream, "ule", NULL); - break; - case 8: - b_stream_write_string(printer->p_stream, "ugt", NULL); - break; - case 9: - b_stream_write_string(printer->p_stream, "uge", NULL); - break; - default: - return MIE_SUCCESS; + if (pred < 0 || pred >= nr_predicates) { + return MIE_ERR_BAD_STATE; } + b_stream_write_string(printer->p_stream, predicates[pred], NULL); + b_stream_write_char(printer->p_stream, ' '); mie_printer_print_op_arg(printer, left, false); b_stream_write_string(printer->p_stream, ", ", NULL); @@ -69,11 +65,111 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) { + struct mie_file_span span; + if (MIE_VECTOR_COUNT(out->op_result) != 1) { + mie_op_get_results_span(out, &span); + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_RESULTS, + MIE_BUILTIN_MSG_OP_INCORRECT_NUMBER_OF_RESULTS, &span); + return MIE_ERR_BAD_SYNTAX; + } + + b_string *tmp = mie_parser_get_tempstr(parser); + if (!mie_parser_parse_word(parser, tmp, &span)) { + mie_parser_report_unexpected_token_s( + parser, "predicate word", "comparison operation"); + return MIE_ERR_BAD_SYNTAX; + } + + int pred = find_predicate(b_string_ptr(tmp)); + if (pred == -1) { + struct mie_diag *diag = mie_parser_report_error_simple( + parser, "arith", MIE_ARITH_E_INVALID_COMPARISON_PREDICATE, + MIE_ARITH_MSG_INVALID_COMPARISON_PREDICATE, &span); + mie_diag_push_msg( + diag, mie_parser_get_mie_ctx(parser), "arith", + MIE_ARITH_MSG_VALID_COMPARISON_PREDICATES); + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_parameter_list( + parser, false, MIE_VECTOR_REF(out->op_args), + "comparison operands")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (MIE_VECTOR_COUNT(out->op_args) != 2) { + mie_op_get_args_span(out, &span); + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_ARGUMENTS, + MIE_BUILTIN_MSG_OP_INCORRECT_NUMBER_OF_ARGS, &span); + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COLON)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COLON, "comparison operand type"); + return MIE_ERR_BAD_SYNTAX; + } + + const struct mie_type *type; + if (!mie_parser_parse_type(parser, "comparison operand type", &type, &span)) { + return MIE_ERR_BAD_SYNTAX; + } + + bool is_int_type = mie_type_is(type, "builtin", "int") + || mie_type_is(type, "builtin", "index"); + + if (!is_int_type) { + mie_parser_report_error_simple( + parser, "arith", MIE_ARITH_E_INVALID_INTEGER_TYPE, + MIE_ARITH_MSG_EXPECTED_INTEGER_TYPE, &span); + return MIE_ERR_BAD_SYNTAX; + } + + for (size_t i = 0; i < MIE_VECTOR_COUNT(out->op_args); i++) { + out->op_args.items[i].arg_unresolved.reg_type = type; + } + + out->op_result.items[0].reg_type + = mie_ctx_get_int_type(mie_parser_get_mie_ctx(parser), 1); + + struct mie_attribute *pred_attribute + = mie_ctx_get_int(mie_parser_get_mie_ctx(parser), pred, 64); + mie_attribute_map_put( + &out->op_attrib, "predicate", pred_attribute, + MIE_ATTRMAP_F_REPLACE); + return MIE_SUCCESS; } +struct mie_register *mie_arith_cmpi_put( + struct mie_emitter *e, enum mie_arith_cmpi_predicate pred, + struct mie_register *left, struct mie_register *right, const char *name) +{ + struct mie_register *args[] = {left, right}; + const size_t nr_args = sizeof args / sizeof args[0]; + + struct mie_op *op = mie_emitter_put_op(e, "arith", "cmpi", args, nr_args); + const struct mie_type *ty = left->reg_type; + + struct mie_register *result = mie_op_add_result(op, ty); + mie_emitter_put_name(e, &result->reg_name, name); + + struct mie_attribute *pred_attribute + = mie_ctx_get_int(mie_emitter_get_ctx(e), pred, 64); + mie_attribute_map_put( + &op->op_attrib, "predicate", pred_attribute, MIE_ATTRMAP_F_REPLACE); + + return result; +} + MIE_OP_DEFINITION_BEGIN(mie_arith_cmpi, "cmpi") MIE_OP_DEFINITION_PRINT(print); MIE_OP_DEFINITION_PARSE(parse); diff --git a/mie/dialect/arith/op/constant.c b/mie/dialect/arith/op/constant.c index 05c4fdf..c426048 100644 --- a/mie/dialect/arith/op/constant.c +++ b/mie/dialect/arith/op/constant.c @@ -1,11 +1,14 @@ #include +#include #include #include #include #include #include #include +#include #include +#include static enum mie_status print(struct mie_printer *printer, const struct mie_op *op) { @@ -36,11 +39,126 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static enum mie_status parse_int( + struct mie_parser *parser, long long i, struct mie_file_span *loc, + struct mie_op *out) { + if (!mie_parser_parse_symbol(parser, MIE_SYM_COLON)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COLON, "arithmetic constant type"); + return MIE_ERR_BAD_SYNTAX; + } + + const struct mie_type *type = NULL; + struct mie_file_span type_span; + if (!mie_parser_parse_type( + parser, "arithmetic constant type", &type, &type_span)) { + mie_parser_report_unexpected_token( + parser, MIE_TOK_TYPENAME, "arithmetic constant type"); + return MIE_ERR_BAD_SYNTAX; + } + + struct mie_attribute *value = NULL; + + if (mie_type_is(type, "builtin", "int")) { + value = mie_ctx_get_int( + mie_parser_get_mie_ctx(parser), i, + mie_int_type_get_width(type)); + } else if (mie_type_is(type, "builtin", "index")) { + value = mie_ctx_get_index(mie_parser_get_mie_ctx(parser), i); + } else { + mie_parser_report_error_simple( + parser, "arith", MIE_ARITH_E_INVALID_INTEGER_TYPE, + MIE_ARITH_MSG_EXPECTED_INTEGER_TYPE, &type_span); + } + + if (MIE_VECTOR_COUNT(out->op_result) != 1) { + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_RESULTS, + MIE_BUILTIN_MSG_OP_EXPECTS_X_RESULTS, &type_span); + return MIE_ERR_BAD_SYNTAX; + } + + mie_attribute_map_put( + &out->op_attrib, "value", value, MIE_ATTRMAP_F_REPLACE); + + out->op_result.items[0].reg_type = type; + return MIE_SUCCESS; } +static enum mie_status parse_float( + struct mie_parser *parser, double d, struct mie_file_span *loc, + struct mie_op *out) +{ + if (!mie_parser_parse_symbol(parser, MIE_SYM_COLON)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COLON, "arithmetic constant type"); + return MIE_ERR_BAD_SYNTAX; + } + + const struct mie_type *type = NULL; + struct mie_file_span type_span; + if (!mie_parser_parse_type( + parser, "arithmetic constant type", &type, &type_span)) { + mie_parser_report_unexpected_token( + parser, MIE_TOK_TYPENAME, "arithmetic constant type"); + return MIE_ERR_BAD_SYNTAX; + } + + struct mie_attribute *value = NULL; + + if (mie_type_is(type, "builtin", "float")) { + value = mie_ctx_get_float( + mie_parser_get_mie_ctx(parser), d, + mie_float_type_get_width(type)); + } else { + mie_parser_report_error_simple( + parser, "arith", MIE_ARITH_E_INVALID_FLOAT_TYPE, + MIE_ARITH_MSG_EXPECTED_FLOAT_TYPE, &type_span); + return MIE_ERR_BAD_SYNTAX; + } + + if (MIE_VECTOR_COUNT(out->op_result) != 1) { + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_RESULTS, + MIE_BUILTIN_MSG_OP_EXPECTS_X_RESULTS, &type_span); + return MIE_ERR_BAD_SYNTAX; + } + + mie_attribute_map_put( + &out->op_attrib, "value", value, MIE_ATTRMAP_F_REPLACE); + + out->op_result.items[0].reg_type = type; + + return MIE_SUCCESS; +} + +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) +{ + double d; + long long i; + struct mie_file_span span; + if (mie_parser_parse_int(parser, &i, &span)) { + return parse_int(parser, i, &span, out); + } else if (mie_parser_parse_float(parser, &d, &span)) { + return parse_float(parser, d, &span, out); + } else { + struct mie_parser_item required[] = { + MIE_PARSE_ITEM_TOKEN(MIE_TOK_INT), + MIE_PARSE_ITEM_TOKEN(MIE_TOK_FLOAT), + MIE_PARSE_ITEM_NONE, + }; + mie_parser_report_unexpected_token_v( + parser, required, "arithmetic constant"); + return MIE_ERR_BAD_SYNTAX; + } +} + struct mie_register *mie_arith_constant_i_put( struct mie_emitter *e, long long value, const char *name) { diff --git a/mie/include/mie/dialect/arith.h b/mie/include/mie/dialect/arith.h index 2c5a74f..e190d75 100644 --- a/mie/include/mie/dialect/arith.h +++ b/mie/include/mie/dialect/arith.h @@ -10,6 +10,32 @@ struct mie_ctx; struct mie_dialect; struct mie_emitter; +enum mie_arith_diag { + MIE_ARITH_E_INVALID_INTEGER_TYPE, + MIE_ARITH_E_INVALID_FLOAT_TYPE, + MIE_ARITH_E_INVALID_COMPARISON_PREDICATE, +}; + +enum mie_arith_msg { + MIE_ARITH_MSG_EXPECTED_INTEGER_TYPE, + MIE_ARITH_MSG_EXPECTED_FLOAT_TYPE, + MIE_ARITH_MSG_INVALID_COMPARISON_PREDICATE, + MIE_ARITH_MSG_VALID_COMPARISON_PREDICATES, +}; + +enum mie_arith_cmpi_predicate { + MIE_ARITH_CMPI_EQ = 0, + MIE_ARITH_CMPI_NE = 1, + MIE_ARITH_CMPI_SLT = 2, + MIE_ARITH_CMPI_SLE = 3, + MIE_ARITH_CMPI_SGT = 4, + MIE_ARITH_CMPI_SGE = 5, + MIE_ARITH_CMPI_ULT = 6, + MIE_ARITH_CMPI_ULE = 7, + MIE_ARITH_CMPI_UGT = 8, + MIE_ARITH_CMPI_UGE = 9, +}; + MIE_API struct mie_dialect *mie_arith_dialect_create(struct mie_ctx *ctx); MIE_API struct mie_register *mie_arith_constant_i_put( @@ -19,6 +45,9 @@ MIE_API struct mie_register *mie_arith_constant_f_put( MIE_API struct mie_register *mie_arith_addi_put( struct mie_emitter *e, struct mie_register *left, struct mie_register *right, const char *name); +MIE_API struct mie_register *mie_arith_cmpi_put( + struct mie_emitter *e, enum mie_arith_cmpi_predicate pred, + struct mie_register *left, struct mie_register *right, const char *name); MIE_API struct mie_register *mie_arith_addf_put( struct mie_emitter *e, struct mie_register *left, struct mie_register *right, const char *name);