Line data Source code
1 : // Copyright (C) 2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #include "rust-system.h"
20 : #include "rust-compile-context.h"
21 : #include "rust-compile-type.h"
22 : #include "rust-tyty.h"
23 : #include "rust-abi.h"
24 : #include "rust-tree.h"
25 : #include "tree.h"
26 : #include "fold-const.h"
27 : #include "rust-compile-platform-intrinsic.h"
28 :
29 : namespace Rust {
30 : namespace Compile {
31 :
32 : const std::map<std::string, PlatformIntrinsic::PlatformIntrinsicMapping>
33 : PlatformIntrinsic::platform_intrinsics = {
34 : {"simd_add", {OpKind::BINARY, PLUS_EXPR}},
35 : {"simd_sub", {OpKind::BINARY, MINUS_EXPR}},
36 : {"simd_mul", {OpKind::BINARY, MULT_EXPR}},
37 : {"simd_div",
38 : {OpKind::BINARY,
39 : TRUNC_DIV_EXPR}}, // uses RDIV_EXPR if operands are real type
40 : {"simd_shl", {OpKind::BINARY, LSHIFT_EXPR}},
41 : {"simd_shr", {OpKind::BINARY, RSHIFT_EXPR}},
42 : {"simd_and", {OpKind::BINARY, BIT_AND_EXPR}},
43 : {"simd_or", {OpKind::BINARY, BIT_IOR_EXPR}},
44 : {"simd_xor", {OpKind::BINARY, BIT_XOR_EXPR}},
45 : {"simd_eq", {OpKind::COMPARISON, EQ_EXPR}},
46 : {"simd_ne", {OpKind::COMPARISON, NE_EXPR}},
47 : {"simd_lt", {OpKind::COMPARISON, LT_EXPR}},
48 : {"simd_le", {OpKind::COMPARISON, LE_EXPR}},
49 : {"simd_gt", {OpKind::COMPARISON, GT_EXPR}},
50 : {"simd_ge", {OpKind::COMPARISON, GE_EXPR}},
51 : };
52 :
53 : tree
54 0 : compile_comparison_op (const TyTy::FnType *fntype,
55 : const std::vector<tree> &arguments, location_t locus,
56 : const tree &result_type, const tree_code op_code)
57 : {
58 0 : tree input_type = TREE_TYPE (arguments[0]);
59 0 : tree predicate_type = truth_type_for (input_type);
60 :
61 0 : tree predicate = fold_build2_loc (locus, op_code, predicate_type,
62 0 : arguments[0], arguments[1]);
63 0 : return fold_build3_loc (locus, VEC_COND_EXPR, result_type, predicate,
64 : build_minus_one_cst (result_type),
65 0 : build_zero_cst (result_type));
66 : }
67 :
68 : tree
69 0 : compile_binary_op (const TyTy::FnType *fntype,
70 : const std::vector<tree> &arguments, location_t locus,
71 : const tree &result_type, const tree_code op_code)
72 : {
73 0 : tree_code final_op_code = op_code;
74 :
75 : // idk any more elegant way to do this
76 0 : if (final_op_code == TRUNC_DIV_EXPR
77 0 : && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE)
78 : final_op_code = RDIV_EXPR;
79 :
80 0 : return fold_build2_loc (locus, final_op_code, result_type, arguments[0],
81 0 : arguments[1]);
82 : }
83 :
84 : tree
85 0 : PlatformIntrinsic::compile_call (Context *ctx, TyTy::FnType *fntype,
86 : const std::vector<tree> &arguments,
87 : location_t locus)
88 : {
89 0 : rust_assert (fntype != nullptr);
90 0 : rust_assert (fntype->get_abi () == ABI::PLATFORM_INTRINSIC);
91 0 : auto *result_ty = fntype->get_return_type ()->destructure ();
92 0 : tree result_type = TyTyResolveCompile::compile (ctx, result_ty);
93 :
94 0 : auto it = platform_intrinsics.find (fntype->get_identifier ());
95 0 : if (it == platform_intrinsics.end ())
96 : {
97 : // TODO add an error here
98 0 : return error_mark_node;
99 : }
100 :
101 0 : const auto &mapping = it->second;
102 :
103 0 : switch (mapping.kind)
104 : {
105 0 : case OpKind::BINARY:
106 0 : return compile_binary_op (fntype, arguments, locus, result_type,
107 0 : mapping.code);
108 0 : case OpKind::COMPARISON:
109 0 : return compile_comparison_op (fntype, arguments, locus, result_type,
110 0 : mapping.code);
111 0 : default:
112 0 : return error_mark_node;
113 : }
114 : }
115 :
116 : } // namespace Compile
117 : } // namespace Rust
|