|
34 | 34 | namespace Rust {
|
35 | 35 | namespace Compile {
|
36 | 36 |
|
| 37 | +static bool |
| 38 | +is_basic_integer_type (TyTy::BaseType *type) |
| 39 | +{ |
| 40 | + switch (type->get_kind ()) |
| 41 | + { |
| 42 | + case TyTy::INT: |
| 43 | + case TyTy::UINT: |
| 44 | + case TyTy::USIZE: |
| 45 | + case TyTy::ISIZE: |
| 46 | + return true; |
| 47 | + default: |
| 48 | + return false; |
| 49 | + break; |
| 50 | + } |
| 51 | +} |
| 52 | + |
37 | 53 | static tree
|
38 | 54 | offset_handler (Context *ctx, TyTy::FnType *fntype);
|
39 | 55 | static tree
|
@@ -97,6 +113,17 @@ atomic_store_handler (int ordering)
|
97 | 113 | };
|
98 | 114 | }
|
99 | 115 |
|
| 116 | +static inline tree |
| 117 | +unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); |
| 118 | + |
| 119 | +const static std::function<tree (Context *, TyTy::FnType *)> |
| 120 | +unchecked_op_handler (tree_code op) |
| 121 | +{ |
| 122 | + return [op] (Context *ctx, TyTy::FnType *fntype) { |
| 123 | + return unchecked_op_inner (ctx, fntype, op); |
| 124 | + }; |
| 125 | +} |
| 126 | + |
100 | 127 | static inline tree
|
101 | 128 | sorry_handler (Context *ctx, TyTy::FnType *fntype)
|
102 | 129 | {
|
@@ -125,6 +152,13 @@ static const std::map<std::string,
|
125 | 152 | {"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)},
|
126 | 153 | {"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)},
|
127 | 154 | {"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)},
|
| 155 | + {"unchecked_add", unchecked_op_handler (PLUS_EXPR)}, |
| 156 | + {"unchecked_sub", unchecked_op_handler (MINUS_EXPR)}, |
| 157 | + {"unchecked_mul", unchecked_op_handler (MULT_EXPR)}, |
| 158 | + {"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)}, |
| 159 | + {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)}, |
| 160 | + {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)}, |
| 161 | + {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)}, |
128 | 162 | };
|
129 | 163 |
|
130 | 164 | Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
|
@@ -714,6 +748,52 @@ atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering)
|
714 | 748 | TREE_SIDE_EFFECTS (store_call) = 1;
|
715 | 749 |
|
716 | 750 | ctx->add_statement (store_call);
|
| 751 | + finalize_intrinsic_block (ctx, fndecl); |
| 752 | + |
| 753 | + return fndecl; |
| 754 | +} |
| 755 | + |
| 756 | +static inline tree |
| 757 | +unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op) |
| 758 | +{ |
| 759 | + rust_assert (fntype->get_params ().size () == 2); |
| 760 | + rust_assert (fntype->get_num_substitutions () == 1); |
| 761 | + |
| 762 | + tree lookup = NULL_TREE; |
| 763 | + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) |
| 764 | + return lookup; |
| 765 | + |
| 766 | + auto fndecl = compile_intrinsic_function (ctx, fntype); |
| 767 | + |
| 768 | + // setup the params |
| 769 | + std::vector<Bvariable *> param_vars; |
| 770 | + compile_fn_params (ctx, fntype, fndecl, ¶m_vars); |
| 771 | + |
| 772 | + if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) |
| 773 | + return error_mark_node; |
| 774 | + |
| 775 | + enter_intrinsic_block (ctx, fndecl); |
| 776 | + |
| 777 | + // BUILTIN unchecked_<op> BODY BEGIN |
| 778 | + |
| 779 | + auto x = ctx->get_backend ()->var_expression (param_vars[0], Location ()); |
| 780 | + auto y = ctx->get_backend ()->var_expression (param_vars[1], Location ()); |
| 781 | + |
| 782 | + auto *monomorphized_type |
| 783 | + = fntype->get_substs ().at (0).get_param_ty ()->resolve (); |
| 784 | + if (!is_basic_integer_type (monomorphized_type)) |
| 785 | + rust_error_at (fntype->get_locus (), |
| 786 | + "unchecked operation intrinsics can only be used with " |
| 787 | + "basic integer types (got %qs)", |
| 788 | + monomorphized_type->get_name ().c_str ()); |
| 789 | + |
| 790 | + auto expr = build2 (op, TREE_TYPE (x), x, y); |
| 791 | + auto return_statement |
| 792 | + = ctx->get_backend ()->return_statement (fndecl, {expr}, Location ()); |
| 793 | + |
| 794 | + ctx->add_statement (return_statement); |
| 795 | + |
| 796 | + // BUILTIN unchecked_<op> BODY END |
717 | 797 |
|
718 | 798 | finalize_intrinsic_block (ctx, fndecl);
|
719 | 799 |
|
|
0 commit comments