22#include "llvm/ADT/SmallVector.h"
36struct RVVIntrinsicDef {
41 std::string OverloadName;
44 std::string BuiltinName;
50struct RVVOverloadIntrinsicDef {
58#define DECL_SIGNATURE_TABLE
59#include "clang/Basic/riscv_vector_builtin_sema.inc"
60#undef DECL_SIGNATURE_TABLE
64#define DECL_SIGNATURE_TABLE
65#include "clang/Basic/riscv_sifive_vector_builtin_sema.inc"
66#undef DECL_SIGNATURE_TABLE
70#define DECL_INTRINSIC_RECORDS
71#include "clang/Basic/riscv_vector_builtin_sema.inc"
72#undef DECL_INTRINSIC_RECORDS
76#define DECL_INTRINSIC_RECORDS
77#include "clang/Basic/riscv_sifive_vector_builtin_sema.inc"
78#undef DECL_INTRINSIC_RECORDS
85 case IntrinsicKind::RVV:
87 case IntrinsicKind::SIFIVE_VECTOR:
90 llvm_unreachable(
"Unhandled IntrinsicKind");
95 switch (
Type->getScalarType()) {
96 case ScalarTypeKind::Void:
99 case ScalarTypeKind::Size_t:
102 case ScalarTypeKind::Ptrdiff_t:
105 case ScalarTypeKind::UnsignedLong:
108 case ScalarTypeKind::SignedLong:
111 case ScalarTypeKind::Boolean:
114 case ScalarTypeKind::SignedInteger:
117 case ScalarTypeKind::UnsignedInteger:
120 case ScalarTypeKind::Float:
121 switch (
Type->getElementBitwidth()) {
132 llvm_unreachable(
"Unsupported floating point width.");
137 llvm_unreachable(
"Unhandled type.");
139 if (
Type->isVector()) {
146 if (
Type->isConstant())
150 if (
Type->isPointer())
162 bool ConstructedRISCVVBuiltins;
163 bool ConstructedRISCVSiFiveVectorBuiltins;
166 std::vector<RVVIntrinsicDef> IntrinsicList;
168 StringMap<size_t> Intrinsics;
170 StringMap<RVVOverloadIntrinsicDef> OverloadIntrinsics;
175 StringRef OverloadedSuffixStr,
bool IsMask,
187 RISCVIntrinsicManagerImpl(
clang::Sema &S) : S(S), Context(S.Context) {
188 ConstructedRISCVVBuiltins =
false;
189 ConstructedRISCVSiFiveVectorBuiltins =
false;
202void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics(
205 static const std::pair<const char *, RVVRequire> FeatureCheckList[] = {
219 for (
auto &Record : Recs) {
221 if (llvm::any_of(FeatureCheckList, [&](
const auto &Item) {
222 return (
Record.RequiredExtensions & Item.second) == Item.second &&
234 K,
Record.OverloadedSuffixIndex,
Record.OverloadedSuffixSize);
241 const Policy DefaultPolicy;
245 BasicProtoSeq,
false,
247 UnMaskedPolicyScheme, DefaultPolicy,
Record.IsTuple);
252 BasicProtoSeq,
true,
Record.HasMaskedOffOperand,
253 Record.HasVL,
Record.NF, MaskedPolicyScheme, DefaultPolicy,
256 bool UnMaskedHasPolicy = UnMaskedPolicyScheme != PolicyScheme::SchemeNone;
257 bool MaskedHasPolicy = MaskedPolicyScheme != PolicyScheme::SchemeNone;
264 for (
unsigned int TypeRangeMaskShift = 0;
265 TypeRangeMaskShift <= static_cast<unsigned int>(BasicType::MaxOffset);
266 ++TypeRangeMaskShift) {
267 unsigned int BaseTypeI = 1 << TypeRangeMaskShift;
268 BaseType =
static_cast<BasicType>(BaseTypeI);
270 if ((BaseTypeI &
Record.TypeRangeMask) != BaseTypeI)
273 if (BaseType == BasicType::Float16) {
284 for (
int Log2LMUL = -3; Log2LMUL <= 3; Log2LMUL++) {
285 if (!(
Record.Log2LMULMask & (1 << (Log2LMUL + 3))))
288 std::optional<RVVTypes> Types =
289 TypeCache.computeTypes(BaseType, Log2LMUL,
Record.NF, ProtoSeq);
292 if (!Types.has_value())
296 TypeCache, BaseType, Log2LMUL, SuffixProto);
298 TypeCache, BaseType, Log2LMUL, OverloadedSuffixProto);
301 InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
false, *Types,
302 UnMaskedHasPolicy, DefaultPolicy);
305 if (
Record.UnMaskedPolicyScheme != PolicyScheme::SchemeNone) {
306 for (
auto P : SupportedUnMaskedPolicies) {
309 BasicProtoSeq,
false,
311 UnMaskedPolicyScheme,
P,
Record.IsTuple);
312 std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
313 BaseType, Log2LMUL,
Record.NF, PolicyPrototype);
314 InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
315 false, *PolicyTypes, UnMaskedHasPolicy,
322 std::optional<RVVTypes> MaskTypes =
323 TypeCache.computeTypes(BaseType, Log2LMUL,
Record.NF, ProtoMaskSeq);
324 InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
true,
325 *MaskTypes, MaskedHasPolicy, DefaultPolicy);
326 if (
Record.MaskedPolicyScheme == PolicyScheme::SchemeNone)
329 for (
auto P : SupportedMaskedPolicies) {
332 BasicProtoSeq,
true,
Record.HasMaskedOffOperand,
335 std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
336 BaseType, Log2LMUL,
Record.NF, PolicyPrototype);
337 InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
338 true, *PolicyTypes, MaskedHasPolicy,
P);
345void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
348 ConstructedRISCVVBuiltins =
true;
353 !ConstructedRISCVSiFiveVectorBuiltins) {
354 ConstructedRISCVSiFiveVectorBuiltins =
true;
356 IntrinsicKind::SIFIVE_VECTOR);
361void RISCVIntrinsicManagerImpl::InitRVVIntrinsic(
363 StringRef OverloadedSuffixStr,
bool IsMasked,
RVVTypes &Signature,
364 bool HasPolicy,
Policy PolicyAttrs) {
366 std::string Name =
Record.Name;
367 if (!SuffixStr.empty())
368 Name +=
"_" + SuffixStr.str();
371 std::string OverloadedName;
372 if (!
Record.OverloadedName)
373 OverloadedName = StringRef(
Record.Name).split(
"_").first.str();
375 OverloadedName =
Record.OverloadedName;
376 if (!OverloadedSuffixStr.empty())
377 OverloadedName +=
"_" + OverloadedSuffixStr.str();
380 std::string BuiltinName =
"__builtin_rvv_" + std::string(
Record.Name);
383 OverloadedName, PolicyAttrs,
384 Record.HasFRMRoundModeOp);
387 size_t Index = IntrinsicList.size();
388 IntrinsicList.push_back({Name, OverloadedName, BuiltinName, Signature});
391 Intrinsics.insert({Name, Index});
394 RVVOverloadIntrinsicDef &OverloadIntrinsicDef =
395 OverloadIntrinsics[OverloadedName];
398 OverloadIntrinsicDef.Indexes.push_back(Index);
401void RISCVIntrinsicManagerImpl::CreateRVVIntrinsicDecl(
LookupResult &LR,
407 RVVIntrinsicDef &IDef = IntrinsicList[Index];
409 size_t SigLength = Sigs.size();
416 for (
size_t i = 1; i < SigLength; ++i)
429 Context,
Parent, Loc, Loc, II, BuiltinFuncType,
nullptr,
436 const auto *FP = cast<FunctionProtoType>(BuiltinFuncType);
438 for (
unsigned IParm = 0, E = FP->getNumParams(); IParm != E; ++IParm) {
441 FP->getParamType(IParm),
nullptr,
SC_None,
nullptr);
443 ParmList.push_back(Parm);
445 RVVIntrinsicDecl->setParams(ParmList);
449 RVVIntrinsicDecl->
addAttr(OverloadableAttr::CreateImplicit(Context));
454 BuiltinAliasAttr::CreateImplicit(S.
Context, &IntrinsicII));
460bool RISCVIntrinsicManagerImpl::CreateIntrinsicIfFound(
LookupResult &LR,
463 StringRef Name = II->
getName();
466 auto OvIItr = OverloadIntrinsics.find(Name);
467 if (OvIItr != OverloadIntrinsics.end()) {
468 const RVVOverloadIntrinsicDef &OvIntrinsicDef = OvIItr->second;
469 for (
auto Index : OvIntrinsicDef.Indexes)
470 CreateRVVIntrinsicDecl(LR, II, PP, Index,
479 auto Itr = Intrinsics.find(Name);
480 if (Itr != Intrinsics.end()) {
481 CreateRVVIntrinsicDecl(LR, II, PP, Itr->second,
491std::unique_ptr<clang::sema::RISCVIntrinsicManager>
493 return std::make_unique<RISCVIntrinsicManagerImpl>(S);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
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, 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.
std::vector< RVVTypePtr > RVVTypes
std::unique_ptr< sema::RISCVIntrinsicManager > CreateRISCVIntrinsicManager(Sema &S)
YAML serialization mapping.
Extra information about a function prototype.