3333#include " llvm/IR/IntrinsicsXCore.h"
3434#include " llvm/IR/Module.h"
3535#include " llvm/IR/Type.h"
36+ #include " llvm/Support/IntrinsicID.h"
3637
3738using namespace llvm ;
39+ using namespace Intrinsic ;
40+
41+ // / Table of per-target intrinsic name tables.
42+ #define GET_INTRINSIC_TARGET_DATA
43+ #include " llvm/IR/IntrinsicImpl.inc"
44+ #undef GET_INTRINSIC_TARGET_DATA
45+ size_t constexpr NumTargets = sizeof (TargetInfos) / sizeof (TargetInfos[0 ]);
46+
47+ // Returns true if the given intrinsic ID is valid, that is, its value is one
48+ // of the valid enum values defined for this intrinsic (including
49+ // not_intrinsic).
50+ bool Intrinsic::IsIntrinsicIDValid (ID ID) {
51+ if (ID == Intrinsic::not_intrinsic)
52+ return true ;
53+ auto Decoded = DecodeIntrinsicIDNoFail (ID);
54+ if (!Decoded)
55+ return false ;
56+ unsigned TargetIdx = Decoded->first ;
57+ unsigned IntrinsicIdx = Decoded->second ;
58+ return TargetIdx < NumTargets && IntrinsicIdx < TargetInfos[TargetIdx].Count ;
59+ }
60+
61+ // Returns linear index of ID if its valid, else returns 0.
62+ inline unsigned getLinearIndex (Intrinsic::ID ID) {
63+ auto Decoded = DecodeIntrinsicIDNoFail (ID);
64+ if (!Decoded)
65+ return 0 ;
66+ unsigned TargetIdx = Decoded->first ;
67+ unsigned IntrinsicIdx = Decoded->second ;
68+ return TargetInfos[TargetIdx].FirstLinearIndex + IntrinsicIdx;
69+ }
70+
71+ ID Intrinsic::GetNextValidIntrinsicID (Intrinsic::ID ID) {
72+ if (ID == Intrinsic::not_intrinsic)
73+ return EncodeIntrinsicID (0 , 0 );
74+ if (ID == Intrinsic::last_valid_intrinsic_id)
75+ return Intrinsic::end_id;
76+ if (ID == Intrinsic::end_id)
77+ llvm_unreachable (" Cannot find the next valid intrisnic" );
78+ auto [TargetIndex, IntrinsicIndex] = DecodeIntrinsicID (ID);
79+ if (IntrinsicIndex + 1 < TargetInfos[TargetIndex].Count )
80+ return EncodeIntrinsicID (TargetIndex, IntrinsicIndex + 1 );
81+ if (TargetIndex + 1 < NumTargets)
82+ return EncodeIntrinsicID (TargetIndex + 1 , 0 );
83+ llvm_unreachable (" Cannot find the next valid intrisnic" );
84+ }
3885
3986// / Table of string intrinsic names indexed by enum value.
4087static constexpr const char *const IntrinsicNameTable[] = {
@@ -45,12 +92,12 @@ static constexpr const char *const IntrinsicNameTable[] = {
4592};
4693
4794StringRef Intrinsic::getBaseName (ID id) {
48- assert (id < num_intrinsics && " Invalid intrinsic ID!" );
49- return IntrinsicNameTable[id ];
95+ assert (IsIntrinsicIDValid (id) && " Invalid intrinsic ID!" );
96+ return ArrayRef ( IntrinsicNameTable)[ getLinearIndex (id) ];
5097}
5198
5299StringRef Intrinsic::getName (ID id) {
53- assert (id < num_intrinsics && " Invalid intrinsic ID!" );
100+ assert (IsIntrinsicIDValid (id) && " Invalid intrinsic ID!" );
54101 assert (!Intrinsic::isOverloaded (id) &&
55102 " This version of getName does not support overloading" );
56103 return getBaseName (id);
@@ -157,8 +204,7 @@ static std::string getMangledTypeStr(Type *Ty, bool &HasUnnamedType) {
157204static std::string getIntrinsicNameImpl (Intrinsic::ID Id, ArrayRef<Type *> Tys,
158205 Module *M, FunctionType *FT,
159206 bool EarlyModuleCheck) {
160-
161- assert (Id < Intrinsic::num_intrinsics && " Invalid intrinsic ID!" );
207+ assert (IsIntrinsicIDValid (Id) && " Invalid intrinsic ID!" );
162208 assert ((Tys.empty () || Intrinsic::isOverloaded (Id)) &&
163209 " This version of getName is for overloaded intrinsics only" );
164210 (void )EarlyModuleCheck;
@@ -450,11 +496,15 @@ DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
450496#undef GET_INTRINSIC_GENERATOR_GLOBAL
451497
452498void Intrinsic::getIntrinsicInfoTableEntries (
453- ID id , SmallVectorImpl<IITDescriptor> &T) {
499+ ID IntrinsicID , SmallVectorImpl<IITDescriptor> &T) {
454500 static_assert (sizeof (IIT_Table[0 ]) == 2 ,
455501 " Expect 16-bit entries in IIT_Table" );
502+ assert (IsIntrinsicIDValid (IntrinsicID));
503+ unsigned Idx = getLinearIndex (IntrinsicID);
504+ if (Idx == 0 )
505+ return ;
456506 // Check to see if the intrinsic's type was expressible by the table.
457- uint16_t TableVal = IIT_Table[id - 1 ];
507+ uint16_t TableVal = IIT_Table[Idx - 1 ];
458508
459509 // Decode the TableVal into an array of IITValues.
460510 SmallVector<unsigned char > IITValues;
@@ -609,19 +659,20 @@ FunctionType *Intrinsic::getType(LLVMContext &Context, ID id,
609659 return FunctionType::get (ResultTy, ArgTys, false );
610660}
611661
612- bool Intrinsic::isOverloaded (ID id) {
662+ // Check if an intrinsic is overloaded or not using its linear index.
663+ static bool isOverloadedUsingLinearIndex (unsigned Idx) {
613664#define GET_INTRINSIC_OVERLOAD_TABLE
614665#include " llvm/IR/IntrinsicImpl.inc"
615666#undef GET_INTRINSIC_OVERLOAD_TABLE
616667}
617668
618- // / Table of per-target intrinsic name tables.
619- # define GET_INTRINSIC_TARGET_DATA
620- # include " llvm/IR/IntrinsicImpl.inc "
621- # undef GET_INTRINSIC_TARGET_DATA
669+ bool Intrinsic::isOverloaded (ID id) {
670+ assert ( IsIntrinsicIDValid (id));
671+ return isOverloadedUsingLinearIndex ( getLinearIndex (id));
672+ }
622673
623674bool Intrinsic::isTargetIntrinsic (Intrinsic::ID IID) {
624- return IID > TargetInfos[ 0 ]. Count ;
675+ return IID != Intrinsic::not_intrinsic && DecodeIntrinsicID (IID). first != 0 ;
625676}
626677
627678int llvm::Intrinsic::lookupLLVMIntrinsicByName (ArrayRef<const char *> NameTable,
@@ -683,7 +734,29 @@ findTargetSubtable(StringRef Name) {
683734 // We've either found the target or just fall back to the generic set, which
684735 // is always first.
685736 const auto &TI = It != Targets.end () && It->Name == Target ? *It : Targets[0 ];
686- return {ArrayRef (&IntrinsicNameTable[1 ] + TI.Offset , TI.Count ), TI.Name };
737+ unsigned LinearIndex = TI.FirstLinearIndex ;
738+ return {ArrayRef (IntrinsicNameTable + LinearIndex, TI.Count ), TI.Name };
739+ }
740+
741+ static Intrinsic::ID getIntrinsicIDFromIndex (unsigned Idx) {
742+ if (Idx == 0 )
743+ return Intrinsic::not_intrinsic;
744+
745+ auto It =
746+ partition_point (TargetInfos, [Idx](const IntrinsicTargetInfo &Info) {
747+ return Info.FirstLinearIndex + Info.Count < Idx;
748+ });
749+ // Idx, if present, will be in the entry at It or It + 1.
750+ if (It == std::end (TargetInfos))
751+ return Intrinsic::not_intrinsic;
752+ unsigned TargetIndex = std::distance (std::begin (TargetInfos), It);
753+ if (It->FirstLinearIndex <= Idx && Idx < It->FirstLinearIndex + It->Count )
754+ return EncodeIntrinsicID (TargetIndex, Idx - It->FirstLinearIndex );
755+ ++It;
756+ ++TargetIndex;
757+ if (It->FirstLinearIndex <= Idx && Idx < It->FirstLinearIndex + It->Count )
758+ return EncodeIntrinsicID (TargetIndex, Idx - It->FirstLinearIndex );
759+ return Intrinsic::not_intrinsic;
687760}
688761
689762// / This does the actual lookup of an intrinsic ID which matches the given
@@ -693,19 +766,19 @@ Intrinsic::ID Intrinsic::lookupIntrinsicID(StringRef Name) {
693766 int Idx = Intrinsic::lookupLLVMIntrinsicByName (NameTable, Name, Target);
694767 if (Idx == -1 )
695768 return Intrinsic::not_intrinsic;
696-
697- // Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have
698- // an index into a sub-table.
769+ const auto MatchSize = strlen (NameTable[Idx]);
770+ // Adjust the index from sub-table index to index into the global table.
699771 int Adjust = NameTable.data () - IntrinsicNameTable;
700- Intrinsic::ID ID = static_cast <Intrinsic::ID>( Idx + Adjust) ;
772+ Idx += Adjust;
701773
702774 // If the intrinsic is not overloaded, require an exact match. If it is
703775 // overloaded, require either exact or prefix match.
704- const auto MatchSize = strlen (NameTable[Idx]);
705776 assert (Name.size () >= MatchSize && " Expected either exact or prefix match" );
706777 bool IsExactMatch = Name.size () == MatchSize;
707- return IsExactMatch || Intrinsic::isOverloaded (ID) ? ID
708- : Intrinsic::not_intrinsic;
778+ Intrinsic::ID r = IsExactMatch || isOverloadedUsingLinearIndex (Idx)
779+ ? getIntrinsicIDFromIndex (Idx)
780+ : Intrinsic::not_intrinsic;
781+ return r;
709782}
710783
711784// / This defines the "Intrinsic::getAttributes(ID id)" method.
@@ -718,10 +791,11 @@ Function *Intrinsic::getOrInsertDeclaration(Module *M, ID id,
718791 // There can never be multiple globals with the same name of different types,
719792 // because intrinsics must be a specific type.
720793 auto *FT = getType (M->getContext (), id, Tys);
721- return cast<Function>(
794+ Function *F = cast<Function>(
722795 M->getOrInsertFunction (
723796 Tys.empty () ? getName (id) : getName (id, Tys, M, FT), FT)
724797 .getCallee ());
798+ return F;
725799}
726800
727801Function *Intrinsic::getDeclarationIfExists (const Module *M, ID id) {
@@ -1043,8 +1117,9 @@ bool Intrinsic::matchIntrinsicVarArg(
10431117
10441118bool Intrinsic::getIntrinsicSignature (Intrinsic::ID ID, FunctionType *FT,
10451119 SmallVectorImpl<Type *> &ArgTys) {
1046- if (!ID )
1120+ if (ID == Intrinsic::not_intrinsic )
10471121 return false ;
1122+ assert (IsIntrinsicIDValid (ID));
10481123
10491124 SmallVector<Intrinsic::IITDescriptor, 8 > Table;
10501125 getIntrinsicInfoTableEntries (ID, Table);
0 commit comments