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
80#include
81#include
82#include
83#include
84#include
85#include <system_error>
86#include
87#include
88
89using namespace llvm;
91
92#define DEBUG_TYPE "lowertypetests"
93
94STATISTIC(ByteArraySizeBits, "Byte array size in bits");
95STATISTIC(ByteArraySizeBytes, "Byte array size in bytes");
96STATISTIC(NumByteArraysCreated, "Number of byte arrays created");
97STATISTIC(NumTypeTestCallsLowered, "Number of type test calls lowered");
98STATISTIC(NumTypeIdDisjointSets, "Number of disjoint sets of type identifiers");
99
101 "lowertypetests-avoid-reuse",
102 cl::desc("Try to avoid reuse of byte array addresses using aliases"),
104
106 "lowertypetests-summary-action",
107 cl::desc("What to do with the summary when running this pass"),
110 "Import typeid resolutions from summary and globals"),
112 "Export typeid resolutions to summary and globals")),
114
116 "lowertypetests-read-summary",
117 cl::desc("Read summary from given YAML file before running pass"),
119
121 "lowertypetests-write-summary",
122 cl::desc("Write summary to given YAML file after running pass"),
124
127 cl::desc("Simply drop type test sequences"),
129 "Do not drop any type tests"),
130 clEnumValN(DropTestKind::Assume, "assume",
131 "Drop type test assume sequences"),
133 "Drop all type test sequences")),
135
138 return false;
139
141 return false;
142
144 if (BitOffset >= BitSize)
145 return false;
146
147 return Bits.count(BitSize - 1 - BitOffset);
148}
149
151 OS << "offset " << ByteOffset << " size " << BitSize << " align "
153
155 OS << " all-ones\n";
156 return;
157 }
158
159 OS << " { ";
161 OS << B << ' ';
162 OS << "}\n";
163}
164
168
169
170
171
172
173
178 }
179
182
184 if (Mask != 0)
186
187
188
192
193
194
195
197 }
198
199 return BSI;
200}
201
203
205 std::vector<uint64_t> &Fragment = Fragments.back();
207
208 for (auto ObjIndex : F) {
210 if (OldFragmentIndex == 0) {
211
212
213 Fragment.push_back(ObjIndex);
214 } else {
215
216
217
218
219
220 std::vector<uint64_t> &OldFragment = Fragments[OldFragmentIndex];
222 OldFragment.clear();
223 }
224 }
225
226
227 for (uint64_t ObjIndex : Fragment)
229}
230
234
235 unsigned Bit = 0;
238 Bit = I;
239
240 AllocByteOffset = BitAllocs[Bit];
241
242
243 unsigned ReqSize = AllocByteOffset + BitSize;
245 if (Bytes.size() < ReqSize)
246 Bytes.resize(ReqSize);
247
248
249 AllocMask = 1 << Bit;
251 Bytes[AllocByteOffset + B] |= AllocMask;
252}
253
255 if (F->isDeclarationForLinker())
256 return false;
258 F->getParent()->getModuleFlag("CFI Canonical Jump Tables"));
259 if (!CI || !CI->isZero())
260 return true;
261 return F->hasFnAttribute("cfi-canonical-jump-table");
262}
263
264namespace {
265
266struct ByteArrayInfo {
267 std::set<uint64_t> Bits;
271 uint8_t *MaskPtr = nullptr;
272};
273
274
275
276
277
278
279class GlobalTypeMember final : TrailingObjects<GlobalTypeMember, MDNode *> {
281
283 size_t NTypes;
284
285
286
287
288
289
290 bool IsJumpTableCanonical;
291
292
293
294 bool IsExported;
295
296public:
298 bool IsJumpTableCanonical, bool IsExported,
300 auto *GTM = static_cast<GlobalTypeMember *>(Alloc.Allocate(
301 totalSizeToAlloc<MDNode *>(Types.size()), alignof(GlobalTypeMember)));
302 GTM->GO = GO;
303 GTM->NTypes = Types.size();
304 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
305 GTM->IsExported = IsExported;
306 llvm::copy(Types, GTM->getTrailingObjects());
307 return GTM;
308 }
309
310 GlobalObject *getGlobal() const {
311 return GO;
312 }
313
315 return IsJumpTableCanonical;
316 }
317
318 bool isExported() const {
319 return IsExported;
320 }
321
322 ArrayRef<MDNode *> types() const { return getTrailingObjects(NTypes); }
323};
324
325struct ICallBranchFunnel final
326 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
329 unsigned UniqueId) {
330 auto *Call = static_cast<ICallBranchFunnel *>(
331 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.size()),
332 alignof(ICallBranchFunnel)));
333 Call->CI = CI;
334 Call->UniqueId = UniqueId;
335 Call->NTargets = Targets.size();
338 }
339
340 CallInst *CI;
342 return getTrailingObjects(NTargets);
343 }
344
345 unsigned UniqueId;
346
347private:
348 size_t NTargets;
349};
350
351struct ScopedSaveAliaseesAndUsed {
354 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
355 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
356
357
358
359
360 void collectAndEraseUsedFunctions(Module &M,
361 SmallVectorImpl<GlobalValue *> &Vec,
362 bool CompilerUsed) {
364 if (!GV)
365 return;
366
367
368
369 GV->eraseFromParent();
370 auto NonFuncBegin =
371 std::stable_partition(Vec.begin(), Vec.end(), [](GlobalValue *GV) {
372 return isa(GV);
373 });
374 if (CompilerUsed)
376 else
379 }
380
381 ScopedSaveAliaseesAndUsed(Module &M) : M(M) {
382
383
384
385
386
387
388
389
390
391
392
393
394 collectAndEraseUsedFunctions(M, Used, false);
395 collectAndEraseUsedFunctions(M, CompilerUsed, true);
396
397 for (auto &GA : M.aliases()) {
398
399
401 FunctionAliases.push_back({&GA, F});
402 }
403
404 for (auto &GI : M.ifuncs())
406 ResolverIFuncs.push_back({&GI, F});
407 }
408
409 ~ScopedSaveAliaseesAndUsed() {
412
413 for (auto P : FunctionAliases)
414 P.first->setAliasee(P.second);
415
416 for (auto P : ResolverIFuncs) {
417
418
419
420 P.first->setResolver(P.second);
421 }
422 }
423};
424
425class LowerTypeTestsModule {
427
428 ModuleSummaryIndex *ExportSummary;
429 const ModuleSummaryIndex *ImportSummary;
430
431
433
437
438
439
440
441 bool CanUseArmJumpTable = false, CanUseThumbBWJumpTable = false;
442
443
444 int HasBranchTargetEnforcement = -1;
445
446 IntegerType *Int1Ty = Type::getInt1Ty(M.getContext());
447 IntegerType *Int8Ty = Type::getInt8Ty(M.getContext());
448 PointerType *PtrTy = PointerType::getUnqual(M.getContext());
449 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(M.getContext()), 0);
450 IntegerType *Int32Ty = Type::getInt32Ty(M.getContext());
451 IntegerType *Int64Ty = Type::getInt64Ty(M.getContext());
452 IntegerType *IntPtrTy = M.getDataLayout().getIntPtrType(M.getContext(), 0);
453
454
455 uint64_t IndirectIndex = 1;
456
457
458
459
460 struct TypeIdUserInfo {
461 std::vector<CallInst *> CallSites;
462 bool IsExported = false;
463 };
464 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
465
466
467
468
469
470 struct TypeIdLowering {
472
473
474
476
477
478
480
481
482
484
485
487
488
490
491
493 };
494
495 std::vector ByteArrayInfos;
496
497 Function *WeakInitializerFn = nullptr;
498
499 GlobalVariable *GlobalAnnotation;
500 DenseSet<Value *> FunctionAnnotations;
501
502 bool shouldExportConstantsAsAbsoluteSymbols();
503 uint8_t *exportTypeId(StringRef TypeId, const TypeIdLowering &TIL);
504 TypeIdLowering importTypeId(StringRef TypeId);
505 void importTypeTest(CallInst *CI);
507
508 ByteArrayInfo *createByteArray(const BitSetInfo &BSI);
509 void allocateByteArrays();
510 Value *createBitSetTest(IRBuilder<> &B, const TypeIdLowering &TIL,
511 Value *BitOffset);
512 void lowerTypeTestCalls(
514 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
515 Value *lowerTypeTestCall(Metadata *TypeId, CallInst *CI,
516 const TypeIdLowering &TIL);
517
522 bool hasBranchTargetEnforcement();
523 unsigned getJumpTableEntrySize(Triple::ArchType JumpTableArch);
524 InlineAsm *createJumpTableEntryAsm(Triple::ArchType JumpTableArch);
525 void verifyTypeMDNode(GlobalObject *GO, MDNode *Type);
532 void
536
537 void replaceWeakDeclarationWithJumpTablePtr(Function *F, Constant *JT,
538 bool IsJumpTableCanonical);
539 void moveInitializerToModuleConstructor(GlobalVariable *GV);
540 void findGlobalVariableUsersOf(Constant *C,
541 SmallSetVector<GlobalVariable *, 8> &Out);
542
545
546
547
548
549
550
551 void replaceCfiUses(Function *Old, Value *New, bool IsJumpTableCanonical);
552
553
554
555 void replaceDirectCalls(Value *Old, Value *New);
556
557 bool isFunctionAnnotation(Value *V) const {
558 return FunctionAnnotations.contains(V);
559 }
560
561 void maybeReplaceComdat(Function *F, StringRef OriginalName);
562
563public:
565 ModuleSummaryIndex *ExportSummary,
566 const ModuleSummaryIndex *ImportSummary,
568
569 bool lower();
570
571
572
574};
575}
576
577
583
584
585
587 Value *BitOffset) {
589 unsigned BitWidth = BitsType->getBitWidth();
590
591 BitOffset = B.CreateZExtOrTrunc(BitOffset, BitsType);
592 Value *BitIndex =
593 B.CreateAnd(BitOffset, ConstantInt::get(BitsType, BitWidth - 1));
594 Value *BitMask = B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
595 Value *MaskedBits = B.CreateAnd(Bits, BitMask);
596 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
597}
598
599ByteArrayInfo *LowerTypeTestsModule::createByteArray(const BitSetInfo &BSI) {
600
601
602
603 auto ByteArrayGlobal = new GlobalVariable(
605 auto MaskGlobal = new GlobalVariable(M, Int8Ty, true,
607
608 ByteArrayInfos.emplace_back();
609 ByteArrayInfo *BAI = &ByteArrayInfos.back();
610
611 BAI->Bits = BSI.Bits;
612 BAI->BitSize = BSI.BitSize;
613 BAI->ByteArray = ByteArrayGlobal;
614 BAI->MaskGlobal = MaskGlobal;
615 return BAI;
616}
617
618void LowerTypeTestsModule::allocateByteArrays() {
620 [](const ByteArrayInfo &BAI1, const ByteArrayInfo &BAI2) {
621 return BAI1.BitSize > BAI2.BitSize;
622 });
623
624 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
625
627 for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {
628 ByteArrayInfo *BAI = &ByteArrayInfos[I];
629
630 uint8_t Mask;
631 BAB.allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[I], Mask);
632
636 if (BAI->MaskPtr)
637 *BAI->MaskPtr = Mask;
638 }
639
642 new GlobalVariable(M, ByteArrayConst->getType(), true,
644
645 for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {
646 ByteArrayInfo *BAI = &ByteArrayInfos[I];
647
648 Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0),
649 ConstantInt::get(IntPtrTy, ByteArrayOffsets[I])};
651 ByteArrayConst->getType(), ByteArray, Idxs);
652
653
654
655
660 }
661
665 ByteArraySizeBytes = BAB.Bytes.size();
666}
667
668
669
671 const TypeIdLowering &TIL,
672 Value *BitOffset) {
674
675
677 } else {
680
681
682
683
685 "bits_use", ByteArray, &M);
686 }
687
688 Value *ByteAddr = B.CreateGEP(Int8Ty, ByteArray, BitOffset);
689 Value *Byte = B.CreateLoad(Int8Ty, ByteAddr);
690
691 Value *ByteAndMask =
693 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
694 }
695}
696
701 GV->getMetadata(LLVMContext::MD_type, Types);
703 if (Type->getOperand(1) != TypeId)
704 continue;
708 ->getZExtValue();
709 if (COffset == Offset)
710 return true;
711 }
712 return false;
713 }
714
716 APInt APOffset(DL.getIndexSizeInBits(0), 0);
717 bool Result = GEP->accumulateConstantOffset(DL, APOffset);
718 if (!Result)
719 return false;
722 }
723
725 if (Op->getOpcode() == Instruction::BitCast)
727
728 if (Op->getOpcode() == Instruction::Select)
731 }
732
733 return false;
734}
735
736
737
738Value *LowerTypeTestsModule::lowerTypeTestCall(Metadata *TypeId, CallInst *CI,
739 const TypeIdLowering &TIL) {
740
742 return nullptr;
745
747 const DataLayout &DL = M.getDataLayout();
750
752
754
755 Value *PtrAsInt = B.CreatePtrToInt(Ptr, IntPtrTy);
756
757 Constant *OffsetedGlobalAsInt =
760 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
761
762
763
764
765
766 Value *PtrOffset = B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
767
768
769
770
771
772
773
774
775
776 Value *BitOffset = B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,
777 {PtrOffset, PtrOffset, TIL.AlignLog2});
778
779 Value *OffsetInRange = B.CreateICmpULE(BitOffset, TIL.SizeM1);
780
781
783 return OffsetInRange;
784
785
786
787
788
796 Br->getMetadata(LLVMContext::MD_prof));
798
799
800 for (auto &Phi : Else->phis())
801 Phi.addIncoming(Phi.getIncomingValueForBlock(Then), InitialBB);
802
804 return createBitSetTest(ThenB, TIL, BitOffset);
805 }
806
807 MDBuilder MDB(M.getContext());
809 MDB.createLikelyBranchWeights()));
810
811
812
813 Value *Bit = createBitSetTest(ThenB, TIL, BitOffset);
814
815
816
817
818 B.SetInsertPoint(CI);
819 PHINode *P = B.CreatePHI(Int1Ty, 2);
820 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
821 P->addIncoming(Bit, ThenB.GetInsertBlock());
822 return P;
823}
824
825
826
827void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
829
830
831
832
833
834 std::vector<Constant *> GlobalInits;
835 const DataLayout &DL = M.getDataLayout();
836 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
838 uint64_t CurOffset = 0;
839 uint64_t DesiredPadding = 0;
840 for (GlobalTypeMember *G : Globals) {
842 Align Alignment =
843 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
844 MaxAlign = std::max(MaxAlign, Alignment);
845 uint64_t GVOffset = alignTo(CurOffset + DesiredPadding, Alignment);
846 GlobalLayout[G] = GVOffset;
847 if (GVOffset != 0) {
848 uint64_t Padding = GVOffset - CurOffset;
849 GlobalInits.push_back(
851 }
852
853 GlobalInits.push_back(GV->getInitializer());
854 uint64_t InitSize = DL.getTypeAllocSize(GV->getValueType());
855 CurOffset = GVOffset + InitSize;
856
857
858 DesiredPadding = NextPowerOf2(InitSize - 1) - InitSize;
859
860
861
862
863
864 if (DesiredPadding > 32)
865 DesiredPadding = alignTo(InitSize, 32) - InitSize;
866 }
867
869 auto *CombinedGlobal =
870 new GlobalVariable(M, NewInit->getType(), true,
872 CombinedGlobal->setAlignment(MaxAlign);
873
875 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
876
877
878
879
880 for (unsigned I = 0; I != Globals.size(); ++I) {
882
883
884 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
885 ConstantInt::get(Int32Ty, I * 2)};
887 NewInit->getType(), CombinedGlobal, CombinedGlobalIdxs);
889 GlobalAlias *GAlias =
891 "", CombinedGlobalElemPtr, &M);
896 }
897}
898
899bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
902}
903
904
905
906
907
908
909
910
911
912uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
913 const TypeIdLowering &TIL) {
914 TypeTestResolution &TTRes =
916 TTRes.TheKind = TIL.TheKind;
917
918 auto ExportGlobal = [&](StringRef Name, Constant *C) {
919 GlobalAlias *GA =
921 "__typeid_" + TypeId + "_" + Name, C, &M);
923 };
924
925 auto ExportConstant = [&](StringRef Name, uint64_t &Storage, Constant *C) {
926 if (shouldExportConstantsAsAbsoluteSymbols())
928 else
930 };
931
933 ExportGlobal("global_addr", TIL.OffsetedGlobal);
934
938 ExportConstant("align", TTRes.AlignLog2, TIL.AlignLog2);
939 ExportConstant("size_m1", TTRes.SizeM1, TIL.SizeM1);
940
941 uint64_t BitSize = cast(TIL.SizeM1)->getZExtValue() + 1;
944 else
946 }
947
949 ExportGlobal("byte_array", TIL.TheByteArray);
950 if (shouldExportConstantsAsAbsoluteSymbols())
951 ExportGlobal("bit_mask", TIL.BitMask);
952 else
954 }
955
957 ExportConstant("inline_bits", TTRes.InlineBits, TIL.InlineBits);
958
959 return nullptr;
960}
961
962LowerTypeTestsModule::TypeIdLowering
963LowerTypeTestsModule::importTypeId(StringRef TypeId) {
964 const TypeIdSummary *TidSummary = ImportSummary->getTypeIdSummary(TypeId);
965 if (!TidSummary)
966 return {};
967 const TypeTestResolution &TTRes = TidSummary->TTRes;
968
969 TypeIdLowering TIL;
970 TIL.TheKind = TTRes.TheKind;
971
972 auto ImportGlobal = [&](StringRef Name) {
973
974
975 GlobalVariable *GV = M.getOrInsertGlobal(
976 ("__typeid_" + TypeId + "_" + Name).str(), Int8Arr0Ty);
978 return GV;
979 };
980
981 auto ImportConstant = [&](StringRef Name, uint64_t Const, unsigned AbsWidth,
983 if (!shouldExportConstantsAsAbsoluteSymbols()) {
985 ConstantInt::get(isa(Ty) ? Ty : Int64Ty, Const);
988 return C;
989 }
990
991 Constant *C = ImportGlobal(Name);
995 if (GV->getMetadata(LLVMContext::MD_absolute_symbol))
996 return C;
997
998 auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {
1001 GV->setMetadata(LLVMContext::MD_absolute_symbol,
1003 };
1004 if (AbsWidth == IntPtrTy->getBitWidth())
1005 SetAbsRange(~0ull, ~0ull);
1006 else
1007 SetAbsRange(0, 1ull << AbsWidth);
1008 return C;
1009 };
1010
1012 auto *GV = ImportGlobal("global_addr");
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1025 TIL.OffsetedGlobal = GV;
1026 }
1027
1031 TIL.AlignLog2 = ImportConstant("align", TTRes.AlignLog2, 8, IntPtrTy);
1032 TIL.SizeM1 =
1034 }
1035
1037 TIL.TheByteArray = ImportGlobal("byte_array");
1038 TIL.BitMask = ImportConstant("bit_mask", TTRes.BitMask, 8, PtrTy);
1039 }
1040
1042 TIL.InlineBits = ImportConstant(
1045
1046 return TIL;
1047}
1048
1049void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1051 if (!TypeIdMDVal)
1052 report_fatal_error("Second argument of llvm.type.test must be metadata");
1053
1055
1056
1057
1058 if (!TypeIdStr)
1059 return;
1060
1061 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1062 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1063 if (Lowered) {
1066 }
1067}
1068
1069void LowerTypeTestsModule::maybeReplaceComdat(Function *F,
1070 StringRef OriginalName) {
1071
1072
1073
1074
1075 if (F->hasComdat() && ObjectFormat == Triple::COFF &&
1076 F->getComdat()->getName() == OriginalName) {
1077 Comdat *OldComdat = F->getComdat();
1078 Comdat *NewComdat = M.getOrInsertComdat(F->getName());
1079 for (GlobalObject &GO : M.global_objects()) {
1080 if (GO.getComdat() == OldComdat)
1082 }
1083 }
1084}
1085
1086
1087
1088void LowerTypeTestsModule::importFunction(Function *F,
1090 assert(F->getType()->getAddressSpace() == 0);
1091
1093 std::string Name = std::string(F->getName());
1094
1096
1097
1098 if (F->isDSOLocal()) {
1101 F->getAddressSpace(),
1102 Name + ".cfi", &M);
1104 replaceDirectCalls(F, RealF);
1105 }
1106 return;
1107 }
1108
1111
1112
1114 F->getAddressSpace(), Name + ".cfi_jt", &M);
1116 } else {
1117 F->setName(Name + ".cfi");
1118 maybeReplaceComdat(F, Name);
1120 F->getAddressSpace(), Name, &M);
1123
1124
1125
1126
1127 for (auto &U : F->uses()) {
1129 std::string AliasName = A->getName().str() + ".cfi";
1132 F->getAddressSpace(), "", &M);
1134 A->replaceAllUsesWith(AliasDecl);
1135 A->setName(AliasName);
1136 }
1137 }
1138 }
1139
1140 if (F->hasExternalWeakLinkage())
1142 else
1144
1145
1146
1147 F->setVisibility(Visibility);
1148}
1149
1150static auto
1154
1155 for (Metadata *TypeId : TypeIds)
1156 OffsetsByTypeID[TypeId];
1157 for (const auto &[Mem, MemOff] : GlobalLayout) {
1159 auto It = OffsetsByTypeID.find(Type->getOperand(1));
1160 if (It == OffsetsByTypeID.end())
1161 continue;
1165 ->getZExtValue();
1166 It->second.push_back(MemOff + Offset);
1167 }
1168 }
1169
1172 for (Metadata *TypeId : TypeIds) {
1176 dbgs() << MDS->getString() << ": ";
1177 else
1178 dbgs() << ": ";
1179 BitSets.back().second.print(dbgs());
1180 });
1181 }
1182
1183 return BitSets;
1184}
1185
1186void LowerTypeTestsModule::lowerTypeTestCalls(
1188 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1189
1190 for (const auto &[TypeId, BSI] : buildBitSets(TypeIds, GlobalLayout)) {
1191 ByteArrayInfo *BAI = nullptr;
1192 TypeIdLowering TIL;
1193
1194 uint64_t GlobalOffset =
1197 Int8Ty, CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
1198 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.AlignLog2);
1199 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.BitSize - 1);
1202 : TypeTestResolution::AllOnes;
1205 uint64_t InlineBits = 0;
1206 for (auto Bit : BSI.Bits)
1207 InlineBits |= uint64_t(1) << Bit;
1208 if (InlineBits == 0)
1210 else
1211 TIL.InlineBits = ConstantInt::get(
1212 (BSI.BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1213 } else {
1215 ++NumByteArraysCreated;
1216 BAI = createByteArray(BSI);
1217 TIL.TheByteArray = BAI->ByteArray;
1218 TIL.BitMask = BAI->MaskGlobal;
1219 }
1220
1221 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1222
1223 if (TIUI.IsExported) {
1224 uint8_t *MaskPtr = exportTypeId(cast(TypeId)->getString(), TIL);
1225 if (BAI)
1226 BAI->MaskPtr = MaskPtr;
1227 }
1228
1229
1230 for (CallInst *CI : TIUI.CallSites) {
1231 ++NumTypeTestCallsLowered;
1232 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1233 if (Lowered) {
1236 }
1237 }
1238 }
1239}
1240
1241void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) {
1242 if (Type->getNumOperands() != 2)
1243 report_fatal_error("All operands of type metadata must have 2 elements");
1244
1249 "A member of a type identifier may not have an explicit section");
1250
1251
1252
1253
1254
1256 if (!OffsetConstMD)
1259 if (!OffsetInt)
1261}
1262
1270
1271bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1272 if (HasBranchTargetEnforcement == -1) {
1273
1274
1276 M.getModuleFlag("branch-target-enforcement")))
1277 HasBranchTargetEnforcement = !BTE->isZero();
1278 else
1279 HasBranchTargetEnforcement = 0;
1280 }
1281 return HasBranchTargetEnforcement;
1282}
1283
1284unsigned
1285LowerTypeTestsModule::getJumpTableEntrySize(Triple::ArchType JumpTableArch) {
1286 switch (JumpTableArch) {
1290 M.getModuleFlag("cf-protection-branch")))
1291 if (MD->getZExtValue())
1297 if (CanUseThumbBWJumpTable) {
1298 if (hasBranchTargetEnforcement())
1301 } else {
1303 }
1305 if (hasBranchTargetEnforcement())
1313 default:
1315 }
1316}
1317
1318
1319
1320
1321InlineAsm *
1322LowerTypeTestsModule::createJumpTableEntryAsm(Triple::ArchType JumpTableArch) {
1323 std::string Asm;
1324 raw_string_ostream AsmOS(Asm);
1325
1327 bool Endbr = false;
1329 M.getModuleFlag("cf-protection-branch")))
1330 Endbr = !MD->isZero();
1331 if (Endbr)
1332 AsmOS << (JumpTableArch == Triple::x86 ? "endbr32\n" : "endbr64\n");
1333 AsmOS << "jmp ${0:c}@plt\n";
1334 if (Endbr)
1335 AsmOS << ".balign 16, 0xcc\n";
1336 else
1337 AsmOS << "int3\nint3\nint3\n";
1338 } else if (JumpTableArch == Triple::arm) {
1339 AsmOS << "b $0\n";
1341 if (hasBranchTargetEnforcement())
1342 AsmOS << "bti c\n";
1343 AsmOS << "b $0\n";
1345 if (!CanUseThumbBWJumpTable) {
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361 AsmOS << "push {r0,r1}\n"
1362 << "ldr r0, 1f\n"
1363 << "0: add r0, r0, pc\n"
1364 << "str r0, [sp, #4]\n"
1365 << "pop {r0,pc}\n"
1366 << ".balign 4\n"
1367 << "1: .word $0 - (0b + 4)\n";
1368 } else {
1369 if (hasBranchTargetEnforcement())
1370 AsmOS << "bti\n";
1371 AsmOS << "b.w $0\n";
1372 }
1375 AsmOS << "tail $0@plt\n";
1377 AsmOS << "pcalau12i t0, %pc_hi20($0)\n"
1378 << "jirl r0, t0, %pc_lo12($0)\n";
1379 } else {
1381 }
1382
1385 AsmOS.str(), "s",
1386 true);
1387}
1388
1389
1390
1391void LowerTypeTestsModule::buildBitSetsFromFunctions(
1397 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1399 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1400 else
1402}
1403
1404void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1405 GlobalVariable *GV) {
1406 if (WeakInitializerFn == nullptr) {
1409 false),
1411 M.getDataLayout().getProgramAddressSpace(),
1412 "__cfi_global_var_init", &M);
1416 WeakInitializerFn->setSection(
1418 ? "__TEXT,__StaticInit,regular,pure_instructions"
1419 : ".text.startup");
1420
1421
1423 }
1424
1425 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());
1429}
1430
1431void LowerTypeTestsModule::findGlobalVariableUsersOf(
1432 Constant *C, SmallSetVector<GlobalVariable *, 8> &Out) {
1433 for (auto *U : C->users()){
1437 findGlobalVariableUsersOf(C2, Out);
1438 }
1439}
1440
1441
1442void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1443 Function *F, Constant *JT, bool IsJumpTableCanonical) {
1444
1445
1446 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1447 findGlobalVariableUsersOf(F, GlobalVarUsers);
1448 for (auto *GV : GlobalVarUsers) {
1449 if (GV == GlobalAnnotation)
1450 continue;
1451 moveInitializerToModuleConstructor(GV);
1452 }
1453
1454
1455
1459 F->getAddressSpace(), "", &M);
1460 replaceCfiUses(F, PlaceholderFn, IsJumpTableCanonical);
1461
1463
1464 while (!PlaceholderFn->use_empty()) {
1467 assert(InsertPt && "Non-instruction users should have been eliminated");
1469 if (PN)
1470 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1474 Value *Select = Builder.CreateSelect(ICmp, JT,
1476
1479
1480
1481 if (PN)
1482 PN->setIncomingValueForBlock(InsertPt->getParent(), Select);
1483 else
1485 }
1487}
1488
1490 Attribute TFAttr = F->getFnAttribute("target-features");
1494 for (StringRef Feature : Features) {
1495 if (Feature == "-thumb-mode")
1496 return false;
1497 else if (Feature == "+thumb-mode")
1498 return true;
1499 }
1500 }
1501
1503}
1504
1505
1506
1507
1508Triple::ArchType LowerTypeTestsModule::selectJumpTableArmEncoding(
1511 return Arch;
1512
1513 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1514
1515
1516
1518 }
1519
1520
1521 unsigned ArmCount = 0, ThumbCount = 0;
1522 for (const auto GTM : Functions) {
1523 if (!GTM->isJumpTableCanonical()) {
1524
1525
1526 ++ArmCount;
1527 continue;
1528 }
1529
1532 }
1533
1535}
1536
1537void LowerTypeTestsModule::createJumpTable(
1542
1543 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1544
1545
1546
1547
1548
1549 bool areAllEntriesNounwind = true;
1550 for (GlobalTypeMember *GTM : Functions) {
1552 ->hasFnAttribute(llvm::Attribute::NoUnwind)) {
1553 areAllEntriesNounwind = false;
1554 }
1555 IRB.CreateCall(JumpTableAsm, GTM->getGlobal());
1556 }
1557 IRB.CreateUnreachable();
1558
1559
1560 F->setAlignment(Align(getJumpTableEntrySize(JumpTableArch)));
1561 F->addFnAttr(Attribute::Naked);
1563 F->addFnAttr("target-features", "-thumb-mode");
1565 if (hasBranchTargetEnforcement()) {
1566
1567
1568 F->addFnAttr("target-features", "+thumb-mode,+pacbti");
1569 } else {
1570 F->addFnAttr("target-features", "+thumb-mode");
1571 if (CanUseThumbBWJumpTable) {
1572
1573
1574 F->addFnAttr("target-cpu", "cortex-a8");
1575 }
1576 }
1577 }
1578
1579
1580
1582 if (F->hasFnAttribute("branch-target-enforcement"))
1583 F->removeFnAttr("branch-target-enforcement");
1584 if (F->hasFnAttribute("sign-return-address"))
1585 F->removeFnAttr("sign-return-address");
1586 }
1588
1589
1590 F->addFnAttr("target-features", "-c,-relax");
1591 }
1592
1593
1594
1596 F->addFnAttr(Attribute::NoCfCheck);
1597
1598
1599 if (areAllEntriesNounwind)
1600 F->addFnAttr(Attribute::NoUnwind);
1601
1602
1603 F->addFnAttr(Attribute::NoInline);
1604}
1605
1606
1607
1608void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
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
1682
1683
1684
1685
1687
1688
1689
1690 Triple::ArchType JumpTableArch = selectJumpTableArmEncoding(Functions);
1691
1692
1693 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1694 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1695 for (unsigned I = 0; I != Functions.size(); ++I)
1696 GlobalLayout[Functions[I]] = I * EntrySize;
1697
1700 false),
1702 M.getDataLayout().getProgramAddressSpace(),
1703 ".cfi.jumptable", &M);
1709
1710 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1711
1712
1713
1714 for (unsigned I = 0; I != Functions.size(); ++I) {
1716 bool IsJumpTableCanonical = Functions[I]->isJumpTableCanonical();
1717
1719 JumpTableType, JumpTable,
1721 ConstantInt::get(IntPtrTy, I)});
1722
1723 const bool IsExported = Functions[I]->isExported();
1724 if (!IsJumpTableCanonical) {
1728 F->getName() + ".cfi_jt",
1729 CombinedGlobalElemPtr, &M);
1730 if (IsExported)
1732 else
1734 }
1735
1736 if (IsExported) {
1737 if (IsJumpTableCanonical)
1739 else
1741 }
1742
1743 if (!IsJumpTableCanonical) {
1744 if (F->hasExternalWeakLinkage())
1745 replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr,
1746 IsJumpTableCanonical);
1747 else
1748 replaceCfiUses(F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1749 } else {
1750 assert(F->getType()->getAddressSpace() == 0);
1751
1752 GlobalAlias *FAlias =
1754 CombinedGlobalElemPtr, &M);
1757 if (FAlias->hasName()) {
1758 F->setName(FAlias->getName() + ".cfi");
1759 maybeReplaceComdat(F, FAlias->getName());
1760 }
1761 replaceCfiUses(F, FAlias, IsJumpTableCanonical);
1762 if (->hasLocalLinkage())
1764 }
1765 }
1766
1767 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1768}
1769
1770
1771
1772
1773
1774
1775
1776void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1779
1780
1781 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1782
1783 for (GlobalTypeMember *GTM : Functions) {
1785
1786
1787 if (->hasAddressTaken())
1788 continue;
1789
1790
1793 ConstantInt::get(Int64Ty, IndirectIndex))));
1794 F->setMetadata("wasm.index", MD);
1795
1796
1797 GlobalLayout[GTM] = IndirectIndex++;
1798 }
1799
1800
1801
1803 GlobalLayout);
1804}
1805
1806void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1809 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1810 for (unsigned I = 0; I != TypeIds.size(); ++I)
1811 TypeIdIndices[TypeIds[I]] = I;
1812
1813
1814
1815 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.size());
1816 unsigned GlobalIndex = 0;
1817 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1818 for (GlobalTypeMember *GTM : Globals) {
1819 for (MDNode *Type : GTM->types()) {
1820
1821 auto I = TypeIdIndices.find(Type->getOperand(1));
1822 if (I != TypeIdIndices.end())
1823 TypeMembers[I->second].insert(GlobalIndex);
1824 }
1825 GlobalIndices[GTM] = GlobalIndex;
1826 GlobalIndex++;
1827 }
1828
1829 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1830 TypeMembers.emplace_back();
1831 std::set<uint64_t> &TMSet = TypeMembers.back();
1832 for (GlobalTypeMember *T : JT->targets())
1833 TMSet.insert(GlobalIndices[T]);
1834 }
1835
1836
1837
1839 const std::set<uint64_t> &O2) {
1840 return O1.size() < O2.size();
1841 });
1842
1843
1844
1845
1847 for (auto &&MemSet : TypeMembers)
1848 GLB.addFragment(MemSet);
1849
1850
1851 bool IsGlobalSet =
1853 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1854 auto OGTMI = OrderedGTMs.begin();
1855 for (auto &&F : GLB.Fragments) {
1856 for (auto &&Offset : F) {
1859 "variables and functions");
1860 *OGTMI++ = Globals[Offset];
1861 }
1862 }
1863
1864
1865 if (IsGlobalSet)
1866 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1867 else
1868 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1869}
1870
1871
1872LowerTypeTestsModule::LowerTypeTestsModule(
1874 const ModuleSummaryIndex *ImportSummary, DropTestKind DropTypeTests)
1875 : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary),
1877 : DropTypeTests) {
1878 assert(!(ExportSummary && ImportSummary));
1879 Triple TargetTriple(M.getTargetTriple());
1880 Arch = TargetTriple.getArch();
1882 CanUseArmJumpTable = true;
1884 auto &FAM =
1887
1888 if (F.isDeclaration())
1889 continue;
1891 if (TTI.hasArmWideBranch(false))
1892 CanUseArmJumpTable = true;
1893 if (TTI.hasArmWideBranch(true))
1894 CanUseThumbBWJumpTable = true;
1895 }
1896 }
1897 OS = TargetTriple.getOS();
1898 ObjectFormat = TargetTriple.getObjectFormat();
1899
1900
1901
1902 GlobalAnnotation = M.getGlobalVariable("llvm.global.annotations");
1903 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1906 FunctionAnnotations.insert_range(CA->operands());
1907 }
1908}
1909
1911 ModuleSummaryIndex Summary(false);
1912
1913
1914
1916 ExitOnError ExitOnErr("-lowertypetests-read-summary: " + ClReadSummary +
1917 ": ");
1920
1921 yaml::Input In(ReadSummaryFile->getBuffer());
1924 }
1925
1927 LowerTypeTestsModule(
1928 M, AM,
1929 ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr,
1930 ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr,
1931 DropTestKind::None)
1932 .lower();
1933
1935 ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary +
1936 ": ");
1937 std::error_code EC;
1940
1941 yaml::Output Out(OS);
1943 }
1944
1946}
1947
1950 if (Usr) {
1952 if (CB && CB->isCallee(&U))
1953 return true;
1954 }
1955 return false;
1956}
1957
1958void LowerTypeTestsModule::replaceCfiUses(Function *Old, Value *New,
1959 bool IsJumpTableCanonical) {
1960 SmallSetVector<Constant *, 4> Constants;
1962
1963
1965 continue;
1966
1967
1969 continue;
1970
1971
1972 if (isFunctionAnnotation(U.getUser()))
1973 continue;
1974
1975
1976
1979
1980
1982 continue;
1983 }
1984 }
1985
1986 U.set(New);
1987 }
1988
1989
1990 for (auto *C : Constants)
1991 C->handleOperandChange(Old, New);
1992}
1993
1994void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) {
1996}
1997
1999 bool ShouldDropAll) {
2002
2005 Assume->eraseFromParent();
2006
2007
2008
2009
2010
2011
2014 return isa(U);
2015 }));
2017 }
2019 }
2020}
2021
2022bool LowerTypeTestsModule::lower() {
2025
2026 if (DropTypeTests != DropTestKind::None) {
2027 bool ShouldDropAll = DropTypeTests == DropTestKind::All;
2028 if (TypeTestFunc)
2030
2031
2032
2033 Function *PublicTypeTestFunc =
2035 if (PublicTypeTestFunc)
2036 dropTypeTests(M, *PublicTypeTestFunc, ShouldDropAll);
2037 if (TypeTestFunc || PublicTypeTestFunc) {
2038
2039
2040
2041 for (GlobalVariable &GV : M.globals())
2042 GV.eraseMetadata(LLVMContext::MD_vcall_visibility);
2043 return true;
2044 }
2045 return false;
2046 }
2047
2048
2049
2050
2051
2054 return false;
2055
2056 Function *ICallBranchFunnelFunc =
2058 if ((!TypeTestFunc || TypeTestFunc->use_empty()) &&
2059 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->use_empty()) &&
2060 !ExportSummary && !ImportSummary)
2061 return false;
2062
2063 if (ImportSummary) {
2064 if (TypeTestFunc)
2067
2068 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->use_empty())
2070 "unexpected call to llvm.icall.branch.funnel during import phase");
2071
2074 for (auto &F : M) {
2075
2076
2077 if (F.hasLocalLinkage())
2078 continue;
2083 }
2084
2085 {
2086 ScopedSaveAliaseesAndUsed S(M);
2087 for (auto *F : Defs)
2088 importFunction(F, true);
2089 for (auto *F : Decls)
2090 importFunction(F, false);
2091 }
2092
2093 return true;
2094 }
2095
2096
2097
2098
2099 using GlobalClassesTy = EquivalenceClasses<
2100 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2101 GlobalClassesTy GlobalClasses;
2102
2103
2104
2105
2106
2107
2108
2109
2111 struct TIInfo {
2112 unsigned UniqueId;
2113 std::vector<GlobalTypeMember *> RefGlobals;
2114 };
2115 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2116 unsigned CurUniqueId = 0;
2118
2119
2120
2121 const bool CrossDsoCfi = M.getModuleFlag("Cross-DSO CFI") != nullptr;
2122
2123 struct ExportedFunctionInfo {
2125 MDNode *FuncMD;
2126 };
2127 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2128 if (ExportSummary) {
2129 NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
2130 if (CfiFunctionsMD) {
2131
2132 DenseSetGlobalValue::GUID AddressTaken;
2133 for (auto &I : *ExportSummary)
2134 for (auto &GVS : I.second.getSummaryList())
2135 if (GVS->isLive())
2136 for (const auto &Ref : GVS->refs()) {
2137 AddressTaken.insert(Ref.getGUID());
2138 for (auto &RefGVS : Ref.getSummaryList())
2140 AddressTaken.insert(Alias->getAliaseeGUID());
2141 }
2143 if (AddressTaken.count(GUID))
2144 return true;
2145 auto VI = ExportSummary->getValueInfo(GUID);
2146 if (!VI)
2147 return false;
2148 for (auto &I : VI.getSummaryList())
2150 if (AddressTaken.count(Alias->getAliaseeGUID()))
2151 return true;
2152 return false;
2153 };
2154 for (auto *FuncMD : CfiFunctionsMD->operands()) {
2155 assert(FuncMD->getNumOperands() >= 2);
2156 StringRef FunctionName =
2160 ->getValue()
2161 ->getUniqueInteger()
2162 .getZExtValue());
2166
2167
2168 if (!ExportSummary->isGUIDLive(GUID))
2169 continue;
2172 continue;
2173
2175 if (auto VI = ExportSummary->getValueInfo(GUID))
2176 for (const auto &GVS : VI.getSummaryList())
2179
2180 if (!Exported)
2181 continue;
2182 }
2183 auto P = ExportedFunctions.insert({FunctionName, {Linkage, FuncMD}});
2185 P.first->second = {Linkage, FuncMD};
2186 }
2187
2188 for (const auto &P : ExportedFunctions) {
2189 StringRef FunctionName = P.first;
2191 MDNode *FuncMD = P.second.FuncMD;
2192 Function *F = M.getFunction(FunctionName);
2193 if (F && F->hasLocalLinkage()) {
2194
2195
2196
2197
2198
2199
2200 F->setName(F->getName() + ".1");
2201 F = nullptr;
2202 }
2203
2204 if ()
2206 FunctionType::get(Type::getVoidTy(M.getContext()), false),
2207 GlobalVariable::ExternalLinkage,
2208 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2209
2210
2211
2212
2213
2214
2215 if (F->hasAvailableExternallyLinkage()) {
2217 F->deleteBody();
2218 F->setComdat(nullptr);
2219 F->clearMetadata();
2220 }
2221
2222
2223
2226
2227
2228
2229
2230
2231 if (F->isDeclaration()) {
2234
2235 F->eraseMetadata(LLVMContext::MD_type);
2237 F->addMetadata(LLVMContext::MD_type,
2239 }
2240 }
2241 }
2242 }
2243
2244 struct AliasToCreate {
2246 std::string TargetName;
2247 };
2248 std::vector AliasesToCreate;
2249
2250
2251
2252 if (ExportSummary) {
2253 if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) {
2254 for (auto *AliasMD : AliasesMD->operands()) {
2256 for (Metadata *MD : AliasMD->operands()) {
2258 if (!MDS)
2259 continue;
2260 StringRef AliasName = MDS->getString();
2261 if (!ExportedFunctions.count(AliasName))
2262 continue;
2263 auto *AliasF = M.getFunction(AliasName);
2264 if (AliasF)
2266 }
2267
2268 if (Aliases.empty())
2269 continue;
2270
2271 for (unsigned I = 1; I != Aliases.size(); ++I) {
2272 auto *AliasF = Aliases[I];
2273 ExportedFunctions.erase(AliasF->getName());
2274 AliasesToCreate.push_back(
2275 {AliasF, std::string(Aliases[0]->getName())});
2276 }
2277 }
2278 }
2279 }
2280
2281 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2282 for (GlobalObject &GO : M.global_objects()) {
2284 continue;
2285
2287 GO.getMetadata(LLVMContext::MD_type, Types);
2288
2289 bool IsJumpTableCanonical = false;
2290 bool IsExported = false;
2293 if (auto It = ExportedFunctions.find(F->getName());
2294 It != ExportedFunctions.end()) {
2295 IsJumpTableCanonical |= It->second.Linkage == CFL_Definition;
2296 IsExported = true;
2297
2298
2299
2300
2301 } else if (->hasAddressTaken()) {
2302 if (!CrossDsoCfi || !IsJumpTableCanonical || F->hasLocalLinkage())
2303 continue;
2304 }
2305 }
2306
2307 auto *GTM = GlobalTypeMember::create(Alloc, &GO, IsJumpTableCanonical,
2308 IsExported, Types);
2309 GlobalTypeMembers[&GO] = GTM;
2310 for (MDNode *Type : Types) {
2311 verifyTypeMDNode(&GO, Type);
2312 auto &Info = TypeIdInfo[Type->getOperand(1)];
2313 Info.UniqueId = ++CurUniqueId;
2314 Info.RefGlobals.push_back(GTM);
2315 }
2316 }
2317
2318 auto AddTypeIdUse = [&](Metadata *TypeId) -> TypeIdUserInfo & {
2319
2320
2321
2322
2323 auto Ins = TypeIdUsers.insert({TypeId, {}});
2324 if (Ins.second) {
2325
2326 auto &GCI = GlobalClasses.insert(TypeId);
2327 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2328
2329
2330 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2331 CurSet = GlobalClasses.unionSets(
2332 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2333 }
2334
2335 return Ins.first->second;
2336 };
2337
2338 if (TypeTestFunc) {
2339 for (const Use &U : TypeTestFunc->uses()) {
2341
2342
2343
2344
2345
2346
2347 bool OnlyAssumeUses = !CI->use_empty();
2348 for (const Use &CIU : CI->uses()) {
2350 continue;
2351 OnlyAssumeUses = false;
2352 break;
2353 }
2354 if (OnlyAssumeUses)
2355 continue;
2356
2358 if (!TypeIdMDVal)
2359 report_fatal_error("Second argument of llvm.type.test must be metadata");
2360 auto TypeId = TypeIdMDVal->getMetadata();
2361 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2362 }
2363 }
2364
2365 if (ICallBranchFunnelFunc) {
2366 for (const Use &U : ICallBranchFunnelFunc->uses()) {
2369 "llvm.icall.branch.funnel not supported on this target");
2370
2372
2373 std::vector<GlobalTypeMember *> Targets;
2374 if (CI->arg_size() % 2 != 1)
2376
2377 GlobalClassesTy::member_iterator CurSet;
2378 for (unsigned I = 1; I != CI->arg_size(); I += 2) {
2384 "Expected branch funnel operand to be global value");
2385
2386 GlobalTypeMember *GTM = GlobalTypeMembers[Base];
2387 Targets.push_back(GTM);
2388 GlobalClassesTy::member_iterator NewSet =
2389 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2390 if (I == 1)
2391 CurSet = NewSet;
2392 else
2393 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2394 }
2395
2396 GlobalClasses.unionSets(
2397 CurSet, GlobalClasses.findLeader(
2398 GlobalClasses.insert(ICallBranchFunnel::create(
2399 Alloc, CI, Targets, ++CurUniqueId))));
2400 }
2401 }
2402
2403 if (ExportSummary) {
2404 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2405 for (auto &P : TypeIdInfo) {
2408 TypeId->getString())]
2409 .push_back(TypeId);
2410 }
2411
2412 for (auto &P : *ExportSummary) {
2413 for (auto &S : P.second.getSummaryList()) {
2414 if (!ExportSummary->isGlobalValueLive(S.get()))
2415 continue;
2418 for (Metadata *MD : MetadataByGUID[G])
2419 AddTypeIdUse(MD).IsExported = true;
2420 }
2421 }
2422 }
2423
2424 if (GlobalClasses.empty())
2425 return false;
2426
2427 {
2428 ScopedSaveAliaseesAndUsed S(M);
2429
2430 for (const auto &C : GlobalClasses) {
2431 if (->isLeader())
2432 continue;
2433
2434 ++NumTypeIdDisjointSets;
2435
2436 std::vector<Metadata *> TypeIds;
2437 std::vector<GlobalTypeMember *> Globals;
2438 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2439 for (auto M : GlobalClasses.members(*C)) {
2444 else
2446 }
2447
2448
2449
2450
2452 return TypeIdInfo[M1].UniqueId < TypeIdInfo[M2].UniqueId;
2453 });
2454
2455
2457 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2458 return F1->UniqueId < F2->UniqueId;
2459 });
2460
2461
2462 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2463 }
2464 }
2465
2466 allocateByteArrays();
2467
2468 for (auto A : AliasesToCreate) {
2469 auto *Target = M.getNamedValue(A.TargetName);
2471 continue;
2473 AliasGA->setVisibility(A.Alias->getVisibility());
2474 AliasGA->setLinkage(A.Alias->getLinkage());
2475 AliasGA->takeName(A.Alias);
2476 A.Alias->replaceAllUsesWith(AliasGA);
2477 A.Alias->eraseFromParent();
2478 }
2479
2480
2481 if (ExportSummary) {
2482 if (NamedMDNode *SymversMD = M.getNamedMetadata("symvers")) {
2483 for (auto *Symver : SymversMD->operands()) {
2484 assert(Symver->getNumOperands() >= 2);
2487 StringRef Alias = cast(Symver->getOperand(1))->getString();
2488
2489 if (!ExportedFunctions.count(SymbolName))
2490 continue;
2491
2492 M.appendModuleInlineAsm(
2493 (llvm::Twine(".symver ") + SymbolName + ", " + Alias).str());
2494 }
2495 }
2496 }
2497
2498 return true;
2499}
2500
2504 if (UseCommandLine)
2505 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2506 else
2508 LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests)
2509 .lower();
2513}
2514
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536 for (auto &GV : M.globals()) {
2539 continue;
2540
2543 auto MaySimplifyPtr = [&](Value *Ptr) {
2545 if (auto *CFIGV = M.getNamedValue((GV->getName() + ".cfi").str()))
2546 Ptr = CFIGV;
2548 };
2549 auto MaySimplifyInt = [&](Value *Op) {
2551 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2552 return false;
2553 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2554 };
2558 MaySimplifyPtr(CI->getOperand(0))) {
2559
2560
2561
2565 continue;
2566 }
2567 }
2569 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2570 continue;
2573 if (U.getOperandNo() == 0 && CE &&
2574 CE->getOpcode() == Instruction::Sub &&
2575 MaySimplifyInt(CE->getOperand(1))) {
2576
2577
2578
2579
2580
2581 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2583 }
2585 if (U.getOperandNo() == 1 && CI &&
2587 MaySimplifyInt(CI->getOperand(0))) {
2588
2589
2593 }
2594 }
2595 }
2596 }
2597
2604 return PA;
2605}
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:1265
static const unsigned kLOONGARCH64JumpTableEntrySize
Definition LowerTypeTests.cpp:1269
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
Definition LowerTypeTests.cpp:697
static const unsigned kX86IBTJumpTableEntrySize
Definition LowerTypeTests.cpp:1264
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:1268
static auto buildBitSets(ArrayRef< Metadata * > TypeIds, const DenseMap< GlobalTypeMember *, uint64_t > &GlobalLayout)
Definition LowerTypeTests.cpp:1151
static void dropTypeTests(Module &M, Function &TypeTestFunc, bool ShouldDropAll)
Definition LowerTypeTests.cpp:1998
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:586
static bool isThumbFunction(Function *F, Triple::ArchType ModuleArch)
Definition LowerTypeTests.cpp:1489
static const unsigned kX86JumpTableEntrySize
Definition LowerTypeTests.cpp:1263
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:1266
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:578
static bool isDirectCall(Use &U)
Definition LowerTypeTests.cpp:1948
static const unsigned kARMv6MJumpTableEntrySize
Definition LowerTypeTests.cpp:1267
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.
This file contains the declarations for profiling metadata utility functions.
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:2501
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:2515
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:254
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:165
SmallVector< uint64_t, 16 > Offsets
LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const
Definition LowerTypeTests.cpp:136
LLVM_ABI void print(raw_ostream &OS) const
Definition LowerTypeTests.cpp:150
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:231
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:202
std::vector< uint64_t > FragmentMap
Mapping from object index to fragment index.