1 //===------ BPFAbstractMemberAccess.cpp - Abstracting Member Accesses -----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This pass abstracted struct/union member accesses in order to support 10 // compile-once run-everywhere (CO-RE). The CO-RE intends to compile the program 11 // which can run on different kernels. In particular, if bpf program tries to 12 // access a particular kernel data structure member, the details of the 13 // intermediate member access will be remembered so bpf loader can do 14 // necessary adjustment right before program loading. 15 // 16 // For example, 17 // 18 // struct s { 19 // int a; 20 // int b; 21 // }; 22 // struct t { 23 // struct s c; 24 // int d; 25 // }; 26 // struct t e; 27 // 28 // For the member access e.c.b, the compiler will generate code 29 // &e + 4 30 // 31 // The compile-once run-everywhere instead generates the following code 32 // r = 4 33 // &e + r 34 // The "4" in "r = 4" can be changed based on a particular kernel version. 35 // For example, on a particular kernel version, if struct s is changed to 36 // 37 // struct s { 38 // int new_field; 39 // int a; 40 // int b; 41 // } 42 // 43 // By repeating the member access on the host, the bpf loader can 44 // adjust "r = 4" as "r = 8". 45 // 46 // This feature relies on the following three intrinsic calls: 47 // addr = preserve_array_access_index(base, dimension, index) 48 // addr = preserve_union_access_index(base, di_index) 49 // !llvm.preserve.access.index <union_ditype> 50 // addr = preserve_struct_access_index(base, gep_index, di_index) 51 // !llvm.preserve.access.index <struct_ditype> 52 // 53 // Bitfield member access needs special attention. User cannot take the 54 // address of a bitfield acceess. To facilitate kernel verifier 55 // for easy bitfield code optimization, a new clang intrinsic is introduced: 56 // uint32_t __builtin_preserve_field_info(member_access, info_kind) 57 // In IR, a chain with two (or more) intrinsic calls will be generated: 58 // ... 59 // addr = preserve_struct_access_index(base, 1, 1) !struct s 60 // uint32_t result = bpf_preserve_field_info(addr, info_kind) 61 // 62 // Suppose the info_kind is FIELD_SIGNEDNESS, 63 // The above two IR intrinsics will be replaced with 64 // a relocatable insn: 65 // signness = /* signness of member_access */ 66 // and signness can be changed by bpf loader based on the 67 // types on the host. 68 // 69 // User can also test whether a field exists or not with 70 // uint32_t result = bpf_preserve_field_info(member_access, FIELD_EXISTENCE) 71 // The field will be always available (result = 1) during initial 72 // compilation, but bpf loader can patch with the correct value 73 // on the target host where the member_access may or may not be available 74 // 75 //===----------------------------------------------------------------------===// 76 77 #include "BPF.h" 78 #include "BPFCORE.h" 79 #include "BPFTargetMachine.h" 80 #include "llvm/BinaryFormat/Dwarf.h" 81 #include "llvm/IR/DebugInfoMetadata.h" 82 #include "llvm/IR/GlobalVariable.h" 83 #include "llvm/IR/Instruction.h" 84 #include "llvm/IR/Instructions.h" 85 #include "llvm/IR/IntrinsicsBPF.h" 86 #include "llvm/IR/Module.h" 87 #include "llvm/IR/PassManager.h" 88 #include "llvm/IR/Type.h" 89 #include "llvm/IR/User.h" 90 #include "llvm/IR/Value.h" 91 #include "llvm/Pass.h" 92 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 93 #include <stack> 94 95 #define DEBUG_TYPE "bpf-abstract-member-access" 96 97 namespace llvm { 98 constexpr StringRef BPFCoreSharedInfo::AmaAttr; 99 uint32_t BPFCoreSharedInfo::SeqNum; 100 101 Instruction *BPFCoreSharedInfo::insertPassThrough(Module *M, BasicBlock *BB, 102 Instruction *Input, 103 Instruction *Before) { 104 Function *Fn = Intrinsic::getDeclaration( 105 M, Intrinsic::bpf_passthrough, {Input->getType(), Input->getType()}); 106 Constant *SeqNumVal = ConstantInt::get(Type::getInt32Ty(BB->getContext()), 107 BPFCoreSharedInfo::SeqNum++); 108 109 auto *NewInst = CallInst::Create(Fn, {SeqNumVal, Input}); 110 BB->getInstList().insert(Before->getIterator(), NewInst); 111 return NewInst; 112 } 113 } // namespace llvm 114 115 using namespace llvm; 116 117 namespace { 118 class BPFAbstractMemberAccess final { 119 public: 120 BPFAbstractMemberAccess(BPFTargetMachine *TM) : TM(TM) {} 121 122 bool run(Function &F); 123 124 struct CallInfo { 125 uint32_t Kind; 126 uint32_t AccessIndex; 127 MaybeAlign RecordAlignment; 128 MDNode *Metadata; 129 Value *Base; 130 }; 131 typedef std::stack<std::pair<CallInst *, CallInfo>> CallInfoStack; 132 133 private: 134 enum : uint32_t { 135 BPFPreserveArrayAI = 1, 136 BPFPreserveUnionAI = 2, 137 BPFPreserveStructAI = 3, 138 BPFPreserveFieldInfoAI = 4, 139 }; 140 141 TargetMachine *TM; 142 const DataLayout *DL = nullptr; 143 Module *M = nullptr; 144 145 static std::map<std::string, GlobalVariable *> GEPGlobals; 146 // A map to link preserve_*_access_index intrinsic calls. 147 std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain; 148 // A map to hold all the base preserve_*_access_index intrinsic calls. 149 // The base call is not an input of any other preserve_* 150 // intrinsics. 151 std::map<CallInst *, CallInfo> BaseAICalls; 152 153 bool doTransformation(Function &F); 154 155 void traceAICall(CallInst *Call, CallInfo &ParentInfo); 156 void traceBitCast(BitCastInst *BitCast, CallInst *Parent, 157 CallInfo &ParentInfo); 158 void traceGEP(GetElementPtrInst *GEP, CallInst *Parent, 159 CallInfo &ParentInfo); 160 void collectAICallChains(Function &F); 161 162 bool IsPreserveDIAccessIndexCall(const CallInst *Call, CallInfo &Cinfo); 163 bool IsValidAIChain(const MDNode *ParentMeta, uint32_t ParentAI, 164 const MDNode *ChildMeta); 165 bool removePreserveAccessIndexIntrinsic(Function &F); 166 void replaceWithGEP(std::vector<CallInst *> &CallList, 167 uint32_t NumOfZerosIndex, uint32_t DIIndex); 168 bool HasPreserveFieldInfoCall(CallInfoStack &CallStack); 169 void GetStorageBitRange(DIDerivedType *MemberTy, Align RecordAlignment, 170 uint32_t &StartBitOffset, uint32_t &EndBitOffset); 171 uint32_t GetFieldInfo(uint32_t InfoKind, DICompositeType *CTy, 172 uint32_t AccessIndex, uint32_t PatchImm, 173 MaybeAlign RecordAlignment); 174 175 Value *computeBaseAndAccessKey(CallInst *Call, CallInfo &CInfo, 176 std::string &AccessKey, MDNode *&BaseMeta); 177 MDNode *computeAccessKey(CallInst *Call, CallInfo &CInfo, 178 std::string &AccessKey, bool &IsInt32Ret); 179 uint64_t getConstant(const Value *IndexValue); 180 bool transformGEPChain(CallInst *Call, CallInfo &CInfo); 181 }; 182 183 std::map<std::string, GlobalVariable *> BPFAbstractMemberAccess::GEPGlobals; 184 185 class BPFAbstractMemberAccessLegacyPass final : public FunctionPass { 186 BPFTargetMachine *TM; 187 188 bool runOnFunction(Function &F) override { 189 return BPFAbstractMemberAccess(TM).run(F); 190 } 191 192 public: 193 static char ID; 194 195 // Add optional BPFTargetMachine parameter so that BPF backend can add the 196 // phase with target machine to find out the endianness. The default 197 // constructor (without parameters) is used by the pass manager for managing 198 // purposes. 199 BPFAbstractMemberAccessLegacyPass(BPFTargetMachine *TM = nullptr) 200 : FunctionPass(ID), TM(TM) {} 201 }; 202 203 } // End anonymous namespace 204 205 char BPFAbstractMemberAccessLegacyPass::ID = 0; 206 INITIALIZE_PASS(BPFAbstractMemberAccessLegacyPass, DEBUG_TYPE, 207 "BPF Abstract Member Access", false, false) 208 209 FunctionPass *llvm::createBPFAbstractMemberAccess(BPFTargetMachine *TM) { 210 return new BPFAbstractMemberAccessLegacyPass(TM); 211 } 212 213 bool BPFAbstractMemberAccess::run(Function &F) { 214 LLVM_DEBUG(dbgs() << "********** Abstract Member Accesses **********\n"); 215 216 M = F.getParent(); 217 if (!M) 218 return false; 219 220 // Bail out if no debug info. 221 if (M->debug_compile_units().empty()) 222 return false; 223 224 DL = &M->getDataLayout(); 225 return doTransformation(F); 226 } 227 228 static bool SkipDIDerivedTag(unsigned Tag, bool skipTypedef) { 229 if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && 230 Tag != dwarf::DW_TAG_volatile_type && 231 Tag != dwarf::DW_TAG_restrict_type && 232 Tag != dwarf::DW_TAG_member) 233 return false; 234 if (Tag == dwarf::DW_TAG_typedef && !skipTypedef) 235 return false; 236 return true; 237 } 238 239 static DIType * stripQualifiers(DIType *Ty, bool skipTypedef = true) { 240 while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 241 if (!SkipDIDerivedTag(DTy->getTag(), skipTypedef)) 242 break; 243 Ty = DTy->getBaseType(); 244 } 245 return Ty; 246 } 247 248 static const DIType * stripQualifiers(const DIType *Ty) { 249 while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 250 if (!SkipDIDerivedTag(DTy->getTag(), true)) 251 break; 252 Ty = DTy->getBaseType(); 253 } 254 return Ty; 255 } 256 257 static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim) { 258 DINodeArray Elements = CTy->getElements(); 259 uint32_t DimSize = 1; 260 for (uint32_t I = StartDim; I < Elements.size(); ++I) { 261 if (auto *Element = dyn_cast_or_null<DINode>(Elements[I])) 262 if (Element->getTag() == dwarf::DW_TAG_subrange_type) { 263 const DISubrange *SR = cast<DISubrange>(Element); 264 auto *CI = SR->getCount().dyn_cast<ConstantInt *>(); 265 DimSize *= CI->getSExtValue(); 266 } 267 } 268 269 return DimSize; 270 } 271 272 static Type *getBaseElementType(const CallInst *Call) { 273 // Element type is stored in an elementtype() attribute on the first param. 274 return Call->getParamElementType(0); 275 } 276 277 /// Check whether a call is a preserve_*_access_index intrinsic call or not. 278 bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call, 279 CallInfo &CInfo) { 280 if (!Call) 281 return false; 282 283 const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); 284 if (!GV) 285 return false; 286 if (GV->getName().startswith("llvm.preserve.array.access.index")) { 287 CInfo.Kind = BPFPreserveArrayAI; 288 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 289 if (!CInfo.Metadata) 290 report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic"); 291 CInfo.AccessIndex = getConstant(Call->getArgOperand(2)); 292 CInfo.Base = Call->getArgOperand(0); 293 CInfo.RecordAlignment = DL->getABITypeAlign(getBaseElementType(Call)); 294 return true; 295 } 296 if (GV->getName().startswith("llvm.preserve.union.access.index")) { 297 CInfo.Kind = BPFPreserveUnionAI; 298 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 299 if (!CInfo.Metadata) 300 report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic"); 301 CInfo.AccessIndex = getConstant(Call->getArgOperand(1)); 302 CInfo.Base = Call->getArgOperand(0); 303 return true; 304 } 305 if (GV->getName().startswith("llvm.preserve.struct.access.index")) { 306 CInfo.Kind = BPFPreserveStructAI; 307 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 308 if (!CInfo.Metadata) 309 report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic"); 310 CInfo.AccessIndex = getConstant(Call->getArgOperand(2)); 311 CInfo.Base = Call->getArgOperand(0); 312 CInfo.RecordAlignment = DL->getABITypeAlign(getBaseElementType(Call)); 313 return true; 314 } 315 if (GV->getName().startswith("llvm.bpf.preserve.field.info")) { 316 CInfo.Kind = BPFPreserveFieldInfoAI; 317 CInfo.Metadata = nullptr; 318 // Check validity of info_kind as clang did not check this. 319 uint64_t InfoKind = getConstant(Call->getArgOperand(1)); 320 if (InfoKind >= BPFCoreSharedInfo::MAX_FIELD_RELOC_KIND) 321 report_fatal_error("Incorrect info_kind for llvm.bpf.preserve.field.info intrinsic"); 322 CInfo.AccessIndex = InfoKind; 323 return true; 324 } 325 if (GV->getName().startswith("llvm.bpf.preserve.type.info")) { 326 CInfo.Kind = BPFPreserveFieldInfoAI; 327 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 328 if (!CInfo.Metadata) 329 report_fatal_error("Missing metadata for llvm.preserve.type.info intrinsic"); 330 uint64_t Flag = getConstant(Call->getArgOperand(1)); 331 if (Flag >= BPFCoreSharedInfo::MAX_PRESERVE_TYPE_INFO_FLAG) 332 report_fatal_error("Incorrect flag for llvm.bpf.preserve.type.info intrinsic"); 333 if (Flag == BPFCoreSharedInfo::PRESERVE_TYPE_INFO_EXISTENCE) 334 CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_EXISTENCE; 335 else 336 CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_SIZE; 337 return true; 338 } 339 if (GV->getName().startswith("llvm.bpf.preserve.enum.value")) { 340 CInfo.Kind = BPFPreserveFieldInfoAI; 341 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 342 if (!CInfo.Metadata) 343 report_fatal_error("Missing metadata for llvm.preserve.enum.value intrinsic"); 344 uint64_t Flag = getConstant(Call->getArgOperand(2)); 345 if (Flag >= BPFCoreSharedInfo::MAX_PRESERVE_ENUM_VALUE_FLAG) 346 report_fatal_error("Incorrect flag for llvm.bpf.preserve.enum.value intrinsic"); 347 if (Flag == BPFCoreSharedInfo::PRESERVE_ENUM_VALUE_EXISTENCE) 348 CInfo.AccessIndex = BPFCoreSharedInfo::ENUM_VALUE_EXISTENCE; 349 else 350 CInfo.AccessIndex = BPFCoreSharedInfo::ENUM_VALUE; 351 return true; 352 } 353 354 return false; 355 } 356 357 void BPFAbstractMemberAccess::replaceWithGEP(std::vector<CallInst *> &CallList, 358 uint32_t DimensionIndex, 359 uint32_t GEPIndex) { 360 for (auto Call : CallList) { 361 uint32_t Dimension = 1; 362 if (DimensionIndex > 0) 363 Dimension = getConstant(Call->getArgOperand(DimensionIndex)); 364 365 Constant *Zero = 366 ConstantInt::get(Type::getInt32Ty(Call->getParent()->getContext()), 0); 367 SmallVector<Value *, 4> IdxList; 368 for (unsigned I = 0; I < Dimension; ++I) 369 IdxList.push_back(Zero); 370 IdxList.push_back(Call->getArgOperand(GEPIndex)); 371 372 auto *GEP = GetElementPtrInst::CreateInBounds( 373 getBaseElementType(Call), Call->getArgOperand(0), IdxList, "", Call); 374 Call->replaceAllUsesWith(GEP); 375 Call->eraseFromParent(); 376 } 377 } 378 379 bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Function &F) { 380 std::vector<CallInst *> PreserveArrayIndexCalls; 381 std::vector<CallInst *> PreserveUnionIndexCalls; 382 std::vector<CallInst *> PreserveStructIndexCalls; 383 bool Found = false; 384 385 for (auto &BB : F) 386 for (auto &I : BB) { 387 auto *Call = dyn_cast<CallInst>(&I); 388 CallInfo CInfo; 389 if (!IsPreserveDIAccessIndexCall(Call, CInfo)) 390 continue; 391 392 Found = true; 393 if (CInfo.Kind == BPFPreserveArrayAI) 394 PreserveArrayIndexCalls.push_back(Call); 395 else if (CInfo.Kind == BPFPreserveUnionAI) 396 PreserveUnionIndexCalls.push_back(Call); 397 else 398 PreserveStructIndexCalls.push_back(Call); 399 } 400 401 // do the following transformation: 402 // . addr = preserve_array_access_index(base, dimension, index) 403 // is transformed to 404 // addr = GEP(base, dimenion's zero's, index) 405 // . addr = preserve_union_access_index(base, di_index) 406 // is transformed to 407 // addr = base, i.e., all usages of "addr" are replaced by "base". 408 // . addr = preserve_struct_access_index(base, gep_index, di_index) 409 // is transformed to 410 // addr = GEP(base, 0, gep_index) 411 replaceWithGEP(PreserveArrayIndexCalls, 1, 2); 412 replaceWithGEP(PreserveStructIndexCalls, 0, 1); 413 for (auto Call : PreserveUnionIndexCalls) { 414 Call->replaceAllUsesWith(Call->getArgOperand(0)); 415 Call->eraseFromParent(); 416 } 417 418 return Found; 419 } 420 421 /// Check whether the access index chain is valid. We check 422 /// here because there may be type casts between two 423 /// access indexes. We want to ensure memory access still valid. 424 bool BPFAbstractMemberAccess::IsValidAIChain(const MDNode *ParentType, 425 uint32_t ParentAI, 426 const MDNode *ChildType) { 427 if (!ChildType) 428 return true; // preserve_field_info, no type comparison needed. 429 430 const DIType *PType = stripQualifiers(cast<DIType>(ParentType)); 431 const DIType *CType = stripQualifiers(cast<DIType>(ChildType)); 432 433 // Child is a derived/pointer type, which is due to type casting. 434 // Pointer type cannot be in the middle of chain. 435 if (isa<DIDerivedType>(CType)) 436 return false; 437 438 // Parent is a pointer type. 439 if (const auto *PtrTy = dyn_cast<DIDerivedType>(PType)) { 440 if (PtrTy->getTag() != dwarf::DW_TAG_pointer_type) 441 return false; 442 return stripQualifiers(PtrTy->getBaseType()) == CType; 443 } 444 445 // Otherwise, struct/union/array types 446 const auto *PTy = dyn_cast<DICompositeType>(PType); 447 const auto *CTy = dyn_cast<DICompositeType>(CType); 448 assert(PTy && CTy && "ParentType or ChildType is null or not composite"); 449 450 uint32_t PTyTag = PTy->getTag(); 451 assert(PTyTag == dwarf::DW_TAG_array_type || 452 PTyTag == dwarf::DW_TAG_structure_type || 453 PTyTag == dwarf::DW_TAG_union_type); 454 455 uint32_t CTyTag = CTy->getTag(); 456 assert(CTyTag == dwarf::DW_TAG_array_type || 457 CTyTag == dwarf::DW_TAG_structure_type || 458 CTyTag == dwarf::DW_TAG_union_type); 459 460 // Multi dimensional arrays, base element should be the same 461 if (PTyTag == dwarf::DW_TAG_array_type && PTyTag == CTyTag) 462 return PTy->getBaseType() == CTy->getBaseType(); 463 464 DIType *Ty; 465 if (PTyTag == dwarf::DW_TAG_array_type) 466 Ty = PTy->getBaseType(); 467 else 468 Ty = dyn_cast<DIType>(PTy->getElements()[ParentAI]); 469 470 return dyn_cast<DICompositeType>(stripQualifiers(Ty)) == CTy; 471 } 472 473 void BPFAbstractMemberAccess::traceAICall(CallInst *Call, 474 CallInfo &ParentInfo) { 475 for (User *U : Call->users()) { 476 Instruction *Inst = dyn_cast<Instruction>(U); 477 if (!Inst) 478 continue; 479 480 if (auto *BI = dyn_cast<BitCastInst>(Inst)) { 481 traceBitCast(BI, Call, ParentInfo); 482 } else if (auto *CI = dyn_cast<CallInst>(Inst)) { 483 CallInfo ChildInfo; 484 485 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) && 486 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex, 487 ChildInfo.Metadata)) { 488 AIChain[CI] = std::make_pair(Call, ParentInfo); 489 traceAICall(CI, ChildInfo); 490 } else { 491 BaseAICalls[Call] = ParentInfo; 492 } 493 } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) { 494 if (GI->hasAllZeroIndices()) 495 traceGEP(GI, Call, ParentInfo); 496 else 497 BaseAICalls[Call] = ParentInfo; 498 } else { 499 BaseAICalls[Call] = ParentInfo; 500 } 501 } 502 } 503 504 void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast, 505 CallInst *Parent, 506 CallInfo &ParentInfo) { 507 for (User *U : BitCast->users()) { 508 Instruction *Inst = dyn_cast<Instruction>(U); 509 if (!Inst) 510 continue; 511 512 if (auto *BI = dyn_cast<BitCastInst>(Inst)) { 513 traceBitCast(BI, Parent, ParentInfo); 514 } else if (auto *CI = dyn_cast<CallInst>(Inst)) { 515 CallInfo ChildInfo; 516 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) && 517 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex, 518 ChildInfo.Metadata)) { 519 AIChain[CI] = std::make_pair(Parent, ParentInfo); 520 traceAICall(CI, ChildInfo); 521 } else { 522 BaseAICalls[Parent] = ParentInfo; 523 } 524 } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) { 525 if (GI->hasAllZeroIndices()) 526 traceGEP(GI, Parent, ParentInfo); 527 else 528 BaseAICalls[Parent] = ParentInfo; 529 } else { 530 BaseAICalls[Parent] = ParentInfo; 531 } 532 } 533 } 534 535 void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent, 536 CallInfo &ParentInfo) { 537 for (User *U : GEP->users()) { 538 Instruction *Inst = dyn_cast<Instruction>(U); 539 if (!Inst) 540 continue; 541 542 if (auto *BI = dyn_cast<BitCastInst>(Inst)) { 543 traceBitCast(BI, Parent, ParentInfo); 544 } else if (auto *CI = dyn_cast<CallInst>(Inst)) { 545 CallInfo ChildInfo; 546 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) && 547 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex, 548 ChildInfo.Metadata)) { 549 AIChain[CI] = std::make_pair(Parent, ParentInfo); 550 traceAICall(CI, ChildInfo); 551 } else { 552 BaseAICalls[Parent] = ParentInfo; 553 } 554 } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) { 555 if (GI->hasAllZeroIndices()) 556 traceGEP(GI, Parent, ParentInfo); 557 else 558 BaseAICalls[Parent] = ParentInfo; 559 } else { 560 BaseAICalls[Parent] = ParentInfo; 561 } 562 } 563 } 564 565 void BPFAbstractMemberAccess::collectAICallChains(Function &F) { 566 AIChain.clear(); 567 BaseAICalls.clear(); 568 569 for (auto &BB : F) 570 for (auto &I : BB) { 571 CallInfo CInfo; 572 auto *Call = dyn_cast<CallInst>(&I); 573 if (!IsPreserveDIAccessIndexCall(Call, CInfo) || 574 AIChain.find(Call) != AIChain.end()) 575 continue; 576 577 traceAICall(Call, CInfo); 578 } 579 } 580 581 uint64_t BPFAbstractMemberAccess::getConstant(const Value *IndexValue) { 582 const ConstantInt *CV = dyn_cast<ConstantInt>(IndexValue); 583 assert(CV); 584 return CV->getValue().getZExtValue(); 585 } 586 587 /// Get the start and the end of storage offset for \p MemberTy. 588 void BPFAbstractMemberAccess::GetStorageBitRange(DIDerivedType *MemberTy, 589 Align RecordAlignment, 590 uint32_t &StartBitOffset, 591 uint32_t &EndBitOffset) { 592 uint32_t MemberBitSize = MemberTy->getSizeInBits(); 593 uint32_t MemberBitOffset = MemberTy->getOffsetInBits(); 594 595 if (RecordAlignment > 8) { 596 // If the Bits are within an aligned 8-byte, set the RecordAlignment 597 // to 8, other report the fatal error. 598 if (MemberBitOffset / 64 != (MemberBitOffset + MemberBitSize) / 64) 599 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, " 600 "requiring too big alignment"); 601 RecordAlignment = Align(8); 602 } 603 604 uint32_t AlignBits = RecordAlignment.value() * 8; 605 if (MemberBitSize > AlignBits) 606 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, " 607 "bitfield size greater than record alignment"); 608 609 StartBitOffset = MemberBitOffset & ~(AlignBits - 1); 610 if ((StartBitOffset + AlignBits) < (MemberBitOffset + MemberBitSize)) 611 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, " 612 "cross alignment boundary"); 613 EndBitOffset = StartBitOffset + AlignBits; 614 } 615 616 uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind, 617 DICompositeType *CTy, 618 uint32_t AccessIndex, 619 uint32_t PatchImm, 620 MaybeAlign RecordAlignment) { 621 if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE) 622 return 1; 623 624 uint32_t Tag = CTy->getTag(); 625 if (InfoKind == BPFCoreSharedInfo::FIELD_BYTE_OFFSET) { 626 if (Tag == dwarf::DW_TAG_array_type) { 627 auto *EltTy = stripQualifiers(CTy->getBaseType()); 628 PatchImm += AccessIndex * calcArraySize(CTy, 1) * 629 (EltTy->getSizeInBits() >> 3); 630 } else if (Tag == dwarf::DW_TAG_structure_type) { 631 auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 632 if (!MemberTy->isBitField()) { 633 PatchImm += MemberTy->getOffsetInBits() >> 3; 634 } else { 635 unsigned SBitOffset, NextSBitOffset; 636 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, 637 NextSBitOffset); 638 PatchImm += SBitOffset >> 3; 639 } 640 } 641 return PatchImm; 642 } 643 644 if (InfoKind == BPFCoreSharedInfo::FIELD_BYTE_SIZE) { 645 if (Tag == dwarf::DW_TAG_array_type) { 646 auto *EltTy = stripQualifiers(CTy->getBaseType()); 647 return calcArraySize(CTy, 1) * (EltTy->getSizeInBits() >> 3); 648 } else { 649 auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 650 uint32_t SizeInBits = MemberTy->getSizeInBits(); 651 if (!MemberTy->isBitField()) 652 return SizeInBits >> 3; 653 654 unsigned SBitOffset, NextSBitOffset; 655 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, 656 NextSBitOffset); 657 SizeInBits = NextSBitOffset - SBitOffset; 658 if (SizeInBits & (SizeInBits - 1)) 659 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info"); 660 return SizeInBits >> 3; 661 } 662 } 663 664 if (InfoKind == BPFCoreSharedInfo::FIELD_SIGNEDNESS) { 665 const DIType *BaseTy; 666 if (Tag == dwarf::DW_TAG_array_type) { 667 // Signedness only checked when final array elements are accessed. 668 if (CTy->getElements().size() != 1) 669 report_fatal_error("Invalid array expression for llvm.bpf.preserve.field.info"); 670 BaseTy = stripQualifiers(CTy->getBaseType()); 671 } else { 672 auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 673 BaseTy = stripQualifiers(MemberTy->getBaseType()); 674 } 675 676 // Only basic types and enum types have signedness. 677 const auto *BTy = dyn_cast<DIBasicType>(BaseTy); 678 while (!BTy) { 679 const auto *CompTy = dyn_cast<DICompositeType>(BaseTy); 680 // Report an error if the field expression does not have signedness. 681 if (!CompTy || CompTy->getTag() != dwarf::DW_TAG_enumeration_type) 682 report_fatal_error("Invalid field expression for llvm.bpf.preserve.field.info"); 683 BaseTy = stripQualifiers(CompTy->getBaseType()); 684 BTy = dyn_cast<DIBasicType>(BaseTy); 685 } 686 uint32_t Encoding = BTy->getEncoding(); 687 return (Encoding == dwarf::DW_ATE_signed || Encoding == dwarf::DW_ATE_signed_char); 688 } 689 690 if (InfoKind == BPFCoreSharedInfo::FIELD_LSHIFT_U64) { 691 // The value is loaded into a value with FIELD_BYTE_SIZE size, 692 // and then zero or sign extended to U64. 693 // FIELD_LSHIFT_U64 and FIELD_RSHIFT_U64 are operations 694 // to extract the original value. 695 const Triple &Triple = TM->getTargetTriple(); 696 DIDerivedType *MemberTy = nullptr; 697 bool IsBitField = false; 698 uint32_t SizeInBits; 699 700 if (Tag == dwarf::DW_TAG_array_type) { 701 auto *EltTy = stripQualifiers(CTy->getBaseType()); 702 SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits(); 703 } else { 704 MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 705 SizeInBits = MemberTy->getSizeInBits(); 706 IsBitField = MemberTy->isBitField(); 707 } 708 709 if (!IsBitField) { 710 if (SizeInBits > 64) 711 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 712 return 64 - SizeInBits; 713 } 714 715 unsigned SBitOffset, NextSBitOffset; 716 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset); 717 if (NextSBitOffset - SBitOffset > 64) 718 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 719 720 unsigned OffsetInBits = MemberTy->getOffsetInBits(); 721 if (Triple.getArch() == Triple::bpfel) 722 return SBitOffset + 64 - OffsetInBits - SizeInBits; 723 else 724 return OffsetInBits + 64 - NextSBitOffset; 725 } 726 727 if (InfoKind == BPFCoreSharedInfo::FIELD_RSHIFT_U64) { 728 DIDerivedType *MemberTy = nullptr; 729 bool IsBitField = false; 730 uint32_t SizeInBits; 731 if (Tag == dwarf::DW_TAG_array_type) { 732 auto *EltTy = stripQualifiers(CTy->getBaseType()); 733 SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits(); 734 } else { 735 MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 736 SizeInBits = MemberTy->getSizeInBits(); 737 IsBitField = MemberTy->isBitField(); 738 } 739 740 if (!IsBitField) { 741 if (SizeInBits > 64) 742 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 743 return 64 - SizeInBits; 744 } 745 746 unsigned SBitOffset, NextSBitOffset; 747 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset); 748 if (NextSBitOffset - SBitOffset > 64) 749 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 750 751 return 64 - SizeInBits; 752 } 753 754 llvm_unreachable("Unknown llvm.bpf.preserve.field.info info kind"); 755 } 756 757 bool BPFAbstractMemberAccess::HasPreserveFieldInfoCall(CallInfoStack &CallStack) { 758 // This is called in error return path, no need to maintain CallStack. 759 while (CallStack.size()) { 760 auto StackElem = CallStack.top(); 761 if (StackElem.second.Kind == BPFPreserveFieldInfoAI) 762 return true; 763 CallStack.pop(); 764 } 765 return false; 766 } 767 768 /// Compute the base of the whole preserve_* intrinsics chains, i.e., the base 769 /// pointer of the first preserve_*_access_index call, and construct the access 770 /// string, which will be the name of a global variable. 771 Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, 772 CallInfo &CInfo, 773 std::string &AccessKey, 774 MDNode *&TypeMeta) { 775 Value *Base = nullptr; 776 std::string TypeName; 777 CallInfoStack CallStack; 778 779 // Put the access chain into a stack with the top as the head of the chain. 780 while (Call) { 781 CallStack.push(std::make_pair(Call, CInfo)); 782 CInfo = AIChain[Call].second; 783 Call = AIChain[Call].first; 784 } 785 786 // The access offset from the base of the head of chain is also 787 // calculated here as all debuginfo types are available. 788 789 // Get type name and calculate the first index. 790 // We only want to get type name from typedef, structure or union. 791 // If user wants a relocation like 792 // int *p; ... __builtin_preserve_access_index(&p[4]) ... 793 // or 794 // int a[10][20]; ... __builtin_preserve_access_index(&a[2][3]) ... 795 // we will skip them. 796 uint32_t FirstIndex = 0; 797 uint32_t PatchImm = 0; // AccessOffset or the requested field info 798 uint32_t InfoKind = BPFCoreSharedInfo::FIELD_BYTE_OFFSET; 799 while (CallStack.size()) { 800 auto StackElem = CallStack.top(); 801 Call = StackElem.first; 802 CInfo = StackElem.second; 803 804 if (!Base) 805 Base = CInfo.Base; 806 807 DIType *PossibleTypeDef = stripQualifiers(cast<DIType>(CInfo.Metadata), 808 false); 809 DIType *Ty = stripQualifiers(PossibleTypeDef); 810 if (CInfo.Kind == BPFPreserveUnionAI || 811 CInfo.Kind == BPFPreserveStructAI) { 812 // struct or union type. If the typedef is in the metadata, always 813 // use the typedef. 814 TypeName = std::string(PossibleTypeDef->getName()); 815 TypeMeta = PossibleTypeDef; 816 PatchImm += FirstIndex * (Ty->getSizeInBits() >> 3); 817 break; 818 } 819 820 assert(CInfo.Kind == BPFPreserveArrayAI); 821 822 // Array entries will always be consumed for accumulative initial index. 823 CallStack.pop(); 824 825 // BPFPreserveArrayAI 826 uint64_t AccessIndex = CInfo.AccessIndex; 827 828 DIType *BaseTy = nullptr; 829 bool CheckElemType = false; 830 if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) { 831 // array type 832 assert(CTy->getTag() == dwarf::DW_TAG_array_type); 833 834 835 FirstIndex += AccessIndex * calcArraySize(CTy, 1); 836 BaseTy = stripQualifiers(CTy->getBaseType()); 837 CheckElemType = CTy->getElements().size() == 1; 838 } else { 839 // pointer type 840 auto *DTy = cast<DIDerivedType>(Ty); 841 assert(DTy->getTag() == dwarf::DW_TAG_pointer_type); 842 843 BaseTy = stripQualifiers(DTy->getBaseType()); 844 CTy = dyn_cast<DICompositeType>(BaseTy); 845 if (!CTy) { 846 CheckElemType = true; 847 } else if (CTy->getTag() != dwarf::DW_TAG_array_type) { 848 FirstIndex += AccessIndex; 849 CheckElemType = true; 850 } else { 851 FirstIndex += AccessIndex * calcArraySize(CTy, 0); 852 } 853 } 854 855 if (CheckElemType) { 856 auto *CTy = dyn_cast<DICompositeType>(BaseTy); 857 if (!CTy) { 858 if (HasPreserveFieldInfoCall(CallStack)) 859 report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic"); 860 return nullptr; 861 } 862 863 unsigned CTag = CTy->getTag(); 864 if (CTag == dwarf::DW_TAG_structure_type || CTag == dwarf::DW_TAG_union_type) { 865 TypeName = std::string(CTy->getName()); 866 } else { 867 if (HasPreserveFieldInfoCall(CallStack)) 868 report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic"); 869 return nullptr; 870 } 871 TypeMeta = CTy; 872 PatchImm += FirstIndex * (CTy->getSizeInBits() >> 3); 873 break; 874 } 875 } 876 assert(TypeName.size()); 877 AccessKey += std::to_string(FirstIndex); 878 879 // Traverse the rest of access chain to complete offset calculation 880 // and access key construction. 881 while (CallStack.size()) { 882 auto StackElem = CallStack.top(); 883 CInfo = StackElem.second; 884 CallStack.pop(); 885 886 if (CInfo.Kind == BPFPreserveFieldInfoAI) { 887 InfoKind = CInfo.AccessIndex; 888 if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE) 889 PatchImm = 1; 890 break; 891 } 892 893 // If the next Call (the top of the stack) is a BPFPreserveFieldInfoAI, 894 // the action will be extracting field info. 895 if (CallStack.size()) { 896 auto StackElem2 = CallStack.top(); 897 CallInfo CInfo2 = StackElem2.second; 898 if (CInfo2.Kind == BPFPreserveFieldInfoAI) { 899 InfoKind = CInfo2.AccessIndex; 900 assert(CallStack.size() == 1); 901 } 902 } 903 904 // Access Index 905 uint64_t AccessIndex = CInfo.AccessIndex; 906 AccessKey += ":" + std::to_string(AccessIndex); 907 908 MDNode *MDN = CInfo.Metadata; 909 // At this stage, it cannot be pointer type. 910 auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN))); 911 PatchImm = GetFieldInfo(InfoKind, CTy, AccessIndex, PatchImm, 912 CInfo.RecordAlignment); 913 } 914 915 // Access key is the 916 // "llvm." + type name + ":" + reloc type + ":" + patched imm + "$" + 917 // access string, 918 // uniquely identifying one relocation. 919 // The prefix "llvm." indicates this is a temporary global, which should 920 // not be emitted to ELF file. 921 AccessKey = "llvm." + TypeName + ":" + std::to_string(InfoKind) + ":" + 922 std::to_string(PatchImm) + "$" + AccessKey; 923 924 return Base; 925 } 926 927 MDNode *BPFAbstractMemberAccess::computeAccessKey(CallInst *Call, 928 CallInfo &CInfo, 929 std::string &AccessKey, 930 bool &IsInt32Ret) { 931 DIType *Ty = stripQualifiers(cast<DIType>(CInfo.Metadata), false); 932 assert(!Ty->getName().empty()); 933 934 int64_t PatchImm; 935 std::string AccessStr("0"); 936 if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_EXISTENCE) { 937 PatchImm = 1; 938 } else if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_SIZE) { 939 // typedef debuginfo type has size 0, get the eventual base type. 940 DIType *BaseTy = stripQualifiers(Ty, true); 941 PatchImm = BaseTy->getSizeInBits() / 8; 942 } else { 943 // ENUM_VALUE_EXISTENCE and ENUM_VALUE 944 IsInt32Ret = false; 945 946 // The argument could be a global variable or a getelementptr with base to 947 // a global variable depending on whether the clang option `opaque-options` 948 // is set or not. 949 const GlobalVariable *GV = 950 cast<GlobalVariable>(Call->getArgOperand(1)->stripPointerCasts()); 951 assert(GV->hasInitializer()); 952 const ConstantDataArray *DA = cast<ConstantDataArray>(GV->getInitializer()); 953 assert(DA->isString()); 954 StringRef ValueStr = DA->getAsString(); 955 956 // ValueStr format: <EnumeratorStr>:<Value> 957 size_t Separator = ValueStr.find_first_of(':'); 958 StringRef EnumeratorStr = ValueStr.substr(0, Separator); 959 960 // Find enumerator index in the debuginfo 961 DIType *BaseTy = stripQualifiers(Ty, true); 962 const auto *CTy = cast<DICompositeType>(BaseTy); 963 assert(CTy->getTag() == dwarf::DW_TAG_enumeration_type); 964 int EnumIndex = 0; 965 for (const auto Element : CTy->getElements()) { 966 const auto *Enum = cast<DIEnumerator>(Element); 967 if (Enum->getName() == EnumeratorStr) { 968 AccessStr = std::to_string(EnumIndex); 969 break; 970 } 971 EnumIndex++; 972 } 973 974 if (CInfo.AccessIndex == BPFCoreSharedInfo::ENUM_VALUE) { 975 StringRef EValueStr = ValueStr.substr(Separator + 1); 976 PatchImm = std::stoll(std::string(EValueStr)); 977 } else { 978 PatchImm = 1; 979 } 980 } 981 982 AccessKey = "llvm." + Ty->getName().str() + ":" + 983 std::to_string(CInfo.AccessIndex) + std::string(":") + 984 std::to_string(PatchImm) + std::string("$") + AccessStr; 985 986 return Ty; 987 } 988 989 /// Call/Kind is the base preserve_*_access_index() call. Attempts to do 990 /// transformation to a chain of relocable GEPs. 991 bool BPFAbstractMemberAccess::transformGEPChain(CallInst *Call, 992 CallInfo &CInfo) { 993 std::string AccessKey; 994 MDNode *TypeMeta; 995 Value *Base = nullptr; 996 bool IsInt32Ret; 997 998 IsInt32Ret = CInfo.Kind == BPFPreserveFieldInfoAI; 999 if (CInfo.Kind == BPFPreserveFieldInfoAI && CInfo.Metadata) { 1000 TypeMeta = computeAccessKey(Call, CInfo, AccessKey, IsInt32Ret); 1001 } else { 1002 Base = computeBaseAndAccessKey(Call, CInfo, AccessKey, TypeMeta); 1003 if (!Base) 1004 return false; 1005 } 1006 1007 BasicBlock *BB = Call->getParent(); 1008 GlobalVariable *GV; 1009 1010 if (GEPGlobals.find(AccessKey) == GEPGlobals.end()) { 1011 IntegerType *VarType; 1012 if (IsInt32Ret) 1013 VarType = Type::getInt32Ty(BB->getContext()); // 32bit return value 1014 else 1015 VarType = Type::getInt64Ty(BB->getContext()); // 64bit ptr or enum value 1016 1017 GV = new GlobalVariable(*M, VarType, false, GlobalVariable::ExternalLinkage, 1018 nullptr, AccessKey); 1019 GV->addAttribute(BPFCoreSharedInfo::AmaAttr); 1020 GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta); 1021 GEPGlobals[AccessKey] = GV; 1022 } else { 1023 GV = GEPGlobals[AccessKey]; 1024 } 1025 1026 if (CInfo.Kind == BPFPreserveFieldInfoAI) { 1027 // Load the global variable which represents the returned field info. 1028 LoadInst *LDInst; 1029 if (IsInt32Ret) 1030 LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", Call); 1031 else 1032 LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); 1033 1034 Instruction *PassThroughInst = 1035 BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call); 1036 Call->replaceAllUsesWith(PassThroughInst); 1037 Call->eraseFromParent(); 1038 return true; 1039 } 1040 1041 // For any original GEP Call and Base %2 like 1042 // %4 = bitcast %struct.net_device** %dev1 to i64* 1043 // it is transformed to: 1044 // %6 = load llvm.sk_buff:0:50$0:0:0:2:0 1045 // %7 = bitcast %struct.sk_buff* %2 to i8* 1046 // %8 = getelementptr i8, i8* %7, %6 1047 // %9 = bitcast i8* %8 to i64* 1048 // using %9 instead of %4 1049 // The original Call inst is removed. 1050 1051 // Load the global variable. 1052 auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); 1053 1054 // Generate a BitCast 1055 auto *BCInst = new BitCastInst(Base, Type::getInt8PtrTy(BB->getContext())); 1056 BB->getInstList().insert(Call->getIterator(), BCInst); 1057 1058 // Generate a GetElementPtr 1059 auto *GEP = GetElementPtrInst::Create(Type::getInt8Ty(BB->getContext()), 1060 BCInst, LDInst); 1061 BB->getInstList().insert(Call->getIterator(), GEP); 1062 1063 // Generate a BitCast 1064 auto *BCInst2 = new BitCastInst(GEP, Call->getType()); 1065 BB->getInstList().insert(Call->getIterator(), BCInst2); 1066 1067 // For the following code, 1068 // Block0: 1069 // ... 1070 // if (...) goto Block1 else ... 1071 // Block1: 1072 // %6 = load llvm.sk_buff:0:50$0:0:0:2:0 1073 // %7 = bitcast %struct.sk_buff* %2 to i8* 1074 // %8 = getelementptr i8, i8* %7, %6 1075 // ... 1076 // goto CommonExit 1077 // Block2: 1078 // ... 1079 // if (...) goto Block3 else ... 1080 // Block3: 1081 // %6 = load llvm.bpf_map:0:40$0:0:0:2:0 1082 // %7 = bitcast %struct.sk_buff* %2 to i8* 1083 // %8 = getelementptr i8, i8* %7, %6 1084 // ... 1085 // goto CommonExit 1086 // CommonExit 1087 // SimplifyCFG may generate: 1088 // Block0: 1089 // ... 1090 // if (...) goto Block_Common else ... 1091 // Block2: 1092 // ... 1093 // if (...) goto Block_Common else ... 1094 // Block_Common: 1095 // PHI = [llvm.sk_buff:0:50$0:0:0:2:0, llvm.bpf_map:0:40$0:0:0:2:0] 1096 // %6 = load PHI 1097 // %7 = bitcast %struct.sk_buff* %2 to i8* 1098 // %8 = getelementptr i8, i8* %7, %6 1099 // ... 1100 // goto CommonExit 1101 // For the above code, we cannot perform proper relocation since 1102 // "load PHI" has two possible relocations. 1103 // 1104 // To prevent above tail merging, we use __builtin_bpf_passthrough() 1105 // where one of its parameters is a seq_num. Since two 1106 // __builtin_bpf_passthrough() funcs will always have different seq_num, 1107 // tail merging cannot happen. The __builtin_bpf_passthrough() will be 1108 // removed in the beginning of Target IR passes. 1109 // 1110 // This approach is also used in other places when global var 1111 // representing a relocation is used. 1112 Instruction *PassThroughInst = 1113 BPFCoreSharedInfo::insertPassThrough(M, BB, BCInst2, Call); 1114 Call->replaceAllUsesWith(PassThroughInst); 1115 Call->eraseFromParent(); 1116 1117 return true; 1118 } 1119 1120 bool BPFAbstractMemberAccess::doTransformation(Function &F) { 1121 bool Transformed = false; 1122 1123 // Collect PreserveDIAccessIndex Intrinsic call chains. 1124 // The call chains will be used to generate the access 1125 // patterns similar to GEP. 1126 collectAICallChains(F); 1127 1128 for (auto &C : BaseAICalls) 1129 Transformed = transformGEPChain(C.first, C.second) || Transformed; 1130 1131 return removePreserveAccessIndexIntrinsic(F) || Transformed; 1132 } 1133 1134 PreservedAnalyses 1135 BPFAbstractMemberAccessPass::run(Function &F, FunctionAnalysisManager &AM) { 1136 return BPFAbstractMemberAccess(TM).run(F) ? PreservedAnalyses::none() 1137 : PreservedAnalyses::all(); 1138 } 1139