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

123 bool run(Function &F);

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.