LLVM: lib/Target/BPF/BPFAbstractMemberAccess.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
86#include "llvm/IR/IntrinsicsBPF.h"
95#include
96
97#define DEBUG_TYPE "bpf-abstract-member-access"
98
99namespace llvm {
101
106 M, Intrinsic::bpf_passthrough, {Input->getType(), Input->getType()});
109
112 return NewInst;
113}
114}
115
116using namespace llvm;
117
118namespace {
119class BPFAbstractMemberAccess final {
120public:
122
124
125 struct CallInfo {
126 uint32_t Kind;
127 uint32_t AccessIndex;
128 MaybeAlign RecordAlignment;
129 MDNode *Metadata;
130 WeakTrackingVH Base;
131 };
132 typedef std::stack<std::pair<CallInst *, CallInfo>> CallInfoStack;
133
134private:
135 enum : uint32_t {
136 BPFPreserveArrayAI = 1,
137 BPFPreserveUnionAI = 2,
138 BPFPreserveStructAI = 3,
139 BPFPreserveFieldInfoAI = 4,
140 };
141
142 TargetMachine *TM;
143 const DataLayout *DL = nullptr;
145
146 static std::map<std::string, GlobalVariable *> GEPGlobals;
147
148 std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain;
149
150
151
152 std::map<CallInst *, CallInfo> BaseAICalls;
153
154 std::map<DICompositeType *, DIDerivedType *> AnonRecords;
155
156 void CheckAnonRecordType(DIDerivedType *ParentTy, DIType *Ty);
157 void CheckCompositeType(DIDerivedType *ParentTy, DICompositeType *CTy);
158 void CheckDerivedType(DIDerivedType *ParentTy, DIDerivedType *DTy);
159 void ResetMetadata(struct CallInfo &CInfo);
160
161 bool doTransformation(Function &F);
162
163 void traceAICall(CallInst *Call, CallInfo &ParentInfo);
164 void traceBitCast(BitCastInst *BitCast, CallInst *Parent,
165 CallInfo &ParentInfo);
166 void traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
167 CallInfo &ParentInfo);
168 void collectAICallChains(Function &F);
169
170 bool IsPreserveDIAccessIndexCall(const CallInst *Call, CallInfo &Cinfo);
171 bool IsValidAIChain(const MDNode *ParentMeta, uint32_t ParentAI,
172 const MDNode *ChildMeta);
173 bool removePreserveAccessIndexIntrinsic(Function &F);
174 bool HasPreserveFieldInfoCall(CallInfoStack &CallStack);
175 void GetStorageBitRange(DIDerivedType *MemberTy, Align RecordAlignment,
176 uint32_t &StartBitOffset, uint32_t &EndBitOffset);
177 uint32_t GetFieldInfo(uint32_t InfoKind, DICompositeType *CTy,
178 uint32_t AccessIndex, uint32_t PatchImm,
179 MaybeAlign RecordAlignment);
180
181 Value *computeBaseAndAccessKey(CallInst *Call, CallInfo &CInfo,
182 std::string &AccessKey, MDNode *&BaseMeta);
183 MDNode *computeAccessKey(CallInst *Call, CallInfo &CInfo,
184 std::string &AccessKey, bool &IsInt32Ret);
185 bool transformGEPChain(CallInst *Call, CallInfo &CInfo);
186};
187
188std::map<std::string, GlobalVariable *> BPFAbstractMemberAccess::GEPGlobals;
189}
190
191bool BPFAbstractMemberAccess::run(Function &F) {
192 LLVM_DEBUG(dbgs() << "********** Abstract Member Accesses **********\n");
193
194 M = F.getParent();
195 if (!M)
196 return false;
197
198
200 return false;
201
202
203
204
205
206
207 DISubprogram *SP = F.getSubprogram();
208 if (SP && SP->isDefinition()) {
209 for (DIType *Ty: SP->getType()->getTypeArray())
210 CheckAnonRecordType(nullptr, Ty);
211 for (const DINode *DN : SP->getRetainedNodes()) {
213 CheckAnonRecordType(nullptr, DV->getType());
214 }
215 }
216
218 return doTransformation(F);
219}
220
221void BPFAbstractMemberAccess::ResetMetadata(struct CallInfo &CInfo) {
223 auto It = AnonRecords.find(Ty);
224 if (It != AnonRecords.end() && It->second != nullptr)
225 CInfo.Metadata = It->second;
226 }
227}
228
229void BPFAbstractMemberAccess::CheckCompositeType(DIDerivedType *ParentTy,
230 DICompositeType *CTy) {
232 ParentTy->getTag() != dwarf::DW_TAG_typedef)
233 return;
234
235 auto [It, Inserted] = AnonRecords.try_emplace(CTy, ParentTy);
236
237
238
239 if (!Inserted && It->second != ParentTy)
240 It->second = nullptr;
241}
242
243void BPFAbstractMemberAccess::CheckDerivedType(DIDerivedType *ParentTy,
244 DIDerivedType *DTy) {
245 DIType *BaseType = DTy->getBaseType();
247 return;
248
250 if (Tag == dwarf::DW_TAG_pointer_type)
251 CheckAnonRecordType(nullptr, BaseType);
252 else if (Tag == dwarf::DW_TAG_typedef)
253 CheckAnonRecordType(DTy, BaseType);
254 else
255 CheckAnonRecordType(ParentTy, BaseType);
256}
257
258void BPFAbstractMemberAccess::CheckAnonRecordType(DIDerivedType *ParentTy,
259 DIType *Ty) {
260 if (!Ty)
261 return;
262
264 return CheckCompositeType(ParentTy, CTy);
266 return CheckDerivedType(ParentTy, DTy);
267}
268
270 if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
271 Tag != dwarf::DW_TAG_volatile_type &&
272 Tag != dwarf::DW_TAG_restrict_type &&
273 Tag != dwarf::DW_TAG_member)
274 return false;
275 if (Tag == dwarf::DW_TAG_typedef && !skipTypedef)
276 return false;
277 return true;
278}
279
283 break;
284 Ty = DTy->getBaseType();
285 }
286 return Ty;
287}
288
292 break;
293 Ty = DTy->getBaseType();
294 }
295 return Ty;
296}
297
299 DINodeArray Elements = CTy->getElements();
301 for (uint32_t I = StartDim; I < Elements.size(); ++I) {
303 if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
306 DimSize *= CI->getSExtValue();
307 }
308 }
309
310 return DimSize;
311}
312
314
315 return Call->getParamElementType(0);
316}
317
323
324
325bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
326 CallInfo &CInfo) {
328 return false;
329
331 if (!GV)
332 return false;
333 if (GV->getName().starts_with("llvm.preserve.array.access.index")) {
334 CInfo.Kind = BPFPreserveArrayAI;
335 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
336 if (!CInfo.Metadata)
337 report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic");
341 return true;
342 }
343 if (GV->getName().starts_with("llvm.preserve.union.access.index")) {
344 CInfo.Kind = BPFPreserveUnionAI;
345 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
346 if (!CInfo.Metadata)
347 report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic");
348 ResetMetadata(CInfo);
351 return true;
352 }
353 if (GV->getName().starts_with("llvm.preserve.struct.access.index")) {
354 CInfo.Kind = BPFPreserveStructAI;
355 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
356 if (!CInfo.Metadata)
357 report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic");
358 ResetMetadata(CInfo);
362 return true;
363 }
364 if (GV->getName().starts_with("llvm.bpf.preserve.field.info")) {
365 CInfo.Kind = BPFPreserveFieldInfoAI;
366 CInfo.Metadata = nullptr;
367
370 report_fatal_error("Incorrect info_kind for llvm.bpf.preserve.field.info intrinsic");
371 CInfo.AccessIndex = InfoKind;
372 return true;
373 }
374 if (GV->getName().starts_with("llvm.bpf.preserve.type.info")) {
375 CInfo.Kind = BPFPreserveFieldInfoAI;
376 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
377 if (!CInfo.Metadata)
378 report_fatal_error("Missing metadata for llvm.preserve.type.info intrinsic");
381 report_fatal_error("Incorrect flag for llvm.bpf.preserve.type.info intrinsic");
386 else
388 return true;
389 }
390 if (GV->getName().starts_with("llvm.bpf.preserve.enum.value")) {
391 CInfo.Kind = BPFPreserveFieldInfoAI;
392 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
393 if (!CInfo.Metadata)
394 report_fatal_error("Missing metadata for llvm.preserve.enum.value intrinsic");
397 report_fatal_error("Incorrect flag for llvm.bpf.preserve.enum.value intrinsic");
400 else
402 return true;
403 }
404
405 return false;
406}
407
411 if (DimensionIndex > 0)
412 Dimension = getConstant(Call->getArgOperand(DimensionIndex));
413
417 IdxList.push_back(Call->getArgOperand(GEPIndex));
418
420 Call->getArgOperand(0), IdxList,
421 "", Call->getIterator());
422 Call->replaceAllUsesWith(GEP);
423 Call->eraseFromParent();
424}
425
429
433
435 Call->replaceAllUsesWith(Call->getArgOperand(0));
436 Call->eraseFromParent();
437}
438
439bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Function &F) {
440 std::vector<CallInst *> PreserveArrayIndexCalls;
441 std::vector<CallInst *> PreserveUnionIndexCalls;
442 std::vector<CallInst *> PreserveStructIndexCalls;
443 bool Found = false;
444
445 for (auto &BB : F)
446 for (auto &I : BB) {
449 if (!IsPreserveDIAccessIndexCall(Call, CInfo))
450 continue;
451
452 Found = true;
453 if (CInfo.Kind == BPFPreserveArrayAI)
454 PreserveArrayIndexCalls.push_back(Call);
455 else if (CInfo.Kind == BPFPreserveUnionAI)
456 PreserveUnionIndexCalls.push_back(Call);
457 else
458 PreserveStructIndexCalls.push_back(Call);
459 }
460
461
462
463
464
465
466
467
468
469
470
471 for (CallInst *Call : PreserveArrayIndexCalls)
473 for (CallInst *Call : PreserveStructIndexCalls)
475 for (CallInst *Call : PreserveUnionIndexCalls)
477
478 return Found;
479}
480
481
482
483
484bool BPFAbstractMemberAccess::IsValidAIChain(const MDNode *ParentType,
485 uint32_t ParentAI,
486 const MDNode *ChildType) {
487 if (!ChildType)
488 return true;
489
492
493
494
496 return false;
497
498
500 if (PtrTy->getTag() != dwarf::DW_TAG_pointer_type)
501 return false;
503 }
504
505
508 assert(PTy && CTy && "ParentType or ChildType is null or not composite");
509
510 uint32_t PTyTag = PTy->getTag();
511 assert(PTyTag == dwarf::DW_TAG_array_type ||
512 PTyTag == dwarf::DW_TAG_structure_type ||
513 PTyTag == dwarf::DW_TAG_union_type);
514
515 uint32_t CTyTag = CTy->getTag();
516 assert(CTyTag == dwarf::DW_TAG_array_type ||
517 CTyTag == dwarf::DW_TAG_structure_type ||
518 CTyTag == dwarf::DW_TAG_union_type);
519
520
521 if (PTyTag == dwarf::DW_TAG_array_type && PTyTag == CTyTag)
522 return PTy->getBaseType() == CTy->getBaseType();
523
524 DIType *Ty;
525 if (PTyTag == dwarf::DW_TAG_array_type)
526 Ty = PTy->getBaseType();
527 else
529
531}
532
533void BPFAbstractMemberAccess::traceAICall(CallInst *Call,
534 CallInfo &ParentInfo) {
537 if (!Inst)
538 continue;
539
541 traceBitCast(BI, Call, ParentInfo);
543 CallInfo ChildInfo;
544
545 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
546 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
547 ChildInfo.Metadata)) {
548 AIChain[CI] = std::make_pair(Call, ParentInfo);
549 traceAICall(CI, ChildInfo);
550 } else {
551 BaseAICalls[Call] = ParentInfo;
552 }
554 if (GI->hasAllZeroIndices())
555 traceGEP(GI, Call, ParentInfo);
556 else
557 BaseAICalls[Call] = ParentInfo;
558 } else {
559 BaseAICalls[Call] = ParentInfo;
560 }
561 }
562}
563
564void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
565 CallInst *Parent,
566 CallInfo &ParentInfo) {
567 for (User *U : BitCast->users()) {
569 if (!Inst)
570 continue;
571
573 traceBitCast(BI, Parent, ParentInfo);
575 CallInfo ChildInfo;
576 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
577 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
578 ChildInfo.Metadata)) {
579 AIChain[CI] = std::make_pair(Parent, ParentInfo);
580 traceAICall(CI, ChildInfo);
581 } else {
582 BaseAICalls[Parent] = ParentInfo;
583 }
585 if (GI->hasAllZeroIndices())
586 traceGEP(GI, Parent, ParentInfo);
587 else
588 BaseAICalls[Parent] = ParentInfo;
589 } else {
590 BaseAICalls[Parent] = ParentInfo;
591 }
592 }
593}
594
595void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
596 CallInfo &ParentInfo) {
597 for (User *U : GEP->users()) {
599 if (!Inst)
600 continue;
601
603 traceBitCast(BI, Parent, ParentInfo);
605 CallInfo ChildInfo;
606 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
607 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
608 ChildInfo.Metadata)) {
609 AIChain[CI] = std::make_pair(Parent, ParentInfo);
610 traceAICall(CI, ChildInfo);
611 } else {
612 BaseAICalls[Parent] = ParentInfo;
613 }
615 if (GI->hasAllZeroIndices())
616 traceGEP(GI, Parent, ParentInfo);
617 else
618 BaseAICalls[Parent] = ParentInfo;
619 } else {
620 BaseAICalls[Parent] = ParentInfo;
621 }
622 }
623}
624
625void BPFAbstractMemberAccess::collectAICallChains(Function &F) {
626 AIChain.clear();
627 BaseAICalls.clear();
628
629 for (auto &BB : F)
630 for (auto &I : BB) {
631 CallInfo CInfo;
633 if (!IsPreserveDIAccessIndexCall(Call, CInfo) ||
634 AIChain.find(Call) != AIChain.end())
635 continue;
636
637 traceAICall(Call, CInfo);
638 }
639}
640
641
642void BPFAbstractMemberAccess::GetStorageBitRange(DIDerivedType *MemberTy,
643 Align RecordAlignment,
644 uint32_t &StartBitOffset,
645 uint32_t &EndBitOffset) {
646 uint32_t MemberBitSize = MemberTy->getSizeInBits();
648
649 if (RecordAlignment > 8) {
650
651
652 if (MemberBitOffset / 64 != (MemberBitOffset + MemberBitSize) / 64)
653 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
654 "requiring too big alignment");
655 RecordAlignment = Align(8);
656 }
657
658 uint32_t AlignBits = RecordAlignment.value() * 8;
659 if (MemberBitSize > AlignBits)
660 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
661 "bitfield size greater than record alignment");
662
663 StartBitOffset = MemberBitOffset & ~(AlignBits - 1);
664 if ((StartBitOffset + AlignBits) < (MemberBitOffset + MemberBitSize))
665 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
666 "cross alignment boundary");
667 EndBitOffset = StartBitOffset + AlignBits;
668}
669
670uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
671 DICompositeType *CTy,
672 uint32_t AccessIndex,
673 uint32_t PatchImm,
674 MaybeAlign RecordAlignment) {
676 return 1;
677
680 if (Tag == dwarf::DW_TAG_array_type) {
682 PatchImm += AccessIndex * calcArraySize(CTy, 1) *
683 (EltTy->getSizeInBits() >> 3);
684 } else if (Tag == dwarf::DW_TAG_structure_type) {
688 } else {
689 unsigned SBitOffset, NextSBitOffset;
690 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset,
691 NextSBitOffset);
692 PatchImm += SBitOffset >> 3;
693 }
694 }
695 return PatchImm;
696 }
697
699 if (Tag == dwarf::DW_TAG_array_type) {
701 return calcArraySize(CTy, 1) * (EltTy->getSizeInBits() >> 3);
702 } else {
706 return SizeInBits >> 3;
707
708 unsigned SBitOffset, NextSBitOffset;
709 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset,
710 NextSBitOffset);
711 SizeInBits = NextSBitOffset - SBitOffset;
712 if (SizeInBits & (SizeInBits - 1))
713 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info");
714 return SizeInBits >> 3;
715 }
716 }
717
719 const DIType *BaseTy;
720 if (Tag == dwarf::DW_TAG_array_type) {
721
723 report_fatal_error("Invalid array expression for llvm.bpf.preserve.field.info");
725 } else {
728 }
729
730
732 while (!BTy) {
734
735 if (!CompTy || CompTy->getTag() != dwarf::DW_TAG_enumeration_type)
736 report_fatal_error("Invalid field expression for llvm.bpf.preserve.field.info");
739 }
740 uint32_t Encoding = BTy->getEncoding();
741 return (Encoding == dwarf::DW_ATE_signed || Encoding == dwarf::DW_ATE_signed_char);
742 }
743
745
746
747
748
750 DIDerivedType *MemberTy = nullptr;
751 bool IsBitField = false;
752 uint32_t SizeInBits;
753
754 if (Tag == dwarf::DW_TAG_array_type) {
756 SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits();
757 } else {
761 }
762
763 if (!IsBitField) {
764 if (SizeInBits > 64)
765 report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
766 return 64 - SizeInBits;
767 }
768
769 unsigned SBitOffset, NextSBitOffset;
770 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset);
771 if (NextSBitOffset - SBitOffset > 64)
772 report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
773
776 return SBitOffset + 64 - OffsetInBits - SizeInBits;
777 else
778 return OffsetInBits + 64 - NextSBitOffset;
779 }
780
782 DIDerivedType *MemberTy = nullptr;
783 bool IsBitField = false;
784 uint32_t SizeInBits;
785 if (Tag == dwarf::DW_TAG_array_type) {
787 SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits();
788 } else {
792 }
793
794 if (!IsBitField) {
795 if (SizeInBits > 64)
796 report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
797 return 64 - SizeInBits;
798 }
799
800 unsigned SBitOffset, NextSBitOffset;
801 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset);
802 if (NextSBitOffset - SBitOffset > 64)
803 report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
804
805 return 64 - SizeInBits;
806 }
807
808 llvm_unreachable("Unknown llvm.bpf.preserve.field.info info kind");
809}
810
811bool BPFAbstractMemberAccess::HasPreserveFieldInfoCall(CallInfoStack &CallStack) {
812
813 while (CallStack.size()) {
814 auto StackElem = CallStack.top();
815 if (StackElem.second.Kind == BPFPreserveFieldInfoAI)
816 return true;
817 CallStack.pop();
818 }
819 return false;
820}
821
822
823
824
825Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
826 CallInfo &CInfo,
827 std::string &AccessKey,
828 MDNode *&TypeMeta) {
831 CallInfoStack CallStack;
832
833
834 while (Call) {
835 CallStack.push(std::make_pair(Call, CInfo));
836 auto &Chain = AIChain[Call];
837 CInfo = Chain.second;
838 Call = Chain.first;
839 }
840
841
842
843
844
845
846
847
848
849
850
851 uint32_t FirstIndex = 0;
852 uint32_t PatchImm = 0;
854 while (CallStack.size()) {
855 auto StackElem = CallStack.top();
856 Call = StackElem.first;
857 CInfo = StackElem.second;
858
860 Base = CInfo.Base;
861
863 false);
865 if (CInfo.Kind == BPFPreserveUnionAI ||
866 CInfo.Kind == BPFPreserveStructAI) {
867
868
870 TypeMeta = PossibleTypeDef;
871 PatchImm += FirstIndex * (Ty->getSizeInBits() >> 3);
872 break;
873 }
874
875 assert(CInfo.Kind == BPFPreserveArrayAI);
876
877
878 CallStack.pop();
879
880
881 uint64_t AccessIndex = CInfo.AccessIndex;
882
883 DIType *BaseTy = nullptr;
884 bool CheckElemType = false;
886
887 assert(CTy->getTag() == dwarf::DW_TAG_array_type);
888
889
890 FirstIndex += AccessIndex * calcArraySize(CTy, 1);
892 CheckElemType = CTy->getElements().size() == 1;
893 } else {
894
896 assert(DTy->getTag() == dwarf::DW_TAG_pointer_type);
897
900 if (!CTy) {
901 CheckElemType = true;
902 } else if (CTy->getTag() != dwarf::DW_TAG_array_type) {
903 FirstIndex += AccessIndex;
904 CheckElemType = true;
905 } else {
906 FirstIndex += AccessIndex * calcArraySize(CTy, 0);
907 }
908 }
909
910 if (CheckElemType) {
912 if (!CTy) {
913 if (HasPreserveFieldInfoCall(CallStack))
914 report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic");
915 return nullptr;
916 }
917
918 unsigned CTag = CTy->getTag();
919 if (CTag == dwarf::DW_TAG_structure_type || CTag == dwarf::DW_TAG_union_type) {
921 } else {
922 if (HasPreserveFieldInfoCall(CallStack))
923 report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic");
924 return nullptr;
925 }
926 TypeMeta = CTy;
927 PatchImm += FirstIndex * (CTy->getSizeInBits() >> 3);
928 break;
929 }
930 }
932 AccessKey += std::to_string(FirstIndex);
933
934
935
936 while (CallStack.size()) {
937 auto StackElem = CallStack.top();
938 CInfo = StackElem.second;
939 CallStack.pop();
940
941 if (CInfo.Kind == BPFPreserveFieldInfoAI) {
942 InfoKind = CInfo.AccessIndex;
944 PatchImm = 1;
945 break;
946 }
947
948
949
950 if (CallStack.size()) {
951 auto StackElem2 = CallStack.top();
952 CallInfo CInfo2 = StackElem2.second;
953 if (CInfo2.Kind == BPFPreserveFieldInfoAI) {
954 InfoKind = CInfo2.AccessIndex;
955 assert(CallStack.size() == 1);
956 }
957 }
958
959
960 uint64_t AccessIndex = CInfo.AccessIndex;
961 AccessKey += ":" + std::to_string(AccessIndex);
962
963 MDNode *MDN = CInfo.Metadata;
964
966 PatchImm = GetFieldInfo(InfoKind, CTy, AccessIndex, PatchImm,
967 CInfo.RecordAlignment);
968 }
969
970
971
972
973
974
975
976 AccessKey = "llvm." + TypeName + ":" + std::to_string(InfoKind) + ":" +
977 std::to_string(PatchImm) + "$" + AccessKey;
978
980}
981
982MDNode *BPFAbstractMemberAccess::computeAccessKey(CallInst *Call,
983 CallInfo &CInfo,
984 std::string &AccessKey,
985 bool &IsInt32Ret) {
988
989 int64_t PatchImm;
990 std::string AccessStr("0");
993 PatchImm = 1;
995
998 } else {
999
1000 IsInt32Ret = false;
1001
1002
1003
1004
1005 const GlobalVariable *GV =
1010 StringRef ValueStr = DA->getAsString();
1011
1012
1014 StringRef EnumeratorStr = ValueStr.substr(0, Separator);
1015
1016
1019 assert(CTy->getTag() == dwarf::DW_TAG_enumeration_type);
1020 int EnumIndex = 0;
1021 for (const auto Element : CTy->getElements()) {
1023 if (Enum->getName() == EnumeratorStr) {
1024 AccessStr = std::to_string(EnumIndex);
1025 break;
1026 }
1027 EnumIndex++;
1028 }
1029
1031 StringRef EValueStr = ValueStr.substr(Separator + 1);
1032 PatchImm = std::stoll(std::string(EValueStr));
1033 } else {
1034 PatchImm = 1;
1035 }
1036 }
1037
1038 AccessKey = "llvm." + Ty->getName().str() + ":" +
1039 std::to_string(CInfo.AccessIndex) + std::string(":") +
1040 std::to_string(PatchImm) + std::string("$") + AccessStr;
1041
1042 return Ty;
1043}
1044
1045
1046
1047bool BPFAbstractMemberAccess::transformGEPChain(CallInst *Call,
1048 CallInfo &CInfo) {
1049 std::string AccessKey;
1050 MDNode *TypeMeta;
1052 bool IsInt32Ret;
1053
1054 IsInt32Ret = CInfo.Kind == BPFPreserveFieldInfoAI;
1055 if (CInfo.Kind == BPFPreserveFieldInfoAI && CInfo.Metadata) {
1056 TypeMeta = computeAccessKey(Call, CInfo, AccessKey, IsInt32Ret);
1057 } else {
1058 Base = computeBaseAndAccessKey(Call, CInfo, AccessKey, TypeMeta);
1060 return false;
1061 }
1062
1064 GlobalVariable *GV;
1065
1066 if (GEPGlobals.find(AccessKey) == GEPGlobals.end()) {
1067 IntegerType *VarType;
1068 if (IsInt32Ret)
1069 VarType = Type::getInt32Ty(BB->getContext());
1070 else
1071 VarType = Type::getInt64Ty(BB->getContext());
1072
1073 GV = new GlobalVariable(*M, VarType, false, GlobalVariable::ExternalLinkage,
1074 nullptr, AccessKey);
1076 GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
1077 GEPGlobals[AccessKey] = GV;
1078 } else {
1079 GV = GEPGlobals[AccessKey];
1080 }
1081
1082 if (CInfo.Kind == BPFPreserveFieldInfoAI) {
1083
1084 LoadInst *LDInst;
1085 if (IsInt32Ret)
1086 LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "",
1088 else
1089 LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "",
1091
1096 return true;
1097 }
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108 auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "",
1110
1111
1113 LDInst);
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1162
1163 return true;
1164}
1165
1166bool BPFAbstractMemberAccess::doTransformation(Function &F) {
1167 bool Transformed = false;
1168
1169
1170
1171
1172 collectAICallChains(F);
1173
1174 for (auto &C : BaseAICalls)
1175 Transformed = transformGEPChain(C.first, C.second) || Transformed;
1176
1177 return removePreserveAccessIndexIntrinsic(F) || Transformed;
1178}
1179
1180PreservedAnalyses
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void replaceWithGEP(CallInst *Call, uint32_t DimensionIndex, uint32_t GEPIndex)
Definition BPFAbstractMemberAccess.cpp:408
static uint64_t getConstant(const Value *IndexValue)
Definition BPFAbstractMemberAccess.cpp:318
static Type * getBaseElementType(const CallInst *Call)
Definition BPFAbstractMemberAccess.cpp:313
static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim)
Definition BPFAbstractMemberAccess.cpp:298
static bool SkipDIDerivedTag(unsigned Tag, bool skipTypedef)
Definition BPFAbstractMemberAccess.cpp:269
static DIType * stripQualifiers(DIType *Ty, bool skipTypedef=true)
Definition BPFAbstractMemberAccess.cpp:280
This file contains the layout of .BTF and .BTF.ext ELF sections.
This file contains constants used for implementing Dwarf debug support.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
Machine Check Debug Module
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
The Input class is used to parse a yaml document into in-memory structs and vectors.
uint64_t getZExtValue() const
Get zero extended value.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition BPFAbstractMemberAccess.cpp:1181
LLVM Basic Block Representation.
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
DINodeArray getElements() const
DIType * getBaseType() const
LLVM_ABI dwarf::Tag getTag() const
LLVM_ABI BoundType getCount() const
uint64_t getOffsetInBits() const
StringRef getName() const
uint64_t getSizeInBits() const
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static GetElementPtrInst * CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Create an "inbounds" getelementptr.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
void addAttribute(Attribute::AttrKind Kind)
Add attribute to this global.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
A Module instance is used to store all the information related to an LLVM module.
iterator_range< debug_compile_units_iterator > debug_compile_units() const
Return an iterator for all DICompileUnits listed in this Module's llvm.dbg.cu named metadata node and...
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
empty - Check if the string is empty.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
const Triple & getTargetTriple() const
ArchType getArch() const
Get the parsed architecture type of this triple.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM Value Representation.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
auto dyn_cast_or_null(const Y &Val)
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)
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.