1 //===- Intrinsics.h - LLVM Intrinsic Function Handling ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a set of enums which allow processing of intrinsic
10 // functions.  Values of these enum types are returned by
11 // Function::getIntrinsicID.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_IR_INTRINSICS_H
16 #define LLVM_IR_INTRINSICS_H
17 
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/Support/TypeSize.h"
20 #include <optional>
21 #include <string>
22 
23 namespace llvm {
24 
25 class Type;
26 class FunctionType;
27 class Function;
28 class LLVMContext;
29 class Module;
30 class AttributeList;
31 
32 /// This namespace contains an enum with a value for every intrinsic/builtin
33 /// function known by LLVM. The enum values are returned by
34 /// Function::getIntrinsicID().
35 namespace Intrinsic {
36   // Abstraction for the arguments of the noalias intrinsics
37   static const int NoAliasScopeDeclScopeArg = 0;
38 
39   // Intrinsic ID type. This is an opaque typedef to facilitate splitting up
40   // the enum into target-specific enums.
41   typedef unsigned ID;
42 
43   enum IndependentIntrinsics : unsigned {
44     not_intrinsic = 0, // Must be zero
45 
46   // Get the intrinsic enums generated from Intrinsics.td
47 #define GET_INTRINSIC_ENUM_VALUES
48 #include "llvm/IR/IntrinsicEnums.inc"
49 #undef GET_INTRINSIC_ENUM_VALUES
50   };
51 
52   /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
53   /// Note, this version is for intrinsics with no overloads.  Use the other
54   /// version of getName if overloads are required.
55   StringRef getName(ID id);
56 
57   /// Return the LLVM name for an intrinsic, without encoded types for
58   /// overloading, such as "llvm.ssa.copy".
59   StringRef getBaseName(ID id);
60 
61   /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx" or
62   /// "llvm.ssa.copy.p0s_s.1". Note, this version of getName supports overloads.
63   /// This is less efficient than the StringRef version of this function.  If no
64   /// overloads are required, it is safe to use this version, but better to use
65   /// the StringRef version. If one of the types is based on an unnamed type, a
66   /// function type will be computed. Providing FT will avoid this computation.
67   std::string getName(ID Id, ArrayRef<Type *> Tys, Module *M,
68                       FunctionType *FT = nullptr);
69 
70   /// Return the LLVM name for an intrinsic. This is a special version only to
71   /// be used by LLVMIntrinsicCopyOverloadedName. It only supports overloads
72   /// based on named types.
73   std::string getNameNoUnnamedTypes(ID Id, ArrayRef<Type *> Tys);
74 
75   /// Return the function type for an intrinsic.
76   FunctionType *getType(LLVMContext &Context, ID id,
77                         ArrayRef<Type *> Tys = std::nullopt);
78 
79   /// Returns true if the intrinsic can be overloaded.
80   bool isOverloaded(ID id);
81 
82   /// Return the attributes for an intrinsic.
83   AttributeList getAttributes(LLVMContext &C, ID id);
84 
85   /// Create or insert an LLVM Function declaration for an intrinsic, and return
86   /// it.
87   ///
88   /// The Tys parameter is for intrinsics with overloaded types (e.g., those
89   /// using iAny, fAny, vAny, or iPTRAny).  For a declaration of an overloaded
90   /// intrinsic, Tys must provide exactly one type for each overloaded type in
91   /// the intrinsic.
92   Function *getDeclaration(Module *M, ID id,
93                            ArrayRef<Type *> Tys = std::nullopt);
94 
95   /// Looks up Name in NameTable via binary search. NameTable must be sorted
96   /// and all entries must start with "llvm.".  If NameTable contains an exact
97   /// match for Name or a prefix of Name followed by a dot, its index in
98   /// NameTable is returned. Otherwise, -1 is returned.
99   int lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
100                                 StringRef Name);
101 
102   /// Map a Clang builtin name to an intrinsic ID.
103   ID getIntrinsicForClangBuiltin(const char *Prefix, StringRef BuiltinName);
104 
105   /// Map a MS builtin name to an intrinsic ID.
106   ID getIntrinsicForMSBuiltin(const char *Prefix, StringRef BuiltinName);
107 
108   /// This is a type descriptor which explains the type requirements of an
109   /// intrinsic. This is returned by getIntrinsicInfoTableEntries.
110   struct IITDescriptor {
111     enum IITDescriptorKind {
112       Void,
113       VarArg,
114       MMX,
115       Token,
116       Metadata,
117       Half,
118       BFloat,
119       Float,
120       Double,
121       Quad,
122       Integer,
123       Vector,
124       Pointer,
125       Struct,
126       Argument,
127       ExtendArgument,
128       TruncArgument,
129       HalfVecArgument,
130       SameVecWidthArgument,
131       PtrToArgument,
132       PtrToElt,
133       VecOfAnyPtrsToElt,
134       VecElementArgument,
135       Subdivide2Argument,
136       Subdivide4Argument,
137       VecOfBitcastsToInt,
138       AMX,
139       PPCQuad,
140       AnyPtrToElt,
141     } Kind;
142 
143     union {
144       unsigned Integer_Width;
145       unsigned Float_Width;
146       unsigned Pointer_AddressSpace;
147       unsigned Struct_NumElements;
148       unsigned Argument_Info;
149       ElementCount Vector_Width;
150     };
151 
152     enum ArgKind {
153       AK_Any,
154       AK_AnyInteger,
155       AK_AnyFloat,
156       AK_AnyVector,
157       AK_AnyPointer,
158       AK_MatchType = 7
159     };
160 
161     unsigned getArgumentNumber() const {
162       assert(Kind == Argument || Kind == ExtendArgument ||
163              Kind == TruncArgument || Kind == HalfVecArgument ||
164              Kind == SameVecWidthArgument || Kind == PtrToArgument ||
165              Kind == PtrToElt || Kind == VecElementArgument ||
166              Kind == Subdivide2Argument || Kind == Subdivide4Argument ||
167              Kind == VecOfBitcastsToInt);
168       return Argument_Info >> 3;
169     }
170     ArgKind getArgumentKind() const {
171       assert(Kind == Argument || Kind == ExtendArgument ||
172              Kind == TruncArgument || Kind == HalfVecArgument ||
173              Kind == SameVecWidthArgument || Kind == PtrToArgument ||
174              Kind == VecElementArgument || Kind == Subdivide2Argument ||
175              Kind == Subdivide4Argument || Kind == VecOfBitcastsToInt);
176       return (ArgKind)(Argument_Info & 7);
177     }
178 
179     // VecOfAnyPtrsToElt and AnyPtrToElt uses both an overloaded argument (for
180     // address space) and a reference argument (for matching vector width and
181     // element types)
182     unsigned getOverloadArgNumber() const {
183       assert(Kind == VecOfAnyPtrsToElt || Kind == AnyPtrToElt);
184       return Argument_Info >> 16;
185     }
186     unsigned getRefArgNumber() const {
187       assert(Kind == VecOfAnyPtrsToElt || Kind == AnyPtrToElt);
188       return Argument_Info & 0xFFFF;
189     }
190 
191     static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
192       IITDescriptor Result = { K, { Field } };
193       return Result;
194     }
195 
196     static IITDescriptor get(IITDescriptorKind K, unsigned short Hi,
197                              unsigned short Lo) {
198       unsigned Field = Hi << 16 | Lo;
199       IITDescriptor Result = {K, {Field}};
200       return Result;
201     }
202 
203     static IITDescriptor getVector(unsigned Width, bool IsScalable) {
204       IITDescriptor Result = {Vector, {0}};
205       Result.Vector_Width = ElementCount::get(Width, IsScalable);
206       return Result;
207     }
208   };
209 
210   /// Return the IIT table descriptor for the specified intrinsic into an array
211   /// of IITDescriptors.
212   void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
213 
214   enum MatchIntrinsicTypesResult {
215     MatchIntrinsicTypes_Match = 0,
216     MatchIntrinsicTypes_NoMatchRet = 1,
217     MatchIntrinsicTypes_NoMatchArg = 2,
218   };
219 
220   /// Match the specified function type with the type constraints specified by
221   /// the .td file. If the given type is an overloaded type it is pushed to the
222   /// ArgTys vector.
223   ///
224   /// Returns false if the given type matches with the constraints, true
225   /// otherwise.
226   MatchIntrinsicTypesResult
227   matchIntrinsicSignature(FunctionType *FTy, ArrayRef<IITDescriptor> &Infos,
228                           SmallVectorImpl<Type *> &ArgTys);
229 
230   /// Verify if the intrinsic has variable arguments. This method is intended to
231   /// be called after all the fixed arguments have been matched first.
232   ///
233   /// This method returns true on error.
234   bool matchIntrinsicVarArg(bool isVarArg, ArrayRef<IITDescriptor> &Infos);
235 
236   /// Gets the type arguments of an intrinsic call by matching type contraints
237   /// specified by the .td file. The overloaded types are pushed into the
238   /// AgTys vector.
239   ///
240   /// Returns false if the given function is not a valid intrinsic call.
241   bool getIntrinsicSignature(Function *F, SmallVectorImpl<Type *> &ArgTys);
242 
243   // Checks if the intrinsic name matches with its signature and if not
244   // returns the declaration with the same signature and remangled name.
245   // An existing GlobalValue with the wanted name but with a wrong prototype
246   // or of the wrong kind will be renamed by adding ".renamed" to the name.
247   std::optional<Function *> remangleIntrinsicFunction(Function *F);
248 
249 } // End Intrinsic namespace
250 
251 } // End llvm namespace
252 
253 #endif
254