xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===- CodeGenIntrinsics.h - Intrinsic Class Wrapper -----------*- C++ -*--===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // This file defines a wrapper class for the 'Intrinsic' TableGen class.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
14*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
15*0fca6ea1SDimitry Andric 
16*0fca6ea1SDimitry Andric #include "SDNodeProperties.h"
17*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
18*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h"
19*0fca6ea1SDimitry Andric #include "llvm/Support/ModRef.h"
20*0fca6ea1SDimitry Andric #include <string>
21*0fca6ea1SDimitry Andric #include <tuple>
22*0fca6ea1SDimitry Andric #include <vector>
23*0fca6ea1SDimitry Andric 
24*0fca6ea1SDimitry Andric namespace llvm {
25*0fca6ea1SDimitry Andric class Record;
26*0fca6ea1SDimitry Andric class RecordKeeper;
27*0fca6ea1SDimitry Andric 
28*0fca6ea1SDimitry Andric struct CodeGenIntrinsic {
29*0fca6ea1SDimitry Andric   Record *TheDef;       // The actual record defining this intrinsic.
30*0fca6ea1SDimitry Andric   std::string Name;     // The name of the LLVM function "llvm.bswap.i32"
31*0fca6ea1SDimitry Andric   std::string EnumName; // The name of the enum "bswap_i32"
32*0fca6ea1SDimitry Andric   std::string ClangBuiltinName; // Name of the corresponding GCC builtin, or "".
33*0fca6ea1SDimitry Andric   std::string MSBuiltinName;    // Name of the corresponding MS builtin, or "".
34*0fca6ea1SDimitry Andric   std::string TargetPrefix;     // Target prefix, e.g. "ppc" for t-s intrinsics.
35*0fca6ea1SDimitry Andric 
36*0fca6ea1SDimitry Andric   /// This structure holds the return values and parameter values of an
37*0fca6ea1SDimitry Andric   /// intrinsic. If the number of return values is > 1, then the intrinsic
38*0fca6ea1SDimitry Andric   /// implicitly returns a first-class aggregate. The numbering of the types
39*0fca6ea1SDimitry Andric   /// starts at 0 with the first return value and continues from there through
40*0fca6ea1SDimitry Andric   /// the parameter list. This is useful for "matching" types.
41*0fca6ea1SDimitry Andric   struct IntrinsicSignature {
42*0fca6ea1SDimitry Andric     /// The MVT::SimpleValueType for each return type. Note that this list is
43*0fca6ea1SDimitry Andric     /// only populated when in the context of a target .td file. When building
44*0fca6ea1SDimitry Andric     /// Intrinsics.td, this isn't available, because we don't know the target
45*0fca6ea1SDimitry Andric     /// pointer size.
46*0fca6ea1SDimitry Andric     std::vector<Record *> RetTys;
47*0fca6ea1SDimitry Andric 
48*0fca6ea1SDimitry Andric     /// The MVT::SimpleValueType for each parameter type. Note that this list is
49*0fca6ea1SDimitry Andric     /// only populated when in the context of a target .td file.  When building
50*0fca6ea1SDimitry Andric     /// Intrinsics.td, this isn't available, because we don't know the target
51*0fca6ea1SDimitry Andric     /// pointer size.
52*0fca6ea1SDimitry Andric     std::vector<Record *> ParamTys;
53*0fca6ea1SDimitry Andric   };
54*0fca6ea1SDimitry Andric 
55*0fca6ea1SDimitry Andric   IntrinsicSignature IS;
56*0fca6ea1SDimitry Andric 
57*0fca6ea1SDimitry Andric   /// Memory effects of the intrinsic.
58*0fca6ea1SDimitry Andric   MemoryEffects ME = MemoryEffects::unknown();
59*0fca6ea1SDimitry Andric 
60*0fca6ea1SDimitry Andric   /// SDPatternOperator Properties applied to the intrinsic.
61*0fca6ea1SDimitry Andric   unsigned Properties;
62*0fca6ea1SDimitry Andric 
63*0fca6ea1SDimitry Andric   /// This is set to true if the intrinsic is overloaded by its argument
64*0fca6ea1SDimitry Andric   /// types.
65*0fca6ea1SDimitry Andric   bool isOverloaded;
66*0fca6ea1SDimitry Andric 
67*0fca6ea1SDimitry Andric   /// True if the intrinsic is commutative.
68*0fca6ea1SDimitry Andric   bool isCommutative;
69*0fca6ea1SDimitry Andric 
70*0fca6ea1SDimitry Andric   /// True if the intrinsic can throw.
71*0fca6ea1SDimitry Andric   bool canThrow;
72*0fca6ea1SDimitry Andric 
73*0fca6ea1SDimitry Andric   /// True if the intrinsic is marked as noduplicate.
74*0fca6ea1SDimitry Andric   bool isNoDuplicate;
75*0fca6ea1SDimitry Andric 
76*0fca6ea1SDimitry Andric   /// True if the intrinsic is marked as nomerge.
77*0fca6ea1SDimitry Andric   bool isNoMerge;
78*0fca6ea1SDimitry Andric 
79*0fca6ea1SDimitry Andric   /// True if the intrinsic is no-return.
80*0fca6ea1SDimitry Andric   bool isNoReturn;
81*0fca6ea1SDimitry Andric 
82*0fca6ea1SDimitry Andric   /// True if the intrinsic is no-callback.
83*0fca6ea1SDimitry Andric   bool isNoCallback;
84*0fca6ea1SDimitry Andric 
85*0fca6ea1SDimitry Andric   /// True if the intrinsic is no-sync.
86*0fca6ea1SDimitry Andric   bool isNoSync;
87*0fca6ea1SDimitry Andric 
88*0fca6ea1SDimitry Andric   /// True if the intrinsic is no-free.
89*0fca6ea1SDimitry Andric   bool isNoFree;
90*0fca6ea1SDimitry Andric 
91*0fca6ea1SDimitry Andric   /// True if the intrinsic is will-return.
92*0fca6ea1SDimitry Andric   bool isWillReturn;
93*0fca6ea1SDimitry Andric 
94*0fca6ea1SDimitry Andric   /// True if the intrinsic is cold.
95*0fca6ea1SDimitry Andric   bool isCold;
96*0fca6ea1SDimitry Andric 
97*0fca6ea1SDimitry Andric   /// True if the intrinsic is marked as convergent.
98*0fca6ea1SDimitry Andric   bool isConvergent;
99*0fca6ea1SDimitry Andric 
100*0fca6ea1SDimitry Andric   /// True if the intrinsic has side effects that aren't captured by any
101*0fca6ea1SDimitry Andric   /// of the other flags.
102*0fca6ea1SDimitry Andric   bool hasSideEffects;
103*0fca6ea1SDimitry Andric 
104*0fca6ea1SDimitry Andric   // True if the intrinsic is marked as speculatable.
105*0fca6ea1SDimitry Andric   bool isSpeculatable;
106*0fca6ea1SDimitry Andric 
107*0fca6ea1SDimitry Andric   // True if the intrinsic is marked as strictfp.
108*0fca6ea1SDimitry Andric   bool isStrictFP;
109*0fca6ea1SDimitry Andric 
110*0fca6ea1SDimitry Andric   enum ArgAttrKind {
111*0fca6ea1SDimitry Andric     NoCapture,
112*0fca6ea1SDimitry Andric     NoAlias,
113*0fca6ea1SDimitry Andric     NoUndef,
114*0fca6ea1SDimitry Andric     NonNull,
115*0fca6ea1SDimitry Andric     Returned,
116*0fca6ea1SDimitry Andric     ReadOnly,
117*0fca6ea1SDimitry Andric     WriteOnly,
118*0fca6ea1SDimitry Andric     ReadNone,
119*0fca6ea1SDimitry Andric     ImmArg,
120*0fca6ea1SDimitry Andric     Alignment,
121*0fca6ea1SDimitry Andric     Dereferenceable
122*0fca6ea1SDimitry Andric   };
123*0fca6ea1SDimitry Andric 
124*0fca6ea1SDimitry Andric   struct ArgAttribute {
125*0fca6ea1SDimitry Andric     ArgAttrKind Kind;
126*0fca6ea1SDimitry Andric     uint64_t Value;
127*0fca6ea1SDimitry Andric 
128*0fca6ea1SDimitry Andric     ArgAttribute(ArgAttrKind K, uint64_t V) : Kind(K), Value(V) {}
129*0fca6ea1SDimitry Andric 
130*0fca6ea1SDimitry Andric     bool operator<(const ArgAttribute &Other) const {
131*0fca6ea1SDimitry Andric       return std::tie(Kind, Value) < std::tie(Other.Kind, Other.Value);
132*0fca6ea1SDimitry Andric     }
133*0fca6ea1SDimitry Andric   };
134*0fca6ea1SDimitry Andric 
135*0fca6ea1SDimitry Andric   /// Vector of attributes for each argument.
136*0fca6ea1SDimitry Andric   SmallVector<SmallVector<ArgAttribute, 0>> ArgumentAttributes;
137*0fca6ea1SDimitry Andric 
138*0fca6ea1SDimitry Andric   void addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V = 0);
139*0fca6ea1SDimitry Andric 
140*0fca6ea1SDimitry Andric   bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
141*0fca6ea1SDimitry Andric 
142*0fca6ea1SDimitry Andric   /// Goes through all IntrProperties that have IsDefault
143*0fca6ea1SDimitry Andric   /// value set and sets the property.
144*0fca6ea1SDimitry Andric   void setDefaultProperties(Record *R, ArrayRef<Record *> DefaultProperties);
145*0fca6ea1SDimitry Andric 
146*0fca6ea1SDimitry Andric   /// Helper function to set property \p Name to true;
147*0fca6ea1SDimitry Andric   void setProperty(Record *R);
148*0fca6ea1SDimitry Andric 
149*0fca6ea1SDimitry Andric   /// Returns true if the parameter at \p ParamIdx is a pointer type. Returns
150*0fca6ea1SDimitry Andric   /// false if the parameter is not a pointer, or \p ParamIdx is greater than
151*0fca6ea1SDimitry Andric   /// the size of \p IS.ParamVTs.
152*0fca6ea1SDimitry Andric   ///
153*0fca6ea1SDimitry Andric   /// Note that this requires that \p IS.ParamVTs is available.
154*0fca6ea1SDimitry Andric   bool isParamAPointer(unsigned ParamIdx) const;
155*0fca6ea1SDimitry Andric 
156*0fca6ea1SDimitry Andric   bool isParamImmArg(unsigned ParamIdx) const;
157*0fca6ea1SDimitry Andric 
158*0fca6ea1SDimitry Andric   CodeGenIntrinsic(Record *R, ArrayRef<Record *> DefaultProperties);
159*0fca6ea1SDimitry Andric };
160*0fca6ea1SDimitry Andric 
161*0fca6ea1SDimitry Andric class CodeGenIntrinsicTable {
162*0fca6ea1SDimitry Andric   std::vector<CodeGenIntrinsic> Intrinsics;
163*0fca6ea1SDimitry Andric 
164*0fca6ea1SDimitry Andric public:
165*0fca6ea1SDimitry Andric   struct TargetSet {
166*0fca6ea1SDimitry Andric     std::string Name;
167*0fca6ea1SDimitry Andric     size_t Offset;
168*0fca6ea1SDimitry Andric     size_t Count;
169*0fca6ea1SDimitry Andric   };
170*0fca6ea1SDimitry Andric   std::vector<TargetSet> Targets;
171*0fca6ea1SDimitry Andric 
172*0fca6ea1SDimitry Andric   explicit CodeGenIntrinsicTable(const RecordKeeper &RC);
173*0fca6ea1SDimitry Andric   CodeGenIntrinsicTable() = default;
174*0fca6ea1SDimitry Andric 
175*0fca6ea1SDimitry Andric   bool empty() const { return Intrinsics.empty(); }
176*0fca6ea1SDimitry Andric   size_t size() const { return Intrinsics.size(); }
177*0fca6ea1SDimitry Andric   auto begin() const { return Intrinsics.begin(); }
178*0fca6ea1SDimitry Andric   auto end() const { return Intrinsics.end(); }
179*0fca6ea1SDimitry Andric   CodeGenIntrinsic &operator[](size_t Pos) { return Intrinsics[Pos]; }
180*0fca6ea1SDimitry Andric   const CodeGenIntrinsic &operator[](size_t Pos) const {
181*0fca6ea1SDimitry Andric     return Intrinsics[Pos];
182*0fca6ea1SDimitry Andric   }
183*0fca6ea1SDimitry Andric };
184*0fca6ea1SDimitry Andric } // namespace llvm
185*0fca6ea1SDimitry Andric 
186*0fca6ea1SDimitry Andric #endif
187