xref: /openbsd-src/gnu/llvm/clang/lib/Sema/SemaRISCVVectorLookup.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1*12c85518Srobert //==- SemaRISCVVectorLookup.cpp - Name Lookup for RISC-V Vector Intrinsic -==//
2*12c85518Srobert //
3*12c85518Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*12c85518Srobert // See https://llvm.org/LICENSE.txt for license information.
5*12c85518Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*12c85518Srobert //
7*12c85518Srobert //===----------------------------------------------------------------------===//
8*12c85518Srobert //
9*12c85518Srobert //  This file implements name lookup for RISC-V vector intrinsic.
10*12c85518Srobert //
11*12c85518Srobert //===----------------------------------------------------------------------===//
12*12c85518Srobert 
13*12c85518Srobert #include "clang/AST/ASTContext.h"
14*12c85518Srobert #include "clang/AST/Decl.h"
15*12c85518Srobert #include "clang/Basic/Builtins.h"
16*12c85518Srobert #include "clang/Basic/TargetInfo.h"
17*12c85518Srobert #include "clang/Lex/Preprocessor.h"
18*12c85518Srobert #include "clang/Sema/Lookup.h"
19*12c85518Srobert #include "clang/Sema/RISCVIntrinsicManager.h"
20*12c85518Srobert #include "clang/Sema/Sema.h"
21*12c85518Srobert #include "clang/Support/RISCVVIntrinsicUtils.h"
22*12c85518Srobert #include "llvm/ADT/SmallVector.h"
23*12c85518Srobert #include <optional>
24*12c85518Srobert #include <string>
25*12c85518Srobert #include <vector>
26*12c85518Srobert 
27*12c85518Srobert using namespace llvm;
28*12c85518Srobert using namespace clang;
29*12c85518Srobert using namespace clang::RISCV;
30*12c85518Srobert 
31*12c85518Srobert namespace {
32*12c85518Srobert 
33*12c85518Srobert // Function definition of a RVV intrinsic.
34*12c85518Srobert struct RVVIntrinsicDef {
35*12c85518Srobert   /// Full function name with suffix, e.g. vadd_vv_i32m1.
36*12c85518Srobert   std::string Name;
37*12c85518Srobert 
38*12c85518Srobert   /// Overloaded function name, e.g. vadd.
39*12c85518Srobert   std::string OverloadName;
40*12c85518Srobert 
41*12c85518Srobert   /// Mapping to which clang built-in function, e.g. __builtin_rvv_vadd.
42*12c85518Srobert   std::string BuiltinName;
43*12c85518Srobert 
44*12c85518Srobert   /// Function signature, first element is return type.
45*12c85518Srobert   RVVTypes Signature;
46*12c85518Srobert };
47*12c85518Srobert 
48*12c85518Srobert struct RVVOverloadIntrinsicDef {
49*12c85518Srobert   // Indexes of RISCVIntrinsicManagerImpl::IntrinsicList.
50*12c85518Srobert   SmallVector<size_t, 8> Indexes;
51*12c85518Srobert };
52*12c85518Srobert 
53*12c85518Srobert } // namespace
54*12c85518Srobert 
55*12c85518Srobert static const PrototypeDescriptor RVVSignatureTable[] = {
56*12c85518Srobert #define DECL_SIGNATURE_TABLE
57*12c85518Srobert #include "clang/Basic/riscv_vector_builtin_sema.inc"
58*12c85518Srobert #undef DECL_SIGNATURE_TABLE
59*12c85518Srobert };
60*12c85518Srobert 
61*12c85518Srobert static const RVVIntrinsicRecord RVVIntrinsicRecords[] = {
62*12c85518Srobert #define DECL_INTRINSIC_RECORDS
63*12c85518Srobert #include "clang/Basic/riscv_vector_builtin_sema.inc"
64*12c85518Srobert #undef DECL_INTRINSIC_RECORDS
65*12c85518Srobert };
66*12c85518Srobert 
67*12c85518Srobert // Get subsequence of signature table.
ProtoSeq2ArrayRef(uint16_t Index,uint8_t Length)68*12c85518Srobert static ArrayRef<PrototypeDescriptor> ProtoSeq2ArrayRef(uint16_t Index,
69*12c85518Srobert                                                        uint8_t Length) {
70*12c85518Srobert   return ArrayRef(&RVVSignatureTable[Index], Length);
71*12c85518Srobert }
72*12c85518Srobert 
RVVType2Qual(ASTContext & Context,const RVVType * Type)73*12c85518Srobert static QualType RVVType2Qual(ASTContext &Context, const RVVType *Type) {
74*12c85518Srobert   QualType QT;
75*12c85518Srobert   switch (Type->getScalarType()) {
76*12c85518Srobert   case ScalarTypeKind::Void:
77*12c85518Srobert     QT = Context.VoidTy;
78*12c85518Srobert     break;
79*12c85518Srobert   case ScalarTypeKind::Size_t:
80*12c85518Srobert     QT = Context.getSizeType();
81*12c85518Srobert     break;
82*12c85518Srobert   case ScalarTypeKind::Ptrdiff_t:
83*12c85518Srobert     QT = Context.getPointerDiffType();
84*12c85518Srobert     break;
85*12c85518Srobert   case ScalarTypeKind::UnsignedLong:
86*12c85518Srobert     QT = Context.UnsignedLongTy;
87*12c85518Srobert     break;
88*12c85518Srobert   case ScalarTypeKind::SignedLong:
89*12c85518Srobert     QT = Context.LongTy;
90*12c85518Srobert     break;
91*12c85518Srobert   case ScalarTypeKind::Boolean:
92*12c85518Srobert     QT = Context.BoolTy;
93*12c85518Srobert     break;
94*12c85518Srobert   case ScalarTypeKind::SignedInteger:
95*12c85518Srobert     QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), true);
96*12c85518Srobert     break;
97*12c85518Srobert   case ScalarTypeKind::UnsignedInteger:
98*12c85518Srobert     QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), false);
99*12c85518Srobert     break;
100*12c85518Srobert   case ScalarTypeKind::Float:
101*12c85518Srobert     switch (Type->getElementBitwidth()) {
102*12c85518Srobert     case 64:
103*12c85518Srobert       QT = Context.DoubleTy;
104*12c85518Srobert       break;
105*12c85518Srobert     case 32:
106*12c85518Srobert       QT = Context.FloatTy;
107*12c85518Srobert       break;
108*12c85518Srobert     case 16:
109*12c85518Srobert       QT = Context.Float16Ty;
110*12c85518Srobert       break;
111*12c85518Srobert     default:
112*12c85518Srobert       llvm_unreachable("Unsupported floating point width.");
113*12c85518Srobert     }
114*12c85518Srobert     break;
115*12c85518Srobert   case Invalid:
116*12c85518Srobert     llvm_unreachable("Unhandled type.");
117*12c85518Srobert   }
118*12c85518Srobert   if (Type->isVector())
119*12c85518Srobert     QT = Context.getScalableVectorType(QT, *Type->getScale());
120*12c85518Srobert 
121*12c85518Srobert   if (Type->isConstant())
122*12c85518Srobert     QT = Context.getConstType(QT);
123*12c85518Srobert 
124*12c85518Srobert   // Transform the type to a pointer as the last step, if necessary.
125*12c85518Srobert   if (Type->isPointer())
126*12c85518Srobert     QT = Context.getPointerType(QT);
127*12c85518Srobert 
128*12c85518Srobert   return QT;
129*12c85518Srobert }
130*12c85518Srobert 
131*12c85518Srobert namespace {
132*12c85518Srobert class RISCVIntrinsicManagerImpl : public sema::RISCVIntrinsicManager {
133*12c85518Srobert private:
134*12c85518Srobert   Sema &S;
135*12c85518Srobert   ASTContext &Context;
136*12c85518Srobert   RVVTypeCache TypeCache;
137*12c85518Srobert 
138*12c85518Srobert   // List of all RVV intrinsic.
139*12c85518Srobert   std::vector<RVVIntrinsicDef> IntrinsicList;
140*12c85518Srobert   // Mapping function name to index of IntrinsicList.
141*12c85518Srobert   StringMap<size_t> Intrinsics;
142*12c85518Srobert   // Mapping function name to RVVOverloadIntrinsicDef.
143*12c85518Srobert   StringMap<RVVOverloadIntrinsicDef> OverloadIntrinsics;
144*12c85518Srobert 
145*12c85518Srobert   // Create IntrinsicList
146*12c85518Srobert   void InitIntrinsicList();
147*12c85518Srobert 
148*12c85518Srobert   // Create RVVIntrinsicDef.
149*12c85518Srobert   void InitRVVIntrinsic(const RVVIntrinsicRecord &Record, StringRef SuffixStr,
150*12c85518Srobert                         StringRef OverloadedSuffixStr, bool IsMask,
151*12c85518Srobert                         RVVTypes &Types, bool HasPolicy, Policy PolicyAttrs);
152*12c85518Srobert 
153*12c85518Srobert   // Create FunctionDecl for a vector intrinsic.
154*12c85518Srobert   void CreateRVVIntrinsicDecl(LookupResult &LR, IdentifierInfo *II,
155*12c85518Srobert                               Preprocessor &PP, unsigned Index,
156*12c85518Srobert                               bool IsOverload);
157*12c85518Srobert 
158*12c85518Srobert public:
RISCVIntrinsicManagerImpl(clang::Sema & S)159*12c85518Srobert   RISCVIntrinsicManagerImpl(clang::Sema &S) : S(S), Context(S.Context) {
160*12c85518Srobert     InitIntrinsicList();
161*12c85518Srobert   }
162*12c85518Srobert 
163*12c85518Srobert   // Create RISC-V vector intrinsic and insert into symbol table if found, and
164*12c85518Srobert   // return true, otherwise return false.
165*12c85518Srobert   bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II,
166*12c85518Srobert                               Preprocessor &PP) override;
167*12c85518Srobert };
168*12c85518Srobert } // namespace
169*12c85518Srobert 
InitIntrinsicList()170*12c85518Srobert void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
171*12c85518Srobert   const TargetInfo &TI = Context.getTargetInfo();
172*12c85518Srobert   bool HasVectorFloat32 = TI.hasFeature("zve32f");
173*12c85518Srobert   bool HasVectorFloat64 = TI.hasFeature("zve64d");
174*12c85518Srobert   bool HasZvfh = TI.hasFeature("experimental-zvfh");
175*12c85518Srobert   bool HasRV64 = TI.hasFeature("64bit");
176*12c85518Srobert   bool HasFullMultiply = TI.hasFeature("v");
177*12c85518Srobert 
178*12c85518Srobert   // Construction of RVVIntrinsicRecords need to sync with createRVVIntrinsics
179*12c85518Srobert   // in RISCVVEmitter.cpp.
180*12c85518Srobert   for (auto &Record : RVVIntrinsicRecords) {
181*12c85518Srobert     // Create Intrinsics for each type and LMUL.
182*12c85518Srobert     BasicType BaseType = BasicType::Unknown;
183*12c85518Srobert     ArrayRef<PrototypeDescriptor> BasicProtoSeq =
184*12c85518Srobert         ProtoSeq2ArrayRef(Record.PrototypeIndex, Record.PrototypeLength);
185*12c85518Srobert     ArrayRef<PrototypeDescriptor> SuffixProto =
186*12c85518Srobert         ProtoSeq2ArrayRef(Record.SuffixIndex, Record.SuffixLength);
187*12c85518Srobert     ArrayRef<PrototypeDescriptor> OverloadedSuffixProto = ProtoSeq2ArrayRef(
188*12c85518Srobert         Record.OverloadedSuffixIndex, Record.OverloadedSuffixSize);
189*12c85518Srobert 
190*12c85518Srobert     PolicyScheme UnMaskedPolicyScheme =
191*12c85518Srobert         static_cast<PolicyScheme>(Record.UnMaskedPolicyScheme);
192*12c85518Srobert     PolicyScheme MaskedPolicyScheme =
193*12c85518Srobert         static_cast<PolicyScheme>(Record.MaskedPolicyScheme);
194*12c85518Srobert 
195*12c85518Srobert     const Policy DefaultPolicy;
196*12c85518Srobert 
197*12c85518Srobert     llvm::SmallVector<PrototypeDescriptor> ProtoSeq =
198*12c85518Srobert         RVVIntrinsic::computeBuiltinTypes(BasicProtoSeq, /*IsMasked=*/false,
199*12c85518Srobert                                           /*HasMaskedOffOperand=*/false,
200*12c85518Srobert                                           Record.HasVL, Record.NF,
201*12c85518Srobert                                           UnMaskedPolicyScheme, DefaultPolicy);
202*12c85518Srobert 
203*12c85518Srobert     llvm::SmallVector<PrototypeDescriptor> ProtoMaskSeq =
204*12c85518Srobert         RVVIntrinsic::computeBuiltinTypes(
205*12c85518Srobert             BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand,
206*12c85518Srobert             Record.HasVL, Record.NF, MaskedPolicyScheme, DefaultPolicy);
207*12c85518Srobert 
208*12c85518Srobert     bool UnMaskedHasPolicy = UnMaskedPolicyScheme != PolicyScheme::SchemeNone;
209*12c85518Srobert     bool MaskedHasPolicy = MaskedPolicyScheme != PolicyScheme::SchemeNone;
210*12c85518Srobert     SmallVector<Policy> SupportedUnMaskedPolicies =
211*12c85518Srobert         RVVIntrinsic::getSupportedUnMaskedPolicies();
212*12c85518Srobert     SmallVector<Policy> SupportedMaskedPolicies =
213*12c85518Srobert         RVVIntrinsic::getSupportedMaskedPolicies(Record.HasTailPolicy,
214*12c85518Srobert                                                  Record.HasMaskPolicy);
215*12c85518Srobert 
216*12c85518Srobert     for (unsigned int TypeRangeMaskShift = 0;
217*12c85518Srobert          TypeRangeMaskShift <= static_cast<unsigned int>(BasicType::MaxOffset);
218*12c85518Srobert          ++TypeRangeMaskShift) {
219*12c85518Srobert       unsigned int BaseTypeI = 1 << TypeRangeMaskShift;
220*12c85518Srobert       BaseType = static_cast<BasicType>(BaseTypeI);
221*12c85518Srobert 
222*12c85518Srobert       if ((BaseTypeI & Record.TypeRangeMask) != BaseTypeI)
223*12c85518Srobert         continue;
224*12c85518Srobert 
225*12c85518Srobert       // Check requirement.
226*12c85518Srobert       if (BaseType == BasicType::Float16 && !HasZvfh)
227*12c85518Srobert         continue;
228*12c85518Srobert 
229*12c85518Srobert       if (BaseType == BasicType::Float32 && !HasVectorFloat32)
230*12c85518Srobert         continue;
231*12c85518Srobert 
232*12c85518Srobert       if (BaseType == BasicType::Float64 && !HasVectorFloat64)
233*12c85518Srobert         continue;
234*12c85518Srobert 
235*12c85518Srobert       if (((Record.RequiredExtensions & RVV_REQ_RV64) == RVV_REQ_RV64) &&
236*12c85518Srobert           !HasRV64)
237*12c85518Srobert         continue;
238*12c85518Srobert 
239*12c85518Srobert       if ((BaseType == BasicType::Int64) &&
240*12c85518Srobert           ((Record.RequiredExtensions & RVV_REQ_FullMultiply) ==
241*12c85518Srobert            RVV_REQ_FullMultiply) &&
242*12c85518Srobert           !HasFullMultiply)
243*12c85518Srobert         continue;
244*12c85518Srobert 
245*12c85518Srobert       // Expanded with different LMUL.
246*12c85518Srobert       for (int Log2LMUL = -3; Log2LMUL <= 3; Log2LMUL++) {
247*12c85518Srobert         if (!(Record.Log2LMULMask & (1 << (Log2LMUL + 3))))
248*12c85518Srobert           continue;
249*12c85518Srobert 
250*12c85518Srobert         std::optional<RVVTypes> Types =
251*12c85518Srobert             TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoSeq);
252*12c85518Srobert 
253*12c85518Srobert         // Ignored to create new intrinsic if there are any illegal types.
254*12c85518Srobert         if (!Types.has_value())
255*12c85518Srobert           continue;
256*12c85518Srobert 
257*12c85518Srobert         std::string SuffixStr = RVVIntrinsic::getSuffixStr(
258*12c85518Srobert             TypeCache, BaseType, Log2LMUL, SuffixProto);
259*12c85518Srobert         std::string OverloadedSuffixStr = RVVIntrinsic::getSuffixStr(
260*12c85518Srobert             TypeCache, BaseType, Log2LMUL, OverloadedSuffixProto);
261*12c85518Srobert 
262*12c85518Srobert         // Create non-masked intrinsic.
263*12c85518Srobert         InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, false, *Types,
264*12c85518Srobert                          UnMaskedHasPolicy, DefaultPolicy);
265*12c85518Srobert 
266*12c85518Srobert         // Create non-masked policy intrinsic.
267*12c85518Srobert         if (Record.UnMaskedPolicyScheme != PolicyScheme::SchemeNone) {
268*12c85518Srobert           for (auto P : SupportedUnMaskedPolicies) {
269*12c85518Srobert             llvm::SmallVector<PrototypeDescriptor> PolicyPrototype =
270*12c85518Srobert                 RVVIntrinsic::computeBuiltinTypes(
271*12c85518Srobert                     BasicProtoSeq, /*IsMasked=*/false,
272*12c85518Srobert                     /*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF,
273*12c85518Srobert                     UnMaskedPolicyScheme, P);
274*12c85518Srobert             std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
275*12c85518Srobert                 BaseType, Log2LMUL, Record.NF, PolicyPrototype);
276*12c85518Srobert             InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
277*12c85518Srobert                              /*IsMask=*/false, *PolicyTypes, UnMaskedHasPolicy,
278*12c85518Srobert                              P);
279*12c85518Srobert           }
280*12c85518Srobert         }
281*12c85518Srobert         if (!Record.HasMasked)
282*12c85518Srobert           continue;
283*12c85518Srobert         // Create masked intrinsic.
284*12c85518Srobert         std::optional<RVVTypes> MaskTypes =
285*12c85518Srobert             TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoMaskSeq);
286*12c85518Srobert         InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, true,
287*12c85518Srobert                          *MaskTypes, MaskedHasPolicy, DefaultPolicy);
288*12c85518Srobert         if (Record.MaskedPolicyScheme == PolicyScheme::SchemeNone)
289*12c85518Srobert           continue;
290*12c85518Srobert         // Create masked policy intrinsic.
291*12c85518Srobert         for (auto P : SupportedMaskedPolicies) {
292*12c85518Srobert           llvm::SmallVector<PrototypeDescriptor> PolicyPrototype =
293*12c85518Srobert               RVVIntrinsic::computeBuiltinTypes(
294*12c85518Srobert                   BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand,
295*12c85518Srobert                   Record.HasVL, Record.NF, MaskedPolicyScheme, P);
296*12c85518Srobert           std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
297*12c85518Srobert               BaseType, Log2LMUL, Record.NF, PolicyPrototype);
298*12c85518Srobert           InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
299*12c85518Srobert                            /*IsMask=*/true, *PolicyTypes, MaskedHasPolicy, P);
300*12c85518Srobert         }
301*12c85518Srobert       } // End for different LMUL
302*12c85518Srobert     } // End for different TypeRange
303*12c85518Srobert   }
304*12c85518Srobert }
305*12c85518Srobert 
306*12c85518Srobert // Compute name and signatures for intrinsic with practical types.
InitRVVIntrinsic(const RVVIntrinsicRecord & Record,StringRef SuffixStr,StringRef OverloadedSuffixStr,bool IsMasked,RVVTypes & Signature,bool HasPolicy,Policy PolicyAttrs)307*12c85518Srobert void RISCVIntrinsicManagerImpl::InitRVVIntrinsic(
308*12c85518Srobert     const RVVIntrinsicRecord &Record, StringRef SuffixStr,
309*12c85518Srobert     StringRef OverloadedSuffixStr, bool IsMasked, RVVTypes &Signature,
310*12c85518Srobert     bool HasPolicy, Policy PolicyAttrs) {
311*12c85518Srobert   // Function name, e.g. vadd_vv_i32m1.
312*12c85518Srobert   std::string Name = Record.Name;
313*12c85518Srobert   if (!SuffixStr.empty())
314*12c85518Srobert     Name += "_" + SuffixStr.str();
315*12c85518Srobert 
316*12c85518Srobert   // Overloaded function name, e.g. vadd.
317*12c85518Srobert   std::string OverloadedName;
318*12c85518Srobert   if (!Record.OverloadedName)
319*12c85518Srobert     OverloadedName = StringRef(Record.Name).split("_").first.str();
320*12c85518Srobert   else
321*12c85518Srobert     OverloadedName = Record.OverloadedName;
322*12c85518Srobert   if (!OverloadedSuffixStr.empty())
323*12c85518Srobert     OverloadedName += "_" + OverloadedSuffixStr.str();
324*12c85518Srobert 
325*12c85518Srobert   // clang built-in function name, e.g. __builtin_rvv_vadd.
326*12c85518Srobert   std::string BuiltinName = "__builtin_rvv_" + std::string(Record.Name);
327*12c85518Srobert 
328*12c85518Srobert   RVVIntrinsic::updateNamesAndPolicy(IsMasked, HasPolicy, Name, BuiltinName,
329*12c85518Srobert                                      OverloadedName, PolicyAttrs);
330*12c85518Srobert 
331*12c85518Srobert   // Put into IntrinsicList.
332*12c85518Srobert   size_t Index = IntrinsicList.size();
333*12c85518Srobert   IntrinsicList.push_back({Name, OverloadedName, BuiltinName, Signature});
334*12c85518Srobert 
335*12c85518Srobert   // Creating mapping to Intrinsics.
336*12c85518Srobert   Intrinsics.insert({Name, Index});
337*12c85518Srobert 
338*12c85518Srobert   // Get the RVVOverloadIntrinsicDef.
339*12c85518Srobert   RVVOverloadIntrinsicDef &OverloadIntrinsicDef =
340*12c85518Srobert       OverloadIntrinsics[OverloadedName];
341*12c85518Srobert 
342*12c85518Srobert   // And added the index.
343*12c85518Srobert   OverloadIntrinsicDef.Indexes.push_back(Index);
344*12c85518Srobert }
345*12c85518Srobert 
CreateRVVIntrinsicDecl(LookupResult & LR,IdentifierInfo * II,Preprocessor & PP,unsigned Index,bool IsOverload)346*12c85518Srobert void RISCVIntrinsicManagerImpl::CreateRVVIntrinsicDecl(LookupResult &LR,
347*12c85518Srobert                                                        IdentifierInfo *II,
348*12c85518Srobert                                                        Preprocessor &PP,
349*12c85518Srobert                                                        unsigned Index,
350*12c85518Srobert                                                        bool IsOverload) {
351*12c85518Srobert   ASTContext &Context = S.Context;
352*12c85518Srobert   RVVIntrinsicDef &IDef = IntrinsicList[Index];
353*12c85518Srobert   RVVTypes Sigs = IDef.Signature;
354*12c85518Srobert   size_t SigLength = Sigs.size();
355*12c85518Srobert   RVVType *ReturnType = Sigs[0];
356*12c85518Srobert   QualType RetType = RVVType2Qual(Context, ReturnType);
357*12c85518Srobert   SmallVector<QualType, 8> ArgTypes;
358*12c85518Srobert   QualType BuiltinFuncType;
359*12c85518Srobert 
360*12c85518Srobert   // Skip return type, and convert RVVType to QualType for arguments.
361*12c85518Srobert   for (size_t i = 1; i < SigLength; ++i)
362*12c85518Srobert     ArgTypes.push_back(RVVType2Qual(Context, Sigs[i]));
363*12c85518Srobert 
364*12c85518Srobert   FunctionProtoType::ExtProtoInfo PI(
365*12c85518Srobert       Context.getDefaultCallingConvention(false, false, true));
366*12c85518Srobert 
367*12c85518Srobert   PI.Variadic = false;
368*12c85518Srobert 
369*12c85518Srobert   SourceLocation Loc = LR.getNameLoc();
370*12c85518Srobert   BuiltinFuncType = Context.getFunctionType(RetType, ArgTypes, PI);
371*12c85518Srobert   DeclContext *Parent = Context.getTranslationUnitDecl();
372*12c85518Srobert 
373*12c85518Srobert   FunctionDecl *RVVIntrinsicDecl = FunctionDecl::Create(
374*12c85518Srobert       Context, Parent, Loc, Loc, II, BuiltinFuncType, /*TInfo=*/nullptr,
375*12c85518Srobert       SC_Extern, S.getCurFPFeatures().isFPConstrained(),
376*12c85518Srobert       /*isInlineSpecified*/ false,
377*12c85518Srobert       /*hasWrittenPrototype*/ true);
378*12c85518Srobert 
379*12c85518Srobert   // Create Decl objects for each parameter, adding them to the
380*12c85518Srobert   // FunctionDecl.
381*12c85518Srobert   const auto *FP = cast<FunctionProtoType>(BuiltinFuncType);
382*12c85518Srobert   SmallVector<ParmVarDecl *, 8> ParmList;
383*12c85518Srobert   for (unsigned IParm = 0, E = FP->getNumParams(); IParm != E; ++IParm) {
384*12c85518Srobert     ParmVarDecl *Parm =
385*12c85518Srobert         ParmVarDecl::Create(Context, RVVIntrinsicDecl, Loc, Loc, nullptr,
386*12c85518Srobert                             FP->getParamType(IParm), nullptr, SC_None, nullptr);
387*12c85518Srobert     Parm->setScopeInfo(0, IParm);
388*12c85518Srobert     ParmList.push_back(Parm);
389*12c85518Srobert   }
390*12c85518Srobert   RVVIntrinsicDecl->setParams(ParmList);
391*12c85518Srobert 
392*12c85518Srobert   // Add function attributes.
393*12c85518Srobert   if (IsOverload)
394*12c85518Srobert     RVVIntrinsicDecl->addAttr(OverloadableAttr::CreateImplicit(Context));
395*12c85518Srobert 
396*12c85518Srobert   // Setup alias to __builtin_rvv_*
397*12c85518Srobert   IdentifierInfo &IntrinsicII = PP.getIdentifierTable().get(IDef.BuiltinName);
398*12c85518Srobert   RVVIntrinsicDecl->addAttr(
399*12c85518Srobert       BuiltinAliasAttr::CreateImplicit(S.Context, &IntrinsicII));
400*12c85518Srobert 
401*12c85518Srobert   // Add to symbol table.
402*12c85518Srobert   LR.addDecl(RVVIntrinsicDecl);
403*12c85518Srobert }
404*12c85518Srobert 
CreateIntrinsicIfFound(LookupResult & LR,IdentifierInfo * II,Preprocessor & PP)405*12c85518Srobert bool RISCVIntrinsicManagerImpl::CreateIntrinsicIfFound(LookupResult &LR,
406*12c85518Srobert                                                        IdentifierInfo *II,
407*12c85518Srobert                                                        Preprocessor &PP) {
408*12c85518Srobert   StringRef Name = II->getName();
409*12c85518Srobert 
410*12c85518Srobert   // Lookup the function name from the overload intrinsics first.
411*12c85518Srobert   auto OvIItr = OverloadIntrinsics.find(Name);
412*12c85518Srobert   if (OvIItr != OverloadIntrinsics.end()) {
413*12c85518Srobert     const RVVOverloadIntrinsicDef &OvIntrinsicDef = OvIItr->second;
414*12c85518Srobert     for (auto Index : OvIntrinsicDef.Indexes)
415*12c85518Srobert       CreateRVVIntrinsicDecl(LR, II, PP, Index,
416*12c85518Srobert                              /*IsOverload*/ true);
417*12c85518Srobert 
418*12c85518Srobert     // If we added overloads, need to resolve the lookup result.
419*12c85518Srobert     LR.resolveKind();
420*12c85518Srobert     return true;
421*12c85518Srobert   }
422*12c85518Srobert 
423*12c85518Srobert   // Lookup the function name from the intrinsics.
424*12c85518Srobert   auto Itr = Intrinsics.find(Name);
425*12c85518Srobert   if (Itr != Intrinsics.end()) {
426*12c85518Srobert     CreateRVVIntrinsicDecl(LR, II, PP, Itr->second,
427*12c85518Srobert                            /*IsOverload*/ false);
428*12c85518Srobert     return true;
429*12c85518Srobert   }
430*12c85518Srobert 
431*12c85518Srobert   // It's not an RVV intrinsics.
432*12c85518Srobert   return false;
433*12c85518Srobert }
434*12c85518Srobert 
435*12c85518Srobert namespace clang {
436*12c85518Srobert std::unique_ptr<clang::sema::RISCVIntrinsicManager>
CreateRISCVIntrinsicManager(Sema & S)437*12c85518Srobert CreateRISCVIntrinsicManager(Sema &S) {
438*12c85518Srobert   return std::make_unique<RISCVIntrinsicManagerImpl>(S);
439*12c85518Srobert }
440*12c85518Srobert } // namespace clang
441