LLVM: lib/Transforms/IPO/LowerTypeTests.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
78#include
79#include
80#include
81#include
82#include
83#include <system_error>
84#include
85#include
86
87using namespace llvm;
89
90#define DEBUG_TYPE "lowertypetests"
91
92STATISTIC(ByteArraySizeBits, "Byte array size in bits");
93STATISTIC(ByteArraySizeBytes, "Byte array size in bytes");
94STATISTIC(NumByteArraysCreated, "Number of byte arrays created");
95STATISTIC(NumTypeTestCallsLowered, "Number of type test calls lowered");
96STATISTIC(NumTypeIdDisjointSets, "Number of disjoint sets of type identifiers");
97
99 "lowertypetests-avoid-reuse",
100 cl::desc("Try to avoid reuse of byte array addresses using aliases"),
102
104 "lowertypetests-summary-action",
105 cl::desc("What to do with the summary when running this pass"),
108 "Import typeid resolutions from summary and globals"),
110 "Export typeid resolutions to summary and globals")),
112
114 "lowertypetests-read-summary",
115 cl::desc("Read summary from given YAML file before running pass"),
117
119 "lowertypetests-write-summary",
120 cl::desc("Write summary to given YAML file after running pass"),
122
125 cl::desc("Simply drop type test sequences"),
127 "Do not drop any type tests"),
128 clEnumValN(DropTestKind::Assume, "assume",
129 "Drop type test assume sequences"),
131 "Drop all type test sequences")),
133
136 return false;
137
139 return false;
140
142 if (BitOffset >= BitSize)
143 return false;
144
145 return Bits.count(BitSize - 1 - BitOffset);
146}
147
149 OS << "offset " << ByteOffset << " size " << BitSize << " align "
151
153 OS << " all-ones\n";
154 return;
155 }
156
157 OS << " { ";
159 OS << B << ' ';
160 OS << "}\n";
161}
162
166
167
168
169
170
171
176 }
177
180
182 if (Mask != 0)
184
185
186
190
191
192
193
195 }
196
197 return BSI;
198}
199
201
203 std::vector<uint64_t> &Fragment = Fragments.back();
205
206 for (auto ObjIndex : F) {
208 if (OldFragmentIndex == 0) {
209
210
211 Fragment.push_back(ObjIndex);
212 } else {
213
214
215
216
217
218 std::vector<uint64_t> &OldFragment = Fragments[OldFragmentIndex];
220 OldFragment.clear();
221 }
222 }
223
224
225 for (uint64_t ObjIndex : Fragment)
227}
228
232
233 unsigned Bit = 0;
236 Bit = I;
237
238 AllocByteOffset = BitAllocs[Bit];
239
240
241 unsigned ReqSize = AllocByteOffset + BitSize;
243 if (Bytes.size() < ReqSize)
244 Bytes.resize(ReqSize);
245
246
247 AllocMask = 1 << Bit;
249 Bytes[AllocByteOffset + B] |= AllocMask;
250}
251
253 if (F->isDeclarationForLinker())
254 return false;
256 F->getParent()->getModuleFlag("CFI Canonical Jump Tables"));
257 if (!CI || !CI->isZero())
258 return true;
259 return F->hasFnAttribute("cfi-canonical-jump-table");
260}
261
262namespace {
263
264struct ByteArrayInfo {
265 std::set<uint64_t> Bits;
269 uint8_t *MaskPtr = nullptr;
270};
271
272
273
274
275
276
277class GlobalTypeMember final : TrailingObjects<GlobalTypeMember, MDNode *> {
279
281 size_t NTypes;
282
283
284
285
286
287
288 bool IsJumpTableCanonical;
289
290
291
292 bool IsExported;
293
294public:
296 bool IsJumpTableCanonical, bool IsExported,
298 auto *GTM = static_cast<GlobalTypeMember *>(Alloc.Allocate(
299 totalSizeToAlloc<MDNode *>(Types.size()), alignof(GlobalTypeMember)));
300 GTM->GO = GO;
301 GTM->NTypes = Types.size();
302 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
303 GTM->IsExported = IsExported;
304 llvm::copy(Types, GTM->getTrailingObjects());
305 return GTM;
306 }
307
308 GlobalObject *getGlobal() const {
309 return GO;
310 }
311
313 return IsJumpTableCanonical;
314 }
315
316 bool isExported() const {
317 return IsExported;
318 }
319
320 ArrayRef<MDNode *> types() const { return getTrailingObjects(NTypes); }
321};
322
323struct ICallBranchFunnel final
324 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
327 unsigned UniqueId) {
328 auto *Call = static_cast<ICallBranchFunnel *>(
329 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.size()),
330 alignof(ICallBranchFunnel)));
331 Call->CI = CI;
332 Call->UniqueId = UniqueId;
333 Call->NTargets = Targets.size();
336 }
337
338 CallInst *CI;
340 return getTrailingObjects(NTargets);
341 }
342
343 unsigned UniqueId;
344
345private:
346 size_t NTargets;
347};
348
349struct ScopedSaveAliaseesAndUsed {
352 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
353 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
354
355
356
357
358 void collectAndEraseUsedFunctions(Module &M,
359 SmallVectorImpl<GlobalValue *> &Vec,
360 bool CompilerUsed) {
362 if (!GV)
363 return;
364
365
366
367 GV->eraseFromParent();
368 auto NonFuncBegin =
369 std::stable_partition(Vec.begin(), Vec.end(), [](GlobalValue *GV) {
370 return isa(GV);
371 });
372 if (CompilerUsed)
374 else
377 }
378
379 ScopedSaveAliaseesAndUsed(Module &M) : M(M) {
380
381
382
383
384
385
386
387
388
389
390
391
392 collectAndEraseUsedFunctions(M, Used, false);
393 collectAndEraseUsedFunctions(M, CompilerUsed, true);
394
395 for (auto &GA : M.aliases()) {
396
397
399 FunctionAliases.push_back({&GA, F});
400 }
401
402 for (auto &GI : M.ifuncs())
404 ResolverIFuncs.push_back({&GI, F});
405 }
406
407 ~ScopedSaveAliaseesAndUsed() {
410
411 for (auto P : FunctionAliases)
412 P.first->setAliasee(P.second);
413
414 for (auto P : ResolverIFuncs) {
415
416
417
418 P.first->setResolver(P.second);
419 }
420 }
421};
422
423class LowerTypeTestsModule {
425
426 ModuleSummaryIndex *ExportSummary;
427 const ModuleSummaryIndex *ImportSummary;
428
429
431
435
436
437
438
439 bool CanUseArmJumpTable = false, CanUseThumbBWJumpTable = false;
440
441
442 int HasBranchTargetEnforcement = -1;
443
444 IntegerType *Int1Ty = Type::getInt1Ty(M.getContext());
445 IntegerType *Int8Ty = Type::getInt8Ty(M.getContext());
446 PointerType *PtrTy = PointerType::getUnqual(M.getContext());
447 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(M.getContext()), 0);
448 IntegerType *Int32Ty = Type::getInt32Ty(M.getContext());
449 IntegerType *Int64Ty = Type::getInt64Ty(M.getContext());
450 IntegerType *IntPtrTy = M.getDataLayout().getIntPtrType(M.getContext(), 0);
451
452
453 uint64_t IndirectIndex = 1;
454
455
456
457
458 struct TypeIdUserInfo {
459 std::vector<CallInst *> CallSites;
460 bool IsExported = false;
461 };
462 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
463
464
465
466
467
468 struct TypeIdLowering {
470
471
472
474
475
476
478
479
480
482
483
485
486
488
489
491 };
492
493 std::vector ByteArrayInfos;
494
495 Function *WeakInitializerFn = nullptr;
496
497 GlobalVariable *GlobalAnnotation;
498 DenseSet<Value *> FunctionAnnotations;
499
500 bool shouldExportConstantsAsAbsoluteSymbols();
501 uint8_t *exportTypeId(StringRef TypeId, const TypeIdLowering &TIL);
502 TypeIdLowering importTypeId(StringRef TypeId);
503 void importTypeTest(CallInst *CI);
505
506 ByteArrayInfo *createByteArray(const BitSetInfo &BSI);
507 void allocateByteArrays();
508 Value *createBitSetTest(IRBuilder<> &B, const TypeIdLowering &TIL,
509 Value *BitOffset);
510 void lowerTypeTestCalls(
512 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
513 Value *lowerTypeTestCall(Metadata *TypeId, CallInst *CI,
514 const TypeIdLowering &TIL);
515
520 bool hasBranchTargetEnforcement();
521 unsigned getJumpTableEntrySize(Triple::ArchType JumpTableArch);
522 InlineAsm *createJumpTableEntryAsm(Triple::ArchType JumpTableArch);
523 void verifyTypeMDNode(GlobalObject *GO, MDNode *Type);
530 void
534
535 void replaceWeakDeclarationWithJumpTablePtr(Function *F, Constant *JT,
536 bool IsJumpTableCanonical);
537 void moveInitializerToModuleConstructor(GlobalVariable *GV);
538 void findGlobalVariableUsersOf(Constant *C,
539 SmallSetVector<GlobalVariable *, 8> &Out);
540
543
544
545
546
547
548
549 void replaceCfiUses(Function *Old, Value *New, bool IsJumpTableCanonical);
550
551
552
553 void replaceDirectCalls(Value *Old, Value *New);
554
555 bool isFunctionAnnotation(Value *V) const {
556 return FunctionAnnotations.contains(V);
557 }
558
559 void maybeReplaceComdat(Function *F, StringRef OriginalName);
560
561public:
563 ModuleSummaryIndex *ExportSummary,
564 const ModuleSummaryIndex *ImportSummary,
566
567 bool lower();
568
569
570
572};
573}
574
575
581
582
583
585 Value *BitOffset) {
587 unsigned BitWidth = BitsType->getBitWidth();
588
589 BitOffset = B.CreateZExtOrTrunc(BitOffset, BitsType);
590 Value *BitIndex =
591 B.CreateAnd(BitOffset, ConstantInt::get(BitsType, BitWidth - 1));
592 Value *BitMask = B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
593 Value *MaskedBits = B.CreateAnd(Bits, BitMask);
594 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
595}
596
597ByteArrayInfo *LowerTypeTestsModule::createByteArray(const BitSetInfo &BSI) {
598
599
600
601 auto ByteArrayGlobal = new GlobalVariable(
603 auto MaskGlobal = new GlobalVariable(M, Int8Ty, true,
605
606 ByteArrayInfos.emplace_back();
607 ByteArrayInfo *BAI = &ByteArrayInfos.back();
608
609 BAI->Bits = BSI.Bits;
610 BAI->BitSize = BSI.BitSize;
611 BAI->ByteArray = ByteArrayGlobal;
612 BAI->MaskGlobal = MaskGlobal;
613 return BAI;
614}
615
616void LowerTypeTestsModule::allocateByteArrays() {
618 [](const ByteArrayInfo &BAI1, const ByteArrayInfo &BAI2) {
619 return BAI1.BitSize > BAI2.BitSize;
620 });
621
622 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
623
625 for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {
626 ByteArrayInfo *BAI = &ByteArrayInfos[I];
627
628 uint8_t Mask;
629 BAB.allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[I], Mask);
630
634 if (BAI->MaskPtr)
635 *BAI->MaskPtr = Mask;
636 }
637
640 new GlobalVariable(M, ByteArrayConst->getType(), true,
642
643 for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {
644 ByteArrayInfo *BAI = &ByteArrayInfos[I];
645
646 Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0),
647 ConstantInt::get(IntPtrTy, ByteArrayOffsets[I])};
649 ByteArrayConst->getType(), ByteArray, Idxs);
650
651
652
653
658 }
659
663 ByteArraySizeBytes = BAB.Bytes.size();
664}
665
666
667
669 const TypeIdLowering &TIL,
670 Value *BitOffset) {
672
673
675 } else {
678
679
680
681
683 "bits_use", ByteArray, &M);
684 }
685
686 Value *ByteAddr = B.CreateGEP(Int8Ty, ByteArray, BitOffset);
687 Value *Byte = B.CreateLoad(Int8Ty, ByteAddr);
688
689 Value *ByteAndMask =
691 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
692 }
693}
694
699 GV->getMetadata(LLVMContext::MD_type, Types);
701 if (Type->getOperand(1) != TypeId)
702 continue;
706 ->getZExtValue();
707 if (COffset == Offset)
708 return true;
709 }
710 return false;
711 }
712
714 APInt APOffset(DL.getIndexSizeInBits(0), 0);
715 bool Result = GEP->accumulateConstantOffset(DL, APOffset);
716 if (!Result)
717 return false;
720 }
721
723 if (Op->getOpcode() == Instruction::BitCast)
725
726 if (Op->getOpcode() == Instruction::Select)
729 }
730
731 return false;
732}
733
734
735
736Value *LowerTypeTestsModule::lowerTypeTestCall(Metadata *TypeId, CallInst *CI,
737 const TypeIdLowering &TIL) {
738
740 return nullptr;
743
745 const DataLayout &DL = M.getDataLayout();
748
750
752
753 Value *PtrAsInt = B.CreatePtrToInt(Ptr, IntPtrTy);
754
755 Constant *OffsetedGlobalAsInt =
758 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
759
760
761
762
763
764 Value *PtrOffset = B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
765
766
767
768
769
770
771
772
773
774 Value *BitOffset = B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,
775 {PtrOffset, PtrOffset, TIL.AlignLog2});
776
777 Value *OffsetInRange = B.CreateICmpULE(BitOffset, TIL.SizeM1);
778
779
781 return OffsetInRange;
782
783
784
785
786
794 Br->getMetadata(LLVMContext::MD_prof));
796
797
798 for (auto &Phi : Else->phis())
799 Phi.addIncoming(Phi.getIncomingValueForBlock(Then), InitialBB);
800
802 return createBitSetTest(ThenB, TIL, BitOffset);
803 }
804
806
807
808
809 Value *Bit = createBitSetTest(ThenB, TIL, BitOffset);
810
811
812
813
814 B.SetInsertPoint(CI);
815 PHINode *P = B.CreatePHI(Int1Ty, 2);
816 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
817 P->addIncoming(Bit, ThenB.GetInsertBlock());
818 return P;
819}
820
821
822
823void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
825
826
827
828
829
830 std::vector<Constant *> GlobalInits;
831 const DataLayout &DL = M.getDataLayout();
832 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
834 uint64_t CurOffset = 0;
835 uint64_t DesiredPadding = 0;
836 for (GlobalTypeMember *G : Globals) {
838 Align Alignment =
839 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
840 MaxAlign = std::max(MaxAlign, Alignment);
841 uint64_t GVOffset = alignTo(CurOffset + DesiredPadding, Alignment);
842 GlobalLayout[G] = GVOffset;
843 if (GVOffset != 0) {
844 uint64_t Padding = GVOffset - CurOffset;
845 GlobalInits.push_back(
847 }
848
849 GlobalInits.push_back(GV->getInitializer());
850 uint64_t InitSize = DL.getTypeAllocSize(GV->getValueType());
851 CurOffset = GVOffset + InitSize;
852
853
854 DesiredPadding = NextPowerOf2(InitSize - 1) - InitSize;
855
856
857
858
859
860 if (DesiredPadding > 32)
861 DesiredPadding = alignTo(InitSize, 32) - InitSize;
862 }
863
865 auto *CombinedGlobal =
866 new GlobalVariable(M, NewInit->getType(), true,
868 CombinedGlobal->setAlignment(MaxAlign);
869
871 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
872
873
874
875
876 for (unsigned I = 0; I != Globals.size(); ++I) {
878
879
880 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
881 ConstantInt::get(Int32Ty, I * 2)};
883 NewInit->getType(), CombinedGlobal, CombinedGlobalIdxs);
885 GlobalAlias *GAlias =
887 "", CombinedGlobalElemPtr, &M);
892 }
893}
894
895bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
898}
899
900
901
902
903
904
905
906
907
908uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
909 const TypeIdLowering &TIL) {
910 TypeTestResolution &TTRes =
912 TTRes.TheKind = TIL.TheKind;
913
914 auto ExportGlobal = [&](StringRef Name, Constant *C) {
915 GlobalAlias *GA =
917 "__typeid_" + TypeId + "_" + Name, C, &M);
919 };
920
921 auto ExportConstant = [&](StringRef Name, uint64_t &Storage, Constant *C) {
922 if (shouldExportConstantsAsAbsoluteSymbols())
924 else
926 };
927
929 ExportGlobal("global_addr", TIL.OffsetedGlobal);
930
934 ExportConstant("align", TTRes.AlignLog2, TIL.AlignLog2);
935 ExportConstant("size_m1", TTRes.SizeM1, TIL.SizeM1);
936
937 uint64_t BitSize = cast(TIL.SizeM1)->getZExtValue() + 1;
940 else
942 }
943
945 ExportGlobal("byte_array", TIL.TheByteArray);
946 if (shouldExportConstantsAsAbsoluteSymbols())
947 ExportGlobal("bit_mask", TIL.BitMask);
948 else
950 }
951
953 ExportConstant("inline_bits", TTRes.InlineBits, TIL.InlineBits);
954
955 return nullptr;
956}
957
958LowerTypeTestsModule::TypeIdLowering
959LowerTypeTestsModule::importTypeId(StringRef TypeId) {
960 const TypeIdSummary *TidSummary = ImportSummary->getTypeIdSummary(TypeId);
961 if (!TidSummary)
962 return {};
963 const TypeTestResolution &TTRes = TidSummary->TTRes;
964
965 TypeIdLowering TIL;
966 TIL.TheKind = TTRes.TheKind;
967
968 auto ImportGlobal = [&](StringRef Name) {
969
970
971 GlobalVariable *GV = M.getOrInsertGlobal(
972 ("__typeid_" + TypeId + "_" + Name).str(), Int8Arr0Ty);
974 return GV;
975 };
976
977 auto ImportConstant = [&](StringRef Name, uint64_t Const, unsigned AbsWidth,
979 if (!shouldExportConstantsAsAbsoluteSymbols()) {
981 ConstantInt::get(isa(Ty) ? Ty : Int64Ty, Const);
984 return C;
985 }
986
987 Constant *C = ImportGlobal(Name);
991 if (GV->getMetadata(LLVMContext::MD_absolute_symbol))
992 return C;
993
994 auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {
997 GV->setMetadata(LLVMContext::MD_absolute_symbol,
999 };
1000 if (AbsWidth == IntPtrTy->getBitWidth())
1001 SetAbsRange(~0ull, ~0ull);
1002 else
1003 SetAbsRange(0, 1ull << AbsWidth);
1004 return C;
1005 };
1006
1008 auto *GV = ImportGlobal("global_addr");
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1021 TIL.OffsetedGlobal = GV;
1022 }
1023
1027 TIL.AlignLog2 = ImportConstant("align", TTRes.AlignLog2, 8, IntPtrTy);
1028 TIL.SizeM1 =
1030 }
1031
1033 TIL.TheByteArray = ImportGlobal("byte_array");
1034 TIL.BitMask = ImportConstant("bit_mask", TTRes.BitMask, 8, PtrTy);
1035 }
1036
1038 TIL.InlineBits = ImportConstant(
1041
1042 return TIL;
1043}
1044
1045void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1047 if (!TypeIdMDVal)
1048 report_fatal_error("Second argument of llvm.type.test must be metadata");
1049
1051
1052
1053
1054 if (!TypeIdStr)
1055 return;
1056
1057 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1058 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1059 if (Lowered) {
1062 }
1063}
1064
1065void LowerTypeTestsModule::maybeReplaceComdat(Function *F,
1066 StringRef OriginalName) {
1067
1068
1069
1070
1071 if (F->hasComdat() && ObjectFormat == Triple::COFF &&
1072 F->getComdat()->getName() == OriginalName) {
1073 Comdat *OldComdat = F->getComdat();
1074 Comdat *NewComdat = M.getOrInsertComdat(F->getName());
1075 for (GlobalObject &GO : M.global_objects()) {
1076 if (GO.getComdat() == OldComdat)
1078 }
1079 }
1080}
1081
1082
1083
1084void LowerTypeTestsModule::importFunction(Function *F,
1086 assert(F->getType()->getAddressSpace() == 0);
1087
1089 std::string Name = std::string(F->getName());
1090
1092
1093
1094 if (F->isDSOLocal()) {
1097 F->getAddressSpace(),
1098 Name + ".cfi", &M);
1100 replaceDirectCalls(F, RealF);
1101 }
1102 return;
1103 }
1104
1107
1108
1110 F->getAddressSpace(), Name + ".cfi_jt", &M);
1112 } else {
1113 F->setName(Name + ".cfi");
1114 maybeReplaceComdat(F, Name);
1116 F->getAddressSpace(), Name, &M);
1119
1120
1121
1122
1123 for (auto &U : F->uses()) {
1125 std::string AliasName = A->getName().str() + ".cfi";
1128 F->getAddressSpace(), "", &M);
1130 A->replaceAllUsesWith(AliasDecl);
1131 A->setName(AliasName);
1132 }
1133 }
1134 }
1135
1136 if (F->hasExternalWeakLinkage())
1138 else
1140
1141
1142
1143 F->setVisibility(Visibility);
1144}
1145
1146static auto
1150
1151 for (Metadata *TypeId : TypeIds)
1152 OffsetsByTypeID[TypeId];
1153 for (const auto &[Mem, MemOff] : GlobalLayout) {
1155 auto It = OffsetsByTypeID.find(Type->getOperand(1));
1156 if (It == OffsetsByTypeID.end())
1157 continue;
1161 ->getZExtValue();
1162 It->second.push_back(MemOff + Offset);
1163 }
1164 }
1165
1168 for (Metadata *TypeId : TypeIds) {
1172 dbgs() << MDS->getString() << ": ";
1173 else
1174 dbgs() << ": ";
1175 BitSets.back().second.print(dbgs());
1176 });
1177 }
1178
1179 return BitSets;
1180}
1181
1182void LowerTypeTestsModule::lowerTypeTestCalls(
1184 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1185
1186 for (const auto &[TypeId, BSI] : buildBitSets(TypeIds, GlobalLayout)) {
1187 ByteArrayInfo *BAI = nullptr;
1188 TypeIdLowering TIL;
1189
1190 uint64_t GlobalOffset =
1193 Int8Ty, CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
1194 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.AlignLog2);
1195 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.BitSize - 1);
1198 : TypeTestResolution::AllOnes;
1201 uint64_t InlineBits = 0;
1202 for (auto Bit : BSI.Bits)
1203 InlineBits |= uint64_t(1) << Bit;
1204 if (InlineBits == 0)
1206 else
1207 TIL.InlineBits = ConstantInt::get(
1208 (BSI.BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1209 } else {
1211 ++NumByteArraysCreated;
1212 BAI = createByteArray(BSI);
1213 TIL.TheByteArray = BAI->ByteArray;
1214 TIL.BitMask = BAI->MaskGlobal;
1215 }
1216
1217 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1218
1219 if (TIUI.IsExported) {
1220 uint8_t *MaskPtr = exportTypeId(cast(TypeId)->getString(), TIL);
1221 if (BAI)
1222 BAI->MaskPtr = MaskPtr;
1223 }
1224
1225
1226 for (CallInst *CI : TIUI.CallSites) {
1227 ++NumTypeTestCallsLowered;
1228 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1229 if (Lowered) {
1232 }
1233 }
1234 }
1235}
1236
1237void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) {
1238 if (Type->getNumOperands() != 2)
1239 report_fatal_error("All operands of type metadata must have 2 elements");
1240
1245 "A member of a type identifier may not have an explicit section");
1246
1247
1248
1249
1250
1252 if (!OffsetConstMD)
1255 if (!OffsetInt)
1257}
1258
1266
1267bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1268 if (HasBranchTargetEnforcement == -1) {
1269
1270
1272 M.getModuleFlag("branch-target-enforcement")))
1273 HasBranchTargetEnforcement = !BTE->isZero();
1274 else
1275 HasBranchTargetEnforcement = 0;
1276 }
1277 return HasBranchTargetEnforcement;
1278}
1279
1280unsigned
1281LowerTypeTestsModule::getJumpTableEntrySize(Triple::ArchType JumpTableArch) {
1282 switch (JumpTableArch) {
1286 M.getModuleFlag("cf-protection-branch")))
1287 if (MD->getZExtValue())
1293 if (CanUseThumbBWJumpTable) {
1294 if (hasBranchTargetEnforcement())
1297 } else {
1299 }
1301 if (hasBranchTargetEnforcement())
1309 default:
1311 }
1312}
1313
1314
1315
1316
1317InlineAsm *
1318LowerTypeTestsModule::createJumpTableEntryAsm(Triple::ArchType JumpTableArch) {
1319 std::string Asm;
1320 raw_string_ostream AsmOS(Asm);
1321
1323 bool Endbr = false;
1325 M.getModuleFlag("cf-protection-branch")))
1326 Endbr = !MD->isZero();
1327 if (Endbr)
1328 AsmOS << (JumpTableArch == Triple::x86 ? "endbr32\n" : "endbr64\n");
1329 AsmOS << "jmp ${0:c}@plt\n";
1330 if (Endbr)
1331 AsmOS << ".balign 16, 0xcc\n";
1332 else
1333 AsmOS << "int3\nint3\nint3\n";
1334 } else if (JumpTableArch == Triple::arm) {
1335 AsmOS << "b $0\n";
1337 if (hasBranchTargetEnforcement())
1338 AsmOS << "bti c\n";
1339 AsmOS << "b $0\n";
1341 if (!CanUseThumbBWJumpTable) {
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357 AsmOS << "push {r0,r1}\n"
1358 << "ldr r0, 1f\n"
1359 << "0: add r0, r0, pc\n"
1360 << "str r0, [sp, #4]\n"
1361 << "pop {r0,pc}\n"
1362 << ".balign 4\n"
1363 << "1: .word $0 - (0b + 4)\n";
1364 } else {
1365 if (hasBranchTargetEnforcement())
1366 AsmOS << "bti\n";
1367 AsmOS << "b.w $0\n";
1368 }
1371 AsmOS << "tail $0@plt\n";
1373 AsmOS << "pcalau12i t0, %pc_hi20($0)\n"
1374 << "jirl r0, t0, %pc_lo12($0)\n";
1375 } else {
1377 }
1378
1381 AsmOS.str(), "s",
1382 true);
1383}
1384
1385
1386
1387void LowerTypeTestsModule::buildBitSetsFromFunctions(
1393 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1395 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1396 else
1398}
1399
1400void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1401 GlobalVariable *GV) {
1402 if (WeakInitializerFn == nullptr) {
1405 false),
1407 M.getDataLayout().getProgramAddressSpace(),
1408 "__cfi_global_var_init", &M);
1412 WeakInitializerFn->setSection(
1414 ? "__TEXT,__StaticInit,regular,pure_instructions"
1415 : ".text.startup");
1416
1417
1419 }
1420
1421 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());
1425}
1426
1427void LowerTypeTestsModule::findGlobalVariableUsersOf(
1428 Constant *C, SmallSetVector<GlobalVariable *, 8> &Out) {
1429 for (auto *U : C->users()){
1433 findGlobalVariableUsersOf(C2, Out);
1434 }
1435}
1436
1437
1438void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1439 Function *F, Constant *JT, bool IsJumpTableCanonical) {
1440
1441
1442 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1443 findGlobalVariableUsersOf(F, GlobalVarUsers);
1444 for (auto *GV : GlobalVarUsers) {
1445 if (GV == GlobalAnnotation)
1446 continue;
1447 moveInitializerToModuleConstructor(GV);
1448 }
1449
1450
1451
1455 F->getAddressSpace(), "", &M);
1456 replaceCfiUses(F, PlaceholderFn, IsJumpTableCanonical);
1457
1459
1460 while (!PlaceholderFn->use_empty()) {
1463 assert(InsertPt && "Non-instruction users should have been eliminated");
1465 if (PN)
1466 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1470 Value *Select = Builder.CreateSelect(ICmp, JT,
1472
1475
1476
1477 if (PN)
1478 PN->setIncomingValueForBlock(InsertPt->getParent(), Select);
1479 else
1481 }
1483}
1484
1486 Attribute TFAttr = F->getFnAttribute("target-features");
1490 for (StringRef Feature : Features) {
1491 if (Feature == "-thumb-mode")
1492 return false;
1493 else if (Feature == "+thumb-mode")
1494 return true;
1495 }
1496 }
1497
1499}
1500
1501
1502
1503
1504Triple::ArchType LowerTypeTestsModule::selectJumpTableArmEncoding(
1507 return Arch;
1508
1509 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1510
1511
1512
1514 }
1515
1516
1517 unsigned ArmCount = 0, ThumbCount = 0;
1518 for (const auto GTM : Functions) {
1519 if (!GTM->isJumpTableCanonical()) {
1520
1521
1522 ++ArmCount;
1523 continue;
1524 }
1525
1528 }
1529
1531}
1532
1533void LowerTypeTestsModule::createJumpTable(
1538
1539 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1540
1541
1542
1543
1544
1545 bool areAllEntriesNounwind = true;
1546 for (GlobalTypeMember *GTM : Functions) {
1548 ->hasFnAttribute(llvm::Attribute::NoUnwind)) {
1549 areAllEntriesNounwind = false;
1550 }
1551 IRB.CreateCall(JumpTableAsm, GTM->getGlobal());
1552 }
1553 IRB.CreateUnreachable();
1554
1555
1556 F->setAlignment(Align(getJumpTableEntrySize(JumpTableArch)));
1557 F->addFnAttr(Attribute::Naked);
1559 F->addFnAttr("target-features", "-thumb-mode");
1561 if (hasBranchTargetEnforcement()) {
1562
1563
1564 F->addFnAttr("target-features", "+thumb-mode,+pacbti");
1565 } else {
1566 F->addFnAttr("target-features", "+thumb-mode");
1567 if (CanUseThumbBWJumpTable) {
1568
1569
1570 F->addFnAttr("target-cpu", "cortex-a8");
1571 }
1572 }
1573 }
1574
1575
1576
1578 if (F->hasFnAttribute("branch-target-enforcement"))
1579 F->removeFnAttr("branch-target-enforcement");
1580 if (F->hasFnAttribute("sign-return-address"))
1581 F->removeFnAttr("sign-return-address");
1582 }
1584
1585
1586 F->addFnAttr("target-features", "-c,-relax");
1587 }
1588
1589
1590
1592 F->addFnAttr(Attribute::NoCfCheck);
1593
1594
1595 if (areAllEntriesNounwind)
1596 F->addFnAttr(Attribute::NoUnwind);
1597
1598
1599 F->addFnAttr(Attribute::NoInline);
1600}
1601
1602
1603
1604void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1683
1684
1685
1686 Triple::ArchType JumpTableArch = selectJumpTableArmEncoding(Functions);
1687
1688
1689 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1690 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1691 for (unsigned I = 0; I != Functions.size(); ++I)
1692 GlobalLayout[Functions[I]] = I * EntrySize;
1693
1696 false),
1698 M.getDataLayout().getProgramAddressSpace(),
1699 ".cfi.jumptable", &M);
1705
1706 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1707
1708
1709
1710 for (unsigned I = 0; I != Functions.size(); ++I) {
1712 bool IsJumpTableCanonical = Functions[I]->isJumpTableCanonical();
1713
1715 JumpTableType, JumpTable,
1717 ConstantInt::get(IntPtrTy, I)});
1718
1719 const bool IsExported = Functions[I]->isExported();
1720 if (!IsJumpTableCanonical) {
1724 F->getName() + ".cfi_jt",
1725 CombinedGlobalElemPtr, &M);
1726 if (IsExported)
1728 else
1730 }
1731
1732 if (IsExported) {
1733 if (IsJumpTableCanonical)
1735 else
1737 }
1738
1739 if (!IsJumpTableCanonical) {
1740 if (F->hasExternalWeakLinkage())
1741 replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr,
1742 IsJumpTableCanonical);
1743 else
1744 replaceCfiUses(F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1745 } else {
1746 assert(F->getType()->getAddressSpace() == 0);
1747
1748 GlobalAlias *FAlias =
1750 CombinedGlobalElemPtr, &M);
1753 if (FAlias->hasName()) {
1754 F->setName(FAlias->getName() + ".cfi");
1755 maybeReplaceComdat(F, FAlias->getName());
1756 }
1757 replaceCfiUses(F, FAlias, IsJumpTableCanonical);
1758 if (->hasLocalLinkage())
1760 }
1761 }
1762
1763 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1764}
1765
1766
1767
1768
1769
1770
1771
1772void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1775
1776
1777 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1778
1779 for (GlobalTypeMember *GTM : Functions) {
1781
1782
1783 if (->hasAddressTaken())
1784 continue;
1785
1786
1789 ConstantInt::get(Int64Ty, IndirectIndex))));
1790 F->setMetadata("wasm.index", MD);
1791
1792
1793 GlobalLayout[GTM] = IndirectIndex++;
1794 }
1795
1796
1797
1799 GlobalLayout);
1800}
1801
1802void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1805 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1806 for (unsigned I = 0; I != TypeIds.size(); ++I)
1807 TypeIdIndices[TypeIds[I]] = I;
1808
1809
1810
1811 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.size());
1812 unsigned GlobalIndex = 0;
1813 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1814 for (GlobalTypeMember *GTM : Globals) {
1815 for (MDNode *Type : GTM->types()) {
1816
1817 auto I = TypeIdIndices.find(Type->getOperand(1));
1818 if (I != TypeIdIndices.end())
1819 TypeMembers[I->second].insert(GlobalIndex);
1820 }
1821 GlobalIndices[GTM] = GlobalIndex;
1822 GlobalIndex++;
1823 }
1824
1825 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1826 TypeMembers.emplace_back();
1827 std::set<uint64_t> &TMSet = TypeMembers.back();
1828 for (GlobalTypeMember *T : JT->targets())
1829 TMSet.insert(GlobalIndices[T]);
1830 }
1831
1832
1833
1835 const std::set<uint64_t> &O2) {
1836 return O1.size() < O2.size();
1837 });
1838
1839
1840
1841
1843 for (auto &&MemSet : TypeMembers)
1844 GLB.addFragment(MemSet);
1845
1846
1847 bool IsGlobalSet =
1849 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1850 auto OGTMI = OrderedGTMs.begin();
1851 for (auto &&F : GLB.Fragments) {
1852 for (auto &&Offset : F) {
1855 "variables and functions");
1856 *OGTMI++ = Globals[Offset];
1857 }
1858 }
1859
1860
1861 if (IsGlobalSet)
1862 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1863 else
1864 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1865}
1866
1867
1868LowerTypeTestsModule::LowerTypeTestsModule(
1870 const ModuleSummaryIndex *ImportSummary, DropTestKind DropTypeTests)
1871 : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary),
1873 : DropTypeTests) {
1874 assert(!(ExportSummary && ImportSummary));
1875 Triple TargetTriple(M.getTargetTriple());
1876 Arch = TargetTriple.getArch();
1878 CanUseArmJumpTable = true;
1880 auto &FAM =
1883
1884 if (F.isDeclaration())
1885 continue;
1887 if (TTI.hasArmWideBranch(false))
1888 CanUseArmJumpTable = true;
1889 if (TTI.hasArmWideBranch(true))
1890 CanUseThumbBWJumpTable = true;
1891 }
1892 }
1893 OS = TargetTriple.getOS();
1894 ObjectFormat = TargetTriple.getObjectFormat();
1895
1896
1897
1898 GlobalAnnotation = M.getGlobalVariable("llvm.global.annotations");
1899 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1902 FunctionAnnotations.insert_range(CA->operands());
1903 }
1904}
1905
1907 ModuleSummaryIndex Summary(false);
1908
1909
1910
1912 ExitOnError ExitOnErr("-lowertypetests-read-summary: " + ClReadSummary +
1913 ": ");
1916
1917 yaml::Input In(ReadSummaryFile->getBuffer());
1920 }
1921
1923 LowerTypeTestsModule(
1924 M, AM,
1925 ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr,
1926 ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr,
1927 DropTestKind::None)
1928 .lower();
1929
1931 ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary +
1932 ": ");
1933 std::error_code EC;
1936
1937 yaml::Output Out(OS);
1939 }
1940
1942}
1943
1946 if (Usr) {
1948 if (CB && CB->isCallee(&U))
1949 return true;
1950 }
1951 return false;
1952}
1953
1954void LowerTypeTestsModule::replaceCfiUses(Function *Old, Value *New,
1955 bool IsJumpTableCanonical) {
1956 SmallSetVector<Constant *, 4> Constants;
1958
1959
1961 continue;
1962
1963
1965 continue;
1966
1967
1968 if (isFunctionAnnotation(U.getUser()))
1969 continue;
1970
1971
1972
1975
1976
1978 continue;
1979 }
1980 }
1981
1982 U.set(New);
1983 }
1984
1985
1986 for (auto *C : Constants)
1987 C->handleOperandChange(Old, New);
1988}
1989
1990void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) {
1992}
1993
1995 bool ShouldDropAll) {
1998
2001 Assume->eraseFromParent();
2002
2003
2004
2005
2006
2007
2010 return isa(U);
2011 }));
2013 }
2015 }
2016}
2017
2018bool LowerTypeTestsModule::lower() {
2021
2022 if (DropTypeTests != DropTestKind::None) {
2023 bool ShouldDropAll = DropTypeTests == DropTestKind::All;
2024 if (TypeTestFunc)
2026
2027
2028
2029 Function *PublicTypeTestFunc =
2031 if (PublicTypeTestFunc)
2032 dropTypeTests(M, *PublicTypeTestFunc, ShouldDropAll);
2033 if (TypeTestFunc || PublicTypeTestFunc) {
2034
2035
2036
2037 for (GlobalVariable &GV : M.globals())
2038 GV.eraseMetadata(LLVMContext::MD_vcall_visibility);
2039 return true;
2040 }
2041 return false;
2042 }
2043
2044
2045
2046
2047
2050 return false;
2051
2052 Function *ICallBranchFunnelFunc =
2054 if ((!TypeTestFunc || TypeTestFunc->use_empty()) &&
2055 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->use_empty()) &&
2056 !ExportSummary && !ImportSummary)
2057 return false;
2058
2059 if (ImportSummary) {
2060 if (TypeTestFunc)
2063
2064 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->use_empty())
2066 "unexpected call to llvm.icall.branch.funnel during import phase");
2067
2070 for (auto &F : M) {
2071
2072
2073 if (F.hasLocalLinkage())
2074 continue;
2079 }
2080
2081 {
2082 ScopedSaveAliaseesAndUsed S(M);
2083 for (auto *F : Defs)
2084 importFunction(F, true);
2085 for (auto *F : Decls)
2086 importFunction(F, false);
2087 }
2088
2089 return true;
2090 }
2091
2092
2093
2094
2095 using GlobalClassesTy = EquivalenceClasses<
2096 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2097 GlobalClassesTy GlobalClasses;
2098
2099
2100
2101
2102
2103
2104
2105
2107 struct TIInfo {
2108 unsigned UniqueId;
2109 std::vector<GlobalTypeMember *> RefGlobals;
2110 };
2111 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2112 unsigned CurUniqueId = 0;
2114
2115
2116
2117 const bool CrossDsoCfi = M.getModuleFlag("Cross-DSO CFI") != nullptr;
2118
2119 struct ExportedFunctionInfo {
2121 MDNode *FuncMD;
2122 };
2123 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2124 if (ExportSummary) {
2125 NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
2126 if (CfiFunctionsMD) {
2127
2128 DenseSetGlobalValue::GUID AddressTaken;
2129 for (auto &I : *ExportSummary)
2130 for (auto &GVS : I.second.getSummaryList())
2131 if (GVS->isLive())
2132 for (const auto &Ref : GVS->refs()) {
2133 AddressTaken.insert(Ref.getGUID());
2134 for (auto &RefGVS : Ref.getSummaryList())
2136 AddressTaken.insert(Alias->getAliaseeGUID());
2137 }
2139 if (AddressTaken.count(GUID))
2140 return true;
2141 auto VI = ExportSummary->getValueInfo(GUID);
2142 if (!VI)
2143 return false;
2144 for (auto &I : VI.getSummaryList())
2146 if (AddressTaken.count(Alias->getAliaseeGUID()))
2147 return true;
2148 return false;
2149 };
2150 for (auto *FuncMD : CfiFunctionsMD->operands()) {
2151 assert(FuncMD->getNumOperands() >= 2);
2152 StringRef FunctionName =
2156 ->getValue()
2157 ->getUniqueInteger()
2158 .getZExtValue());
2162
2163
2164 if (!ExportSummary->isGUIDLive(GUID))
2165 continue;
2168 continue;
2169
2171 if (auto VI = ExportSummary->getValueInfo(GUID))
2172 for (const auto &GVS : VI.getSummaryList())
2175
2176 if (!Exported)
2177 continue;
2178 }
2179 auto P = ExportedFunctions.insert({FunctionName, {Linkage, FuncMD}});
2181 P.first->second = {Linkage, FuncMD};
2182 }
2183
2184 for (const auto &P : ExportedFunctions) {
2185 StringRef FunctionName = P.first;
2187 MDNode *FuncMD = P.second.FuncMD;
2188 Function *F = M.getFunction(FunctionName);
2189 if (F && F->hasLocalLinkage()) {
2190
2191
2192
2193
2194
2195
2196 F->setName(F->getName() + ".1");
2197 F = nullptr;
2198 }
2199
2200 if ()
2202 FunctionType::get(Type::getVoidTy(M.getContext()), false),
2203 GlobalVariable::ExternalLinkage,
2204 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2205
2206
2207
2208
2209
2210
2211 if (F->hasAvailableExternallyLinkage()) {
2213 F->deleteBody();
2214 F->setComdat(nullptr);
2215 F->clearMetadata();
2216 }
2217
2218
2219
2222
2223
2224
2225
2226
2227 if (F->isDeclaration()) {
2230
2231 F->eraseMetadata(LLVMContext::MD_type);
2233 F->addMetadata(LLVMContext::MD_type,
2235 }
2236 }
2237 }
2238 }
2239
2240 struct AliasToCreate {
2242 std::string TargetName;
2243 };
2244 std::vector AliasesToCreate;
2245
2246
2247
2248 if (ExportSummary) {
2249 if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) {
2250 for (auto *AliasMD : AliasesMD->operands()) {
2252 for (Metadata *MD : AliasMD->operands()) {
2254 if (!MDS)
2255 continue;
2256 StringRef AliasName = MDS->getString();
2257 if (!ExportedFunctions.count(AliasName))
2258 continue;
2259 auto *AliasF = M.getFunction(AliasName);
2260 if (AliasF)
2262 }
2263
2264 if (Aliases.empty())
2265 continue;
2266
2267 for (unsigned I = 1; I != Aliases.size(); ++I) {
2268 auto *AliasF = Aliases[I];
2269 ExportedFunctions.erase(AliasF->getName());
2270 AliasesToCreate.push_back(
2271 {AliasF, std::string(Aliases[0]->getName())});
2272 }
2273 }
2274 }
2275 }
2276
2277 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2278 for (GlobalObject &GO : M.global_objects()) {
2280 continue;
2281
2283 GO.getMetadata(LLVMContext::MD_type, Types);
2284
2285 bool IsJumpTableCanonical = false;
2286 bool IsExported = false;
2289 if (auto It = ExportedFunctions.find(F->getName());
2290 It != ExportedFunctions.end()) {
2291 IsJumpTableCanonical |= It->second.Linkage == CFL_Definition;
2292 IsExported = true;
2293
2294
2295
2296
2297 } else if (->hasAddressTaken()) {
2298 if (!CrossDsoCfi || !IsJumpTableCanonical || F->hasLocalLinkage())
2299 continue;
2300 }
2301 }
2302
2303 auto *GTM = GlobalTypeMember::create(Alloc, &GO, IsJumpTableCanonical,
2304 IsExported, Types);
2305 GlobalTypeMembers[&GO] = GTM;
2306 for (MDNode *Type : Types) {
2307 verifyTypeMDNode(&GO, Type);
2308 auto &Info = TypeIdInfo[Type->getOperand(1)];
2309 Info.UniqueId = ++CurUniqueId;
2310 Info.RefGlobals.push_back(GTM);
2311 }
2312 }
2313
2314 auto AddTypeIdUse = [&](Metadata *TypeId) -> TypeIdUserInfo & {
2315
2316
2317
2318
2319 auto Ins = TypeIdUsers.insert({TypeId, {}});
2320 if (Ins.second) {
2321
2322 auto &GCI = GlobalClasses.insert(TypeId);
2323 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2324
2325
2326 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2327 CurSet = GlobalClasses.unionSets(
2328 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2329 }
2330
2331 return Ins.first->second;
2332 };
2333
2334 if (TypeTestFunc) {
2335 for (const Use &U : TypeTestFunc->uses()) {
2337
2338
2339
2340
2341
2342
2343 bool OnlyAssumeUses = !CI->use_empty();
2344 for (const Use &CIU : CI->uses()) {
2346 continue;
2347 OnlyAssumeUses = false;
2348 break;
2349 }
2350 if (OnlyAssumeUses)
2351 continue;
2352
2354 if (!TypeIdMDVal)
2355 report_fatal_error("Second argument of llvm.type.test must be metadata");
2356 auto TypeId = TypeIdMDVal->getMetadata();
2357 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2358 }
2359 }
2360
2361 if (ICallBranchFunnelFunc) {
2362 for (const Use &U : ICallBranchFunnelFunc->uses()) {
2365 "llvm.icall.branch.funnel not supported on this target");
2366
2368
2369 std::vector<GlobalTypeMember *> Targets;
2370 if (CI->arg_size() % 2 != 1)
2372
2373 GlobalClassesTy::member_iterator CurSet;
2374 for (unsigned I = 1; I != CI->arg_size(); I += 2) {
2380 "Expected branch funnel operand to be global value");
2381
2382 GlobalTypeMember *GTM = GlobalTypeMembers[Base];
2383 Targets.push_back(GTM);
2384 GlobalClassesTy::member_iterator NewSet =
2385 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2386 if (I == 1)
2387 CurSet = NewSet;
2388 else
2389 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2390 }
2391
2392 GlobalClasses.unionSets(
2393 CurSet, GlobalClasses.findLeader(
2394 GlobalClasses.insert(ICallBranchFunnel::create(
2395 Alloc, CI, Targets, ++CurUniqueId))));
2396 }
2397 }
2398
2399 if (ExportSummary) {
2400 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2401 for (auto &P : TypeIdInfo) {
2404 TypeId->getString())]
2405 .push_back(TypeId);
2406 }
2407
2408 for (auto &P : *ExportSummary) {
2409 for (auto &S : P.second.getSummaryList()) {
2410 if (!ExportSummary->isGlobalValueLive(S.get()))
2411 continue;
2414 for (Metadata *MD : MetadataByGUID[G])
2415 AddTypeIdUse(MD).IsExported = true;
2416 }
2417 }
2418 }
2419
2420 if (GlobalClasses.empty())
2421 return false;
2422
2423 {
2424 ScopedSaveAliaseesAndUsed S(M);
2425
2426 for (const auto &C : GlobalClasses) {
2427 if (->isLeader())
2428 continue;
2429
2430 ++NumTypeIdDisjointSets;
2431
2432 std::vector<Metadata *> TypeIds;
2433 std::vector<GlobalTypeMember *> Globals;
2434 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2435 for (auto M : GlobalClasses.members(*C)) {
2440 else
2442 }
2443
2444
2445
2446
2448 return TypeIdInfo[M1].UniqueId < TypeIdInfo[M2].UniqueId;
2449 });
2450
2451
2453 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2454 return F1->UniqueId < F2->UniqueId;
2455 });
2456
2457
2458 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2459 }
2460 }
2461
2462 allocateByteArrays();
2463
2464 for (auto A : AliasesToCreate) {
2465 auto *Target = M.getNamedValue(A.TargetName);
2467 continue;
2469 AliasGA->setVisibility(A.Alias->getVisibility());
2470 AliasGA->setLinkage(A.Alias->getLinkage());
2471 AliasGA->takeName(A.Alias);
2472 A.Alias->replaceAllUsesWith(AliasGA);
2473 A.Alias->eraseFromParent();
2474 }
2475
2476
2477 if (ExportSummary) {
2478 if (NamedMDNode *SymversMD = M.getNamedMetadata("symvers")) {
2479 for (auto *Symver : SymversMD->operands()) {
2480 assert(Symver->getNumOperands() >= 2);
2483 StringRef Alias = cast(Symver->getOperand(1))->getString();
2484
2485 if (!ExportedFunctions.count(SymbolName))
2486 continue;
2487
2488 M.appendModuleInlineAsm(
2489 (llvm::Twine(".symver ") + SymbolName + ", " + Alias).str());
2490 }
2491 }
2492 }
2493
2494 return true;
2495}
2496
2500 if (UseCommandLine)
2501 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2502 else
2504 LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests)
2505 .lower();
2509}
2510
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532 for (auto &GV : M.globals()) {
2535 continue;
2536
2539 auto MaySimplifyPtr = [&](Value *Ptr) {
2541 if (auto *CFIGV = M.getNamedValue((GV->getName() + ".cfi").str()))
2542 Ptr = CFIGV;
2544 };
2545 auto MaySimplifyInt = [&](Value *Op) {
2547 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2548 return false;
2549 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2550 };
2554 MaySimplifyPtr(CI->getOperand(0))) {
2555
2556
2557
2561 continue;
2562 }
2563 }
2565 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2566 continue;
2569 if (U.getOperandNo() == 0 && CE &&
2570 CE->getOpcode() == Instruction::Sub &&
2571 MaySimplifyInt(CE->getOperand(1))) {
2572
2573
2574
2575
2576
2577 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2579 }
2581 if (U.getOperandNo() == 1 && CI &&
2583 MaySimplifyInt(CI->getOperand(0))) {
2584
2585
2589 }
2590 }
2591 }
2592 }
2593
2600 return PA;
2601}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Prepare AGPR Alloc
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the BumpPtrAllocator interface.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static const unsigned kARMJumpTableEntrySize
Definition LowerTypeTests.cpp:1261
static const unsigned kLOONGARCH64JumpTableEntrySize
Definition LowerTypeTests.cpp:1265
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
Definition LowerTypeTests.cpp:695
static const unsigned kX86IBTJumpTableEntrySize
Definition LowerTypeTests.cpp:1260
static cl::opt< std::string > ClReadSummary("lowertypetests-read-summary", cl::desc("Read summary from given YAML file before running pass"), cl::Hidden)
static const unsigned kRISCVJumpTableEntrySize
Definition LowerTypeTests.cpp:1264
static auto buildBitSets(ArrayRef< Metadata * > TypeIds, const DenseMap< GlobalTypeMember *, uint64_t > &GlobalLayout)
Definition LowerTypeTests.cpp:1147
static void dropTypeTests(Module &M, Function &TypeTestFunc, bool ShouldDropAll)
Definition LowerTypeTests.cpp:1994
static Value * createMaskedBitTest(IRBuilder<> &B, Value *Bits, Value *BitOffset)
Build a test that bit BitOffset mod sizeof(Bits)*8 is set in Bits.
Definition LowerTypeTests.cpp:584
static bool isThumbFunction(Function *F, Triple::ArchType ModuleArch)
Definition LowerTypeTests.cpp:1485
static const unsigned kX86JumpTableEntrySize
Definition LowerTypeTests.cpp:1259
static cl::opt< bool > AvoidReuse("lowertypetests-avoid-reuse", cl::desc("Try to avoid reuse of byte array addresses using aliases"), cl::Hidden, cl::init(true))
static cl::opt< PassSummaryAction > ClSummaryAction("lowertypetests-summary-action", cl::desc("What to do with the summary when running this pass"), cl::values(clEnumValN(PassSummaryAction::None, "none", "Do nothing"), clEnumValN(PassSummaryAction::Import, "import", "Import typeid resolutions from summary and globals"), clEnumValN(PassSummaryAction::Export, "export", "Export typeid resolutions to summary and globals")), cl::Hidden)
static const unsigned kARMBTIJumpTableEntrySize
Definition LowerTypeTests.cpp:1262
static cl::opt< std::string > ClWriteSummary("lowertypetests-write-summary", cl::desc("Write summary to given YAML file after running pass"), cl::Hidden)
static BitSetInfo buildBitSet(ArrayRef< uint64_t > Offsets)
Build a bit set for list of offsets.
Definition LowerTypeTests.cpp:576
static bool isDirectCall(Use &U)
Definition LowerTypeTests.cpp:1944
static const unsigned kARMv6MJumpTableEntrySize
Definition LowerTypeTests.cpp:1263
static cl::opt< DropTestKind > ClDropTypeTests("lowertypetests-drop-type-tests", cl::desc("Simply drop type test sequences"), cl::values(clEnumValN(DropTestKind::None, "none", "Do not drop any type tests"), clEnumValN(DropTestKind::Assume, "assume", "Drop type test assume sequences"), clEnumValN(DropTestKind::All, "all", "Drop all type test sequences")), cl::Hidden, cl::init(DropTestKind::None))
Machine Check Debug Module
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
FunctionAnalysisManager FAM
This file defines the PointerUnion class, which is a discriminated union of pointer types.
static StringRef getName(Value *V)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This pass exposes codegen information to IR-level passes.
This header defines support for implementing classes that have some trailing object (or arrays of obj...
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
void emplace(Args &&...A)
size_t count(StringRef S) const
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
ConstantArray - Constant Array Declarations.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)
Create an "inbounds" getelementptr.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
Analysis pass which computes a DominatorTree.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
LLVM_ABI void setComdat(Comdat *C)
const Comdat * getComdat() const
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
bool hasSection() const
Check if this global has a custom object file section.
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
static bool isLocalLinkage(LinkageTypes Linkage)
LinkageTypes getLinkage() const
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
PointerType * getType() const
Global values are always pointers.
VisibilityTypes
An enumeration for the kinds of visibility of global values.
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
@ ExternalWeakLinkage
ExternalWeak linkage description.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
MaybeAlign getAlign() const
Returns the alignment of the given variable.
void setConstant(bool Val)
LLVM_ABI void setCodeModel(CodeModel::Model CM)
Change the code model for this global.
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition LowerTypeTests.cpp:2497
const MDOperand & getOperand(unsigned I) const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
unsigned getNumOperands() const
Return number of MDNode operands.
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
TypeIdSummary & getOrInsertTypeIdSummary(StringRef TypeId)
Return an existing or new TypeIdSummary entry for TypeId.
const TypeIdSummary * getTypeIdSummary(StringRef TypeId) const
This returns either a pointer to the type id summary (if present in the summary map) or null (if not ...
CfiFunctionIndex & cfiFunctionDecls()
bool partiallySplitLTOUnits() const
CfiFunctionIndex & cfiFunctionDefs()
A Module instance is used to store all the information related to an LLVM module.
iterator_range< op_iterator > operands()
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Analysis pass which computes a PostDominatorTree.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
bool insert(const value_type &X)
Insert a new element into the SetVector.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition LowerTypeTests.cpp:2511
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetTransformInfo.
See the file comment for details on the usage of the TrailingObjects type.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI void replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
DropTestKind
Specifies how to drop type tests.
@ Assume
Do not drop type tests (default).
LLVM_ABI bool isJumpTableCanonical(Function *F)
Definition LowerTypeTests.cpp:252
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
SmallVector< unsigned char, 0 > ByteArray
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
@ Export
Export information to summary.
@ Import
Import information from summary.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
@ Ref
The access may reference the value stored in memory.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr to an Expected.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
LLVM_ABI void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
CfiFunctionLinkage
The type of CFI jumptable needed for a function.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
Kind
Specifies which kind of type check we should emit for this byte array.
@ Unknown
Unknown (analysis not performed, don't lower)
@ Single
Single element (last example in "Short Inline Bit Vectors")
@ Inline
Inlined bit vector ("Short Inline Bit Vectors")
@ Unsat
Unsatisfiable type (i.e. no global has this type metadata)
@ AllOnes
All-ones bit vector ("Eliminating Bit Vector Checks for All-Ones Bit Vectors")
@ ByteArray
Test a byte array (first example)
unsigned SizeM1BitWidth
Range of size-1 expressed as a bit width.
enum llvm::TypeTestResolution::Kind TheKind
LLVM_ABI BitSetInfo build()
Definition LowerTypeTests.cpp:163
SmallVector< uint64_t, 16 > Offsets
LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const
Definition LowerTypeTests.cpp:134
LLVM_ABI void print(raw_ostream &OS) const
Definition LowerTypeTests.cpp:148
std::set< uint64_t > Bits
This class is used to build a byte array containing overlapping bit sets.
uint64_t BitAllocs[BitsPerByte]
The number of bytes allocated so far for each of the bits.
std::vector< uint8_t > Bytes
The byte array built so far.
LLVM_ABI void allocate(const std::set< uint64_t > &Bits, uint64_t BitSize, uint64_t &AllocByteOffset, uint8_t &AllocMask)
Allocate BitSize bits in the byte array where Bits contains the bits to set.
Definition LowerTypeTests.cpp:229
This class implements a layout algorithm for globals referenced by bit sets that tries to keep member...
std::vector< std::vector< uint64_t > > Fragments
The computed layout.
LLVM_ABI void addFragment(const std::set< uint64_t > &F)
Add F to the layout while trying to keep its indices contiguous.
Definition LowerTypeTests.cpp:200
std::vector< uint64_t > FragmentMap
Mapping from object index to fragment index.