Line data Source code
1 : // This file is part of GCC.
2 :
3 : // GCC is free software; you can redistribute it and/or modify it under
4 : // the terms of the GNU General Public License as published by the Free
5 : // Software Foundation; either version 3, or (at your option) any later
6 : // version.
7 :
8 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
9 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 : // for more details.
12 :
13 : // You should have received a copy of the GNU General Public License
14 : // along with GCC; see the file COPYING3. If not see
15 : // <http://www.gnu.org/licenses/>.
16 :
17 : #include "rust-compile-intrinsic.h"
18 : #include "rust-compile-context.h"
19 : #include "rust-builtins.h"
20 : #include "rust-diagnostics.h"
21 : #include "tree-core.h"
22 : #include "rust-intrinsic-handlers.h"
23 : #include "rust-intrinsic-values.h"
24 :
25 : namespace Rust {
26 : namespace Compile {
27 :
28 : using IValue = Values::Intrinsics;
29 :
30 : static const std::map<std::string, handlers::HandlerBuilder> generic_intrinsics
31 : = {{IValue::OFFSET, handlers::offset},
32 : {IValue::ARITH_OFFSET, handlers::arith_offset_handler},
33 : {IValue::WRITE_BYTES, handlers::write_bytes_handler},
34 : {IValue::ASSERT_ZERO_VALID, handlers::assert_zero_valid_handler},
35 : {IValue::SIZE_OF, handlers::sizeof_handler},
36 : {IValue::SIZE_OF_VAL, handlers::size_of_val_handler},
37 : {IValue::MIN_ALIGN_OF, handlers::min_align_of_handler},
38 : {IValue::MIN_ALIGN_OF_VAL, handlers::min_align_of_val_handler},
39 : {IValue::TRANSMUTE, handlers::transmute},
40 : {IValue::ROTATE_LEFT, handlers::rotate_left},
41 : {IValue::ROTATE_RIGHT, handlers::rotate_right},
42 : {IValue::WRAPPING_ADD, handlers::wrapping_op (PLUS_EXPR)},
43 : {IValue::WRAPPING_SUB, handlers::wrapping_op (MINUS_EXPR)},
44 : {IValue::WRAPPING_MUL, handlers::wrapping_op (MULT_EXPR)},
45 : {IValue::ADD_WITH_OVERFLOW, handlers::op_with_overflow (PLUS_EXPR)},
46 : {IValue::SUB_WITH_OVERFLOW, handlers::op_with_overflow (MINUS_EXPR)},
47 : {IValue::MUL_WITH_OVERFLOW, handlers::op_with_overflow (MULT_EXPR)},
48 : {IValue::COPY, handlers::copy (true)},
49 : {IValue::COPY_NONOVERLAPPING, handlers::copy (false)},
50 : {IValue::PREFETCH_READ_DATA, handlers::prefetch_read_data},
51 : {IValue::PREFETCH_WRITE_DATA, handlers::prefetch_write_data},
52 : {IValue::ATOMIC_STORE, handlers::atomic_store (__ATOMIC_SEQ_CST)},
53 : {IValue::ATOMIC_STORE_SEQCST, handlers::atomic_store (__ATOMIC_SEQ_CST)},
54 : {IValue::ATOMIC_STORE_REL, handlers::atomic_store (__ATOMIC_RELEASE)},
55 : {IValue::ATOMIC_STORE_RELEASE, handlers::atomic_store (__ATOMIC_RELEASE)},
56 : {IValue::ATOMIC_STORE_RELAXED, handlers::atomic_store (__ATOMIC_RELAXED)},
57 : {IValue::ATOMIC_STORE_UNORDERED,
58 : handlers::atomic_store (__ATOMIC_RELAXED)},
59 : {IValue::ATOMIC_LOAD, handlers::atomic_load (__ATOMIC_SEQ_CST)},
60 : {IValue::ATOMIC_LOAD_SEQCST, handlers::atomic_load (__ATOMIC_SEQ_CST)},
61 : {IValue::ATOMIC_LOAD_ACQ, handlers::atomic_load (__ATOMIC_ACQUIRE)},
62 : {IValue::ATOMIC_LOAD_ACQUIRE, handlers::atomic_load (__ATOMIC_ACQUIRE)},
63 : {IValue::ATOMIC_LOAD_RELAXED, handlers::atomic_load (__ATOMIC_RELAXED)},
64 : {IValue::ATOMIC_LOAD_UNORDERED, handlers::atomic_load (__ATOMIC_RELAXED)},
65 : {IValue::UNCHECKED_ADD, handlers::unchecked_op (PLUS_EXPR)},
66 : {IValue::UNCHECKED_SUB, handlers::unchecked_op (MINUS_EXPR)},
67 : {IValue::UNCHECKED_MUL, handlers::unchecked_op (MULT_EXPR)},
68 : {IValue::UNCHECKED_DIV, handlers::unchecked_op (TRUNC_DIV_EXPR)},
69 : {IValue::UNCHECKED_REM, handlers::unchecked_op (TRUNC_MOD_EXPR)},
70 : {IValue::UNCHECKED_SHL, handlers::unchecked_op (LSHIFT_EXPR)},
71 : {IValue::UNCHECKED_SHR, handlers::unchecked_op (RSHIFT_EXPR)},
72 : {IValue::UNINIT, handlers::uninit},
73 : {IValue::MOVE_VAL_INIT, handlers::move_val_init},
74 : {IValue::LIKELY, handlers::expect (true)},
75 : {IValue::UNLIKELY, handlers::expect (false)},
76 : {IValue::ASSUME, handlers::assume},
77 : {IValue::TRY, handlers::try_handler (false)},
78 : {IValue::CATCH_UNWIND, handlers::try_handler (true)},
79 : {IValue::DISCRIMINANT_VALUE, handlers::discriminant_value},
80 : {IValue::VARIANT_COUNT, handlers::variant_count},
81 : {IValue::BSWAP, handlers::bswap_handler},
82 : {IValue::CTLZ, handlers::ctlz_handler},
83 : {IValue::CTLZ_NONZERO, handlers::ctlz_nonzero_handler},
84 : {IValue::CTTZ, handlers::cttz_handler},
85 : {IValue::CTTZ_NONZERO, handlers::cttz_nonzero_handler}};
86 :
87 3783 : Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
88 :
89 : /**
90 : * Returns a FUNC_DECL corresponding to the intrinsic function FNTYPE. If a
91 : * corresponding builtin exists, returns it. If not, search in the generic
92 : * intrinsics declared and delegate the return to the corresponding handler.
93 : *
94 : * @param fntype The Rust function type that should be implemented by the
95 : * compiler
96 : */
97 : tree
98 3783 : Intrinsics::compile (TyTy::FnType *fntype, location_t expr_locus)
99 : {
100 3783 : rust_assert (fntype->get_abi () == ABI::INTRINSIC);
101 :
102 3783 : tree builtin = error_mark_node;
103 3783 : BuiltinsContext &builtin_ctx = BuiltinsContext::get ();
104 :
105 7566 : if (builtin_ctx.lookup_simple_builtin (fntype->get_identifier (), &builtin))
106 449 : return builtin;
107 :
108 : // is it an generic builtin?
109 6668 : auto it = generic_intrinsics.find (fntype->get_identifier ());
110 3334 : if (it != generic_intrinsics.end ())
111 3334 : return it->second (ctx, fntype, expr_locus);
112 :
113 0 : location_t locus = ctx->get_mappings ().lookup_location (fntype->get_ref ());
114 0 : rust_error_at (locus, ErrorCode::E0093,
115 : "unrecognized intrinsic function: %qs",
116 0 : fntype->get_identifier ().c_str ());
117 :
118 0 : return error_mark_node;
119 : }
120 :
121 : } // namespace Compile
122 : } // namespace Rust
|