22#include "llvm/ADT/SmallVector.h"
36struct RVVIntrinsicDef {
38 std::string BuiltinName;
44struct RVVOverloadIntrinsicDef {
52#define DECL_SIGNATURE_TABLE
53#include "clang/Basic/riscv_vector_builtin_sema.inc"
54#undef DECL_SIGNATURE_TABLE
58#define DECL_SIGNATURE_TABLE
59#include "clang/Basic/riscv_sifive_vector_builtin_sema.inc"
60#undef DECL_SIGNATURE_TABLE
64#define DECL_INTRINSIC_RECORDS
65#include "clang/Basic/riscv_vector_builtin_sema.inc"
66#undef DECL_INTRINSIC_RECORDS
70#define DECL_INTRINSIC_RECORDS
71#include "clang/Basic/riscv_sifive_vector_builtin_sema.inc"
72#undef DECL_INTRINSIC_RECORDS
79 case IntrinsicKind::RVV:
81 case IntrinsicKind::SIFIVE_VECTOR:
84 llvm_unreachable(
"Unhandled IntrinsicKind");
89 switch (
Type->getScalarType()) {
90 case ScalarTypeKind::Void:
93 case ScalarTypeKind::Size_t:
96 case ScalarTypeKind::Ptrdiff_t:
99 case ScalarTypeKind::UnsignedLong:
102 case ScalarTypeKind::SignedLong:
105 case ScalarTypeKind::Boolean:
108 case ScalarTypeKind::SignedInteger:
111 case ScalarTypeKind::UnsignedInteger:
114 case ScalarTypeKind::BFloat:
117 case ScalarTypeKind::Float:
118 switch (
Type->getElementBitwidth()) {
129 llvm_unreachable(
"Unsupported floating point width.");
134 llvm_unreachable(
"Unhandled type.");
136 if (
Type->isVector()) {
143 if (
Type->isConstant())
147 if (
Type->isPointer())
159 bool ConstructedRISCVVBuiltins;
160 bool ConstructedRISCVSiFiveVectorBuiltins;
163 std::vector<RVVIntrinsicDef> IntrinsicList;
165 StringMap<uint16_t> Intrinsics;
167 StringMap<RVVOverloadIntrinsicDef> OverloadIntrinsics;
172 StringRef OverloadedSuffixStr,
bool IsMask,
184 RISCVIntrinsicManagerImpl(
clang::Sema &S) : S(S), Context(S.Context) {
185 ConstructedRISCVVBuiltins =
false;
186 ConstructedRISCVSiFiveVectorBuiltins =
false;
199void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics(
202 static const std::pair<const char *, RVVRequire> FeatureCheckList[] = {
224 for (
auto &
Record : Recs) {
226 if (llvm::any_of(FeatureCheckList, [&](
const auto &Item) {
227 return (
Record.RequiredExtensions & Item.second) == Item.second &&
239 K,
Record.OverloadedSuffixIndex,
Record.OverloadedSuffixSize);
246 const Policy DefaultPolicy;
250 BasicProtoSeq,
false,
252 UnMaskedPolicyScheme, DefaultPolicy,
Record.IsTuple);
257 BasicProtoSeq,
true,
Record.HasMaskedOffOperand,
258 Record.HasVL,
Record.NF, MaskedPolicyScheme, DefaultPolicy,
261 bool UnMaskedHasPolicy = UnMaskedPolicyScheme != PolicyScheme::SchemeNone;
262 bool MaskedHasPolicy = MaskedPolicyScheme != PolicyScheme::SchemeNone;
269 for (
unsigned int TypeRangeMaskShift = 0;
270 TypeRangeMaskShift <= static_cast<unsigned int>(BasicType::MaxOffset);
271 ++TypeRangeMaskShift) {
272 unsigned int BaseTypeI = 1 << TypeRangeMaskShift;
273 BaseType =
static_cast<BasicType>(BaseTypeI);
275 if ((BaseTypeI &
Record.TypeRangeMask) != BaseTypeI)
278 if (BaseType == BasicType::Float16) {
288 for (
int Log2LMUL = -3; Log2LMUL <= 3; Log2LMUL++) {
289 if (!(
Record.Log2LMULMask & (1 << (Log2LMUL + 3))))
292 std::optional<RVVTypes> Types =
293 TypeCache.computeTypes(BaseType, Log2LMUL,
Record.NF, ProtoSeq);
296 if (!Types.has_value())
300 TypeCache, BaseType, Log2LMUL, SuffixProto);
302 TypeCache, BaseType, Log2LMUL, OverloadedSuffixProto);
305 InitRVVIntrinsic(
Record, SuffixStr, OverloadedSuffixStr,
false, *Types,
306 UnMaskedHasPolicy, DefaultPolicy);
309 if (
Record.UnMaskedPolicyScheme != PolicyScheme::SchemeNone) {
310 for (
auto P : SupportedUnMaskedPolicies) {
313 BasicProtoSeq,
false,
315 UnMaskedPolicyScheme,
P,
Record.IsTuple);
316 std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
317 BaseType, Log2LMUL,
Record.NF, PolicyPrototype);
318 InitRVVIntrinsic(
Record, SuffixStr, OverloadedSuffixStr,
319 false, *PolicyTypes, UnMaskedHasPolicy,
326 std::optional<RVVTypes> MaskTypes =
327 TypeCache.computeTypes(BaseType, Log2LMUL,
Record.NF, ProtoMaskSeq);
328 InitRVVIntrinsic(
Record, SuffixStr, OverloadedSuffixStr,
true,
329 *MaskTypes, MaskedHasPolicy, DefaultPolicy);
330 if (
Record.MaskedPolicyScheme == PolicyScheme::SchemeNone)
333 for (
auto P : SupportedMaskedPolicies) {
336 BasicProtoSeq,
true,
Record.HasMaskedOffOperand,
339 std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
340 BaseType, Log2LMUL,
Record.NF, PolicyPrototype);
341 InitRVVIntrinsic(
Record, SuffixStr, OverloadedSuffixStr,
342 true, *PolicyTypes, MaskedHasPolicy,
P);
349void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
352 ConstructedRISCVVBuiltins =
true;
357 !ConstructedRISCVSiFiveVectorBuiltins) {
358 ConstructedRISCVSiFiveVectorBuiltins =
true;
360 IntrinsicKind::SIFIVE_VECTOR);
365void RISCVIntrinsicManagerImpl::InitRVVIntrinsic(
367 StringRef OverloadedSuffixStr,
bool IsMasked,
RVVTypes &Signature,
368 bool HasPolicy,
Policy PolicyAttrs) {
370 std::string Name =
Record.Name;
371 if (!SuffixStr.empty())
372 Name +=
"_" + SuffixStr.str();
375 std::string OverloadedName;
376 if (!
Record.OverloadedName)
377 OverloadedName = StringRef(
Record.Name).split(
"_").first.str();
379 OverloadedName =
Record.OverloadedName;
380 if (!OverloadedSuffixStr.empty())
381 OverloadedName +=
"_" + OverloadedSuffixStr.str();
384 std::string BuiltinName = std::string(
Record.Name);
387 OverloadedName, PolicyAttrs,
388 Record.HasFRMRoundModeOp);
391 uint16_t Index = IntrinsicList.size();
392 assert(IntrinsicList.size() == (
size_t)Index &&
393 "Intrinsics indices overflow.");
394 IntrinsicList.push_back({BuiltinName, Signature});
397 Intrinsics.insert({Name, Index});
400 RVVOverloadIntrinsicDef &OverloadIntrinsicDef =
401 OverloadIntrinsics[OverloadedName];
404 OverloadIntrinsicDef.Indexes.push_back(Index);
407void RISCVIntrinsicManagerImpl::CreateRVVIntrinsicDecl(
LookupResult &LR,
413 RVVIntrinsicDef &IDef = IntrinsicList[Index];
415 size_t SigLength = Sigs.size();
422 for (
size_t i = 1; i < SigLength; ++i)
435 Context,
Parent, Loc, Loc, II, BuiltinFuncType,
nullptr,
442 const auto *FP = cast<FunctionProtoType>(BuiltinFuncType);
444 for (
unsigned IParm = 0, E = FP->getNumParams(); IParm != E; ++IParm) {
447 FP->getParamType(IParm),
nullptr,
SC_None,
nullptr);
449 ParmList.push_back(Parm);
451 RVVIntrinsicDecl->setParams(ParmList);
455 RVVIntrinsicDecl->
addAttr(OverloadableAttr::CreateImplicit(Context));
461 BuiltinAliasAttr::CreateImplicit(S.
Context, &IntrinsicII));
467bool RISCVIntrinsicManagerImpl::CreateIntrinsicIfFound(
LookupResult &LR,
470 StringRef Name = II->
getName();
471 if (!Name.consume_front(
"__riscv_"))
475 auto OvIItr = OverloadIntrinsics.find(Name);
476 if (OvIItr != OverloadIntrinsics.end()) {
477 const RVVOverloadIntrinsicDef &OvIntrinsicDef = OvIItr->second;
478 for (
auto Index : OvIntrinsicDef.Indexes)
479 CreateRVVIntrinsicDecl(LR, II, PP, Index,
488 auto Itr = Intrinsics.find(Name);
489 if (Itr != Intrinsics.end()) {
490 CreateRVVIntrinsicDecl(LR, II, PP, Itr->second,
500std::unique_ptr<clang::sema::RISCVIntrinsicManager>
502 return std::make_unique<RISCVIntrinsicManagerImpl>(S);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::MachO::Record Record
Defines the clang::Preprocessor interface.
static const RVVIntrinsicRecord RVSiFiveVectorIntrinsicRecords[]
static const RVVIntrinsicRecord RVVIntrinsicRecords[]
static const PrototypeDescriptor RVSiFiveVectorSignatureTable[]
static QualType RVVType2Qual(ASTContext &Context, const RVVType *Type)
static ArrayRef< PrototypeDescriptor > ProtoSeq2ArrayRef(IntrinsicKind K, uint16_t Index, uint8_t Length)
static const PrototypeDescriptor RVVSignatureTable[]
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getScalableVectorType(QualType EltTy, unsigned NumElts, unsigned NumFields=1) const
Return the unique reference to a scalable vector type of the specified element type and scalable numb...
CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod, bool IsBuiltin=false) const
Retrieves the default calling convention for the current target.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstType(QualType T) const
Return the uniqued reference to the type for a const qualified type.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CanQualType UnsignedLongTy
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isFPConstrained() const
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, Expr *TrailingRequiresClause=nullptr)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Represents the results of name lookup.
void addDecl(NamedDecl *D)
Add a declaration to these results with its natural access.
void resolveKind()
Resolves the result kind of the lookup, possibly hiding decls.
SourceLocation getNameLoc() const
Gets the location of the identifier.
Represents a parameter to a function.
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
IdentifierTable & getIdentifierTable()
A (possibly-)qualified type.
static llvm::SmallVector< Policy > getSupportedMaskedPolicies(bool HasTailPolicy, bool HasMaskPolicy)
static llvm::SmallVector< PrototypeDescriptor > computeBuiltinTypes(llvm::ArrayRef< PrototypeDescriptor > Prototype, bool IsMasked, bool HasMaskedOffOperand, bool HasVL, unsigned NF, PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple)
static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName, std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp)
static std::string getSuffixStr(RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL, llvm::ArrayRef< PrototypeDescriptor > PrototypeDescriptors)
static llvm::SmallVector< Policy > getSupportedUnMaskedPolicies()
Sema - This implements semantic analysis and AST building for C.
bool DeclareRISCVSiFiveVectorBuiltins
Indicate RISC-V SiFive vector builtin functions enabled or not.
FPOptions & getCurFPFeatures()
bool DeclareRISCVVBuiltins
Indicate RISC-V vector builtin functions enabled or not.
Encodes a location in the source.
Exposes information about the current target.
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
The base class of the type hierarchy.
virtual bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II, Preprocessor &PP)=0
virtual void InitIntrinsicList()=0
Defines the clang::TargetInfo interface.
@ RVV_REQ_Xsfvfnrclipxfqf
std::vector< RVVTypePtr > RVVTypes
The JSON file list parser is used to communicate input to InstallAPI.
std::unique_ptr< sema::RISCVIntrinsicManager > CreateRISCVIntrinsicManager(Sema &S)
Diagnostic wrappers for TextAPI types for error reporting.
Extra information about a function prototype.