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