LLVM  10.0.0svn
BPFAbstractMemberAccess.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
54 
55 #include "BPF.h"
56 #include "BPFCORE.h"
57 #include "BPFTargetMachine.h"
59 #include "llvm/IR/GlobalVariable.h"
60 #include "llvm/IR/Instruction.h"
61 #include "llvm/IR/Instructions.h"
62 #include "llvm/IR/Module.h"
63 #include "llvm/IR/Type.h"
64 #include "llvm/IR/User.h"
65 #include "llvm/IR/Value.h"
66 #include "llvm/Pass.h"
68 #include <stack>
69 
70 #define DEBUG_TYPE "bpf-abstract-member-access"
71 
72 namespace llvm {
73 const std::string BPFCoreSharedInfo::AmaAttr = "btf_ama";
75  ".BPF.patchable_externs";
76 } // namespace llvm
77 
78 using namespace llvm;
79 
80 namespace {
81 
82 class BPFAbstractMemberAccess final : public ModulePass {
83  StringRef getPassName() const override {
84  return "BPF Abstract Member Access";
85  }
86 
87  bool runOnModule(Module &M) override;
88 
89 public:
90  static char ID;
91  BPFAbstractMemberAccess() : ModulePass(ID) {}
92 
93 private:
94  enum : uint32_t {
95  BPFPreserveArrayAI = 1,
96  BPFPreserveUnionAI = 2,
97  BPFPreserveStructAI = 3,
98  };
99 
100  std::map<std::string, GlobalVariable *> GEPGlobals;
101  // A map to link preserve_*_access_index instrinsic calls.
102  std::map<CallInst *, std::pair<CallInst *, uint32_t>> AIChain;
103  // A map to hold all the base preserve_*_access_index instrinsic calls.
104  // The base call is not an input of any other preserve_*_access_index
105  // intrinsics.
106  std::map<CallInst *, uint32_t> BaseAICalls;
107 
108  bool doTransformation(Module &M);
109 
110  void traceAICall(CallInst *Call, uint32_t Kind, const MDNode *ParentMeta,
111  uint32_t ParentAI);
112  void traceBitCast(BitCastInst *BitCast, CallInst *Parent, uint32_t Kind,
113  const MDNode *ParentMeta, uint32_t ParentAI);
114  void traceGEP(GetElementPtrInst *GEP, CallInst *Parent, uint32_t Kind,
115  const MDNode *ParentMeta, uint32_t ParentAI);
116  void collectAICallChains(Module &M, Function &F);
117 
118  bool IsPreserveDIAccessIndexCall(const CallInst *Call, uint32_t &Kind,
119  const MDNode *&TypeMeta, uint32_t &AccessIndex);
120  bool IsValidAIChain(const MDNode *ParentMeta, uint32_t ParentAI,
121  const MDNode *ChildMeta);
122  bool removePreserveAccessIndexIntrinsic(Module &M);
123  void replaceWithGEP(std::vector<CallInst *> &CallList,
124  uint32_t NumOfZerosIndex, uint32_t DIIndex);
125 
126  Value *computeBaseAndAccessKey(CallInst *Call, std::string &AccessKey,
127  uint32_t Kind, MDNode *&BaseMeta);
128  bool getAccessIndex(const Value *IndexValue, uint64_t &AccessIndex);
129  bool transformGEPChain(Module &M, CallInst *Call, uint32_t Kind);
130 };
131 } // End anonymous namespace
132 
134 INITIALIZE_PASS(BPFAbstractMemberAccess, DEBUG_TYPE,
135  "abstracting struct/union member accessees", false, false)
136 
138  return new BPFAbstractMemberAccess();
139 }
140 
141 bool BPFAbstractMemberAccess::runOnModule(Module &M) {
142  LLVM_DEBUG(dbgs() << "********** Abstract Member Accesses **********\n");
143 
144  // Bail out if no debug info.
145  if (empty(M.debug_compile_units()))
146  return false;
147 
148  return doTransformation(M);
149 }
150 
151 static bool SkipDIDerivedTag(unsigned Tag) {
152  if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type &&
153  Tag != dwarf::DW_TAG_volatile_type &&
154  Tag != dwarf::DW_TAG_restrict_type &&
155  Tag != dwarf::DW_TAG_member)
156  return false;
157  return true;
158 }
159 
161  while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
162  if (!SkipDIDerivedTag(DTy->getTag()))
163  break;
164  Ty = DTy->getBaseType();
165  }
166  return Ty;
167 }
168 
169 static const DIType * stripQualifiers(const DIType *Ty) {
170  while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
171  if (!SkipDIDerivedTag(DTy->getTag()))
172  break;
173  Ty = DTy->getBaseType();
174  }
175  return Ty;
176 }
177 
178 static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim) {
179  DINodeArray Elements = CTy->getElements();
180  uint32_t DimSize = 1;
181  for (uint32_t I = StartDim; I < Elements.size(); ++I) {
182  if (auto *Element = dyn_cast_or_null<DINode>(Elements[I]))
183  if (Element->getTag() == dwarf::DW_TAG_subrange_type) {
184  const DISubrange *SR = cast<DISubrange>(Element);
185  auto *CI = SR->getCount().dyn_cast<ConstantInt *>();
186  DimSize *= CI->getSExtValue();
187  }
188  }
189 
190  return DimSize;
191 }
192 
193 /// Check whether a call is a preserve_*_access_index intrinsic call or not.
194 bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
195  uint32_t &Kind,
196  const MDNode *&TypeMeta,
197  uint32_t &AccessIndex) {
198  if (!Call)
199  return false;
200 
201  const auto *GV = dyn_cast<GlobalValue>(Call->getCalledValue());
202  if (!GV)
203  return false;
204  if (GV->getName().startswith("llvm.preserve.array.access.index")) {
205  Kind = BPFPreserveArrayAI;
206  TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
207  if (!TypeMeta)
208  report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic");
209  AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
210  ->getZExtValue();
211  return true;
212  }
213  if (GV->getName().startswith("llvm.preserve.union.access.index")) {
214  Kind = BPFPreserveUnionAI;
215  TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
216  if (!TypeMeta)
217  report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic");
218  AccessIndex = cast<ConstantInt>(Call->getArgOperand(1))
219  ->getZExtValue();
220  return true;
221  }
222  if (GV->getName().startswith("llvm.preserve.struct.access.index")) {
223  Kind = BPFPreserveStructAI;
224  TypeMeta = Call->getMetadata(LLVMContext::MD_preserve_access_index);
225  if (!TypeMeta)
226  report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic");
227  AccessIndex = cast<ConstantInt>(Call->getArgOperand(2))
228  ->getZExtValue();
229  return true;
230  }
231 
232  return false;
233 }
234 
235 void BPFAbstractMemberAccess::replaceWithGEP(std::vector<CallInst *> &CallList,
236  uint32_t DimensionIndex,
237  uint32_t GEPIndex) {
238  for (auto Call : CallList) {
239  uint32_t Dimension = 1;
240  if (DimensionIndex > 0)
241  Dimension = cast<ConstantInt>(Call->getArgOperand(DimensionIndex))
242  ->getZExtValue();
243 
244  Constant *Zero =
246  SmallVector<Value *, 4> IdxList;
247  for (unsigned I = 0; I < Dimension; ++I)
248  IdxList.push_back(Zero);
249  IdxList.push_back(Call->getArgOperand(GEPIndex));
250 
252  IdxList, "", Call);
253  Call->replaceAllUsesWith(GEP);
254  Call->eraseFromParent();
255  }
256 }
257 
258 bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) {
259  std::vector<CallInst *> PreserveArrayIndexCalls;
260  std::vector<CallInst *> PreserveUnionIndexCalls;
261  std::vector<CallInst *> PreserveStructIndexCalls;
262  bool Found = false;
263 
264  for (Function &F : M)
265  for (auto &BB : F)
266  for (auto &I : BB) {
267  auto *Call = dyn_cast<CallInst>(&I);
268  uint32_t Kind;
269  const MDNode *TypeMeta;
270  uint32_t AccessIndex;
271  if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex))
272  continue;
273 
274  Found = true;
275  if (Kind == BPFPreserveArrayAI)
276  PreserveArrayIndexCalls.push_back(Call);
277  else if (Kind == BPFPreserveUnionAI)
278  PreserveUnionIndexCalls.push_back(Call);
279  else
280  PreserveStructIndexCalls.push_back(Call);
281  }
282 
283  // do the following transformation:
284  // . addr = preserve_array_access_index(base, dimension, index)
285  // is transformed to
286  // addr = GEP(base, dimenion's zero's, index)
287  // . addr = preserve_union_access_index(base, di_index)
288  // is transformed to
289  // addr = base, i.e., all usages of "addr" are replaced by "base".
290  // . addr = preserve_struct_access_index(base, gep_index, di_index)
291  // is transformed to
292  // addr = GEP(base, 0, gep_index)
293  replaceWithGEP(PreserveArrayIndexCalls, 1, 2);
294  replaceWithGEP(PreserveStructIndexCalls, 0, 1);
295  for (auto Call : PreserveUnionIndexCalls) {
296  Call->replaceAllUsesWith(Call->getArgOperand(0));
297  Call->eraseFromParent();
298  }
299 
300  return Found;
301 }
302 
303 /// Check whether the access index chain is valid. We check
304 /// here because there may be type casts between two
305 /// access indexes. We want to ensure memory access still valid.
306 bool BPFAbstractMemberAccess::IsValidAIChain(const MDNode *ParentType,
307  uint32_t ParentAI,
308  const MDNode *ChildType) {
309  const DIType *PType = stripQualifiers(cast<DIType>(ParentType));
310  const DIType *CType = stripQualifiers(cast<DIType>(ChildType));
311 
312  // Child is a derived/pointer type, which is due to type casting.
313  // Pointer type cannot be in the middle of chain.
314  if (isa<DIDerivedType>(CType))
315  return false;
316 
317  // Parent is a pointer type.
318  if (const auto *PtrTy = dyn_cast<DIDerivedType>(PType)) {
319  if (PtrTy->getTag() != dwarf::DW_TAG_pointer_type)
320  return false;
321  return stripQualifiers(PtrTy->getBaseType()) == CType;
322  }
323 
324  // Otherwise, struct/union/array types
325  const auto *PTy = dyn_cast<DICompositeType>(PType);
326  const auto *CTy = dyn_cast<DICompositeType>(CType);
327  assert(PTy && CTy && "ParentType or ChildType is null or not composite");
328 
329  uint32_t PTyTag = PTy->getTag();
330  assert(PTyTag == dwarf::DW_TAG_array_type ||
331  PTyTag == dwarf::DW_TAG_structure_type ||
332  PTyTag == dwarf::DW_TAG_union_type);
333 
334  uint32_t CTyTag = CTy->getTag();
335  assert(CTyTag == dwarf::DW_TAG_array_type ||
336  CTyTag == dwarf::DW_TAG_structure_type ||
337  CTyTag == dwarf::DW_TAG_union_type);
338 
339  // Multi dimensional arrays, base element should be the same
340  if (PTyTag == dwarf::DW_TAG_array_type && PTyTag == CTyTag)
341  return PTy->getBaseType() == CTy->getBaseType();
342 
343  DIType *Ty;
344  if (PTyTag == dwarf::DW_TAG_array_type)
345  Ty = PTy->getBaseType();
346  else
347  Ty = dyn_cast<DIType>(PTy->getElements()[ParentAI]);
348 
349  return dyn_cast<DICompositeType>(stripQualifiers(Ty)) == CTy;
350 }
351 
352 void BPFAbstractMemberAccess::traceAICall(CallInst *Call, uint32_t Kind,
353  const MDNode *ParentMeta,
354  uint32_t ParentAI) {
355  for (User *U : Call->users()) {
356  Instruction *Inst = dyn_cast<Instruction>(U);
357  if (!Inst)
358  continue;
359 
360  if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
361  traceBitCast(BI, Call, Kind, ParentMeta, ParentAI);
362  } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
363  uint32_t CIKind;
364  const MDNode *ChildMeta;
365  uint32_t ChildAI;
366  if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
367  IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
368  AIChain[CI] = std::make_pair(Call, Kind);
369  traceAICall(CI, CIKind, ChildMeta, ChildAI);
370  } else {
371  BaseAICalls[Call] = Kind;
372  }
373  } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
374  if (GI->hasAllZeroIndices())
375  traceGEP(GI, Call, Kind, ParentMeta, ParentAI);
376  else
377  BaseAICalls[Call] = Kind;
378  }
379  }
380 }
381 
382 void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
383  CallInst *Parent, uint32_t Kind,
384  const MDNode *ParentMeta,
385  uint32_t ParentAI) {
386  for (User *U : BitCast->users()) {
387  Instruction *Inst = dyn_cast<Instruction>(U);
388  if (!Inst)
389  continue;
390 
391  if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
392  traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI);
393  } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
394  uint32_t CIKind;
395  const MDNode *ChildMeta;
396  uint32_t ChildAI;
397  if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
398  IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
399  AIChain[CI] = std::make_pair(Parent, Kind);
400  traceAICall(CI, CIKind, ChildMeta, ChildAI);
401  } else {
402  BaseAICalls[Parent] = Kind;
403  }
404  } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
405  if (GI->hasAllZeroIndices())
406  traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
407  else
408  BaseAICalls[Parent] = Kind;
409  }
410  }
411 }
412 
413 void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
414  uint32_t Kind, const MDNode *ParentMeta,
415  uint32_t ParentAI) {
416  for (User *U : GEP->users()) {
417  Instruction *Inst = dyn_cast<Instruction>(U);
418  if (!Inst)
419  continue;
420 
421  if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
422  traceBitCast(BI, Parent, Kind, ParentMeta, ParentAI);
423  } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
424  uint32_t CIKind;
425  const MDNode *ChildMeta;
426  uint32_t ChildAI;
427  if (IsPreserveDIAccessIndexCall(CI, CIKind, ChildMeta, ChildAI) &&
428  IsValidAIChain(ParentMeta, ParentAI, ChildMeta)) {
429  AIChain[CI] = std::make_pair(Parent, Kind);
430  traceAICall(CI, CIKind, ChildMeta, ChildAI);
431  } else {
432  BaseAICalls[Parent] = Kind;
433  }
434  } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
435  if (GI->hasAllZeroIndices())
436  traceGEP(GI, Parent, Kind, ParentMeta, ParentAI);
437  else
438  BaseAICalls[Parent] = Kind;
439  }
440  }
441 }
442 
443 void BPFAbstractMemberAccess::collectAICallChains(Module &M, Function &F) {
444  AIChain.clear();
445  BaseAICalls.clear();
446 
447  for (auto &BB : F)
448  for (auto &I : BB) {
449  uint32_t Kind;
450  const MDNode *TypeMeta;
451  uint32_t AccessIndex;
452  auto *Call = dyn_cast<CallInst>(&I);
453  if (!IsPreserveDIAccessIndexCall(Call, Kind, TypeMeta, AccessIndex) ||
454  AIChain.find(Call) != AIChain.end())
455  continue;
456 
457  traceAICall(Call, Kind, TypeMeta, AccessIndex);
458  }
459 }
460 
461 /// Get access index from the preserve_*_access_index intrinsic calls.
462 bool BPFAbstractMemberAccess::getAccessIndex(const Value *IndexValue,
463  uint64_t &AccessIndex) {
464  const ConstantInt *CV = dyn_cast<ConstantInt>(IndexValue);
465  if (!CV)
466  return false;
467 
468  AccessIndex = CV->getValue().getZExtValue();
469  return true;
470 }
471 
472 /// Compute the base of the whole preserve_*_access_index chains, i.e., the base
473 /// pointer of the first preserve_*_access_index call, and construct the access
474 /// string, which will be the name of a global variable.
475 Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
476  std::string &AccessKey,
477  uint32_t Kind,
478  MDNode *&TypeMeta) {
479  Value *Base = nullptr;
480  std::string TypeName;
481  std::stack<std::pair<CallInst *, uint32_t>> CallStack;
482 
483  // Put the access chain into a stack with the top as the head of the chain.
484  while (Call) {
485  CallStack.push(std::make_pair(Call, Kind));
486  Kind = AIChain[Call].second;
487  Call = AIChain[Call].first;
488  }
489 
490  // The access offset from the base of the head of chain is also
491  // calculated here as all debuginfo types are available.
492 
493  // Get type name and calculate the first index.
494  // We only want to get type name from structure or union.
495  // If user wants a relocation like
496  // int *p; ... __builtin_preserve_access_index(&p[4]) ...
497  // or
498  // int a[10][20]; ... __builtin_preserve_access_index(&a[2][3]) ...
499  // we will skip them.
500  uint32_t FirstIndex = 0;
501  uint32_t AccessOffset = 0;
502  while (CallStack.size()) {
503  auto StackElem = CallStack.top();
504  Call = StackElem.first;
505  Kind = StackElem.second;
506 
507  if (!Base)
508  Base = Call->getArgOperand(0);
509 
510  MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
511  DIType *Ty = stripQualifiers(cast<DIType>(MDN));
512  if (Kind == BPFPreserveUnionAI || Kind == BPFPreserveStructAI) {
513  // struct or union type
514  TypeName = Ty->getName();
515  TypeMeta = Ty;
516  AccessOffset += FirstIndex * Ty->getSizeInBits() >> 3;
517  break;
518  }
519 
520  // Array entries will always be consumed for accumulative initial index.
521  CallStack.pop();
522 
523  // BPFPreserveArrayAI
524  uint64_t AccessIndex;
525  if (!getAccessIndex(Call->getArgOperand(2), AccessIndex))
526  return nullptr;
527 
528  DIType *BaseTy = nullptr;
529  bool CheckElemType = false;
530  if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) {
531  // array type
532  assert(CTy->getTag() == dwarf::DW_TAG_array_type);
533 
534 
535  FirstIndex += AccessIndex * calcArraySize(CTy, 1);
536  BaseTy = stripQualifiers(CTy->getBaseType());
537  CheckElemType = CTy->getElements().size() == 1;
538  } else {
539  // pointer type
540  auto *DTy = cast<DIDerivedType>(Ty);
541  assert(DTy->getTag() == dwarf::DW_TAG_pointer_type);
542 
543  BaseTy = stripQualifiers(DTy->getBaseType());
544  CTy = dyn_cast<DICompositeType>(BaseTy);
545  if (!CTy) {
546  CheckElemType = true;
547  } else if (CTy->getTag() != dwarf::DW_TAG_array_type) {
548  FirstIndex += AccessIndex;
549  CheckElemType = true;
550  } else {
551  FirstIndex += AccessIndex * calcArraySize(CTy, 0);
552  }
553  }
554 
555  if (CheckElemType) {
556  auto *CTy = dyn_cast<DICompositeType>(BaseTy);
557  if (!CTy)
558  return nullptr;
559 
560  unsigned CTag = CTy->getTag();
561  if (CTag != dwarf::DW_TAG_structure_type && CTag != dwarf::DW_TAG_union_type)
562  return nullptr;
563  else
564  TypeName = CTy->getName();
565  TypeMeta = CTy;
566  AccessOffset += FirstIndex * CTy->getSizeInBits() >> 3;
567  break;
568  }
569  }
570  assert(TypeName.size());
571  AccessKey += std::to_string(FirstIndex);
572 
573  // Traverse the rest of access chain to complete offset calculation
574  // and access key construction.
575  while (CallStack.size()) {
576  auto StackElem = CallStack.top();
577  Call = StackElem.first;
578  Kind = StackElem.second;
579  CallStack.pop();
580 
581  // Access Index
582  uint64_t AccessIndex;
583  uint32_t ArgIndex = (Kind == BPFPreserveUnionAI) ? 1 : 2;
584  if (!getAccessIndex(Call->getArgOperand(ArgIndex), AccessIndex))
585  return nullptr;
586  AccessKey += ":" + std::to_string(AccessIndex);
587 
588  MDNode *MDN = Call->getMetadata(LLVMContext::MD_preserve_access_index);
589  // At this stage, it cannot be pointer type.
590  auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN)));
591  uint32_t Tag = CTy->getTag();
592  if (Tag == dwarf::DW_TAG_structure_type) {
593  auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
594  AccessOffset += MemberTy->getOffsetInBits() >> 3;
595  } else if (Tag == dwarf::DW_TAG_array_type) {
596  auto *EltTy = stripQualifiers(CTy->getBaseType());
597  AccessOffset += AccessIndex * calcArraySize(CTy, 1) *
598  EltTy->getSizeInBits() >> 3;
599  }
600  }
601 
602  // Access key is the type name + access string, uniquely identifying
603  // one kernel memory access.
604  AccessKey = TypeName + ":" + std::to_string(AccessOffset) + "$" + AccessKey;
605 
606  return Base;
607 }
608 
609 /// Call/Kind is the base preserve_*_access_index() call. Attempts to do
610 /// transformation to a chain of relocable GEPs.
611 bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
612  uint32_t Kind) {
613  std::string AccessKey;
614  MDNode *TypeMeta;
615  Value *Base =
616  computeBaseAndAccessKey(Call, AccessKey, Kind, TypeMeta);
617  if (!Base)
618  return false;
619 
620  // Do the transformation
621  // For any original GEP Call and Base %2 like
622  // %4 = bitcast %struct.net_device** %dev1 to i64*
623  // it is transformed to:
624  // %6 = load sk_buff:50:$0:0:0:2:0
625  // %7 = bitcast %struct.sk_buff* %2 to i8*
626  // %8 = getelementptr i8, i8* %7, %6
627  // %9 = bitcast i8* %8 to i64*
628  // using %9 instead of %4
629  // The original Call inst is removed.
630  BasicBlock *BB = Call->getParent();
631  GlobalVariable *GV;
632 
633  if (GEPGlobals.find(AccessKey) == GEPGlobals.end()) {
634  GV = new GlobalVariable(M, Type::getInt64Ty(BB->getContext()), false,
635  GlobalVariable::ExternalLinkage, NULL, AccessKey);
637  GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
638  GEPGlobals[AccessKey] = GV;
639  } else {
640  GV = GEPGlobals[AccessKey];
641  }
642 
643  // Load the global variable.
644  auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV);
645  BB->getInstList().insert(Call->getIterator(), LDInst);
646 
647  // Generate a BitCast
648  auto *BCInst = new BitCastInst(Base, Type::getInt8PtrTy(BB->getContext()));
649  BB->getInstList().insert(Call->getIterator(), BCInst);
650 
651  // Generate a GetElementPtr
653  BCInst, LDInst);
654  BB->getInstList().insert(Call->getIterator(), GEP);
655 
656  // Generate a BitCast
657  auto *BCInst2 = new BitCastInst(GEP, Call->getType());
658  BB->getInstList().insert(Call->getIterator(), BCInst2);
659 
660  Call->replaceAllUsesWith(BCInst2);
661  Call->eraseFromParent();
662 
663  return true;
664 }
665 
666 bool BPFAbstractMemberAccess::doTransformation(Module &M) {
667  bool Transformed = false;
668 
669  for (Function &F : M) {
670  // Collect PreserveDIAccessIndex Intrinsic call chains.
671  // The call chains will be used to generate the access
672  // patterns similar to GEP.
673  collectAICallChains(M, F);
674 
675  for (auto &C : BaseAICalls)
676  Transformed = transformGEPChain(M, C.first, C.second) || Transformed;
677  }
678 
679  return removePreserveAccessIndexIntrinsic(M) || Transformed;
680 }
uint64_t CallInst * C
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks &#39;this&#39; from the containing basic block and deletes it.
Definition: Instruction.cpp:67
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1569
INITIALIZE_PASS(BPFAbstractMemberAccess, DEBUG_TYPE, "abstracting struct/union member accessees", false, false) ModulePass *llvm
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value *> IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Definition: Instructions.h:901
This class represents a function call, abstracting a target machine&#39;s calling convention.
static bool SkipDIDerivedTag(unsigned Tag)
void addAttribute(Attribute::AttrKind Kind)
Add attribute to this global.
Externally visible function.
Definition: GlobalValue.h:48
Metadata node.
Definition: Metadata.h:863
F(f)
An instruction for reading from memory.
Definition: Instructions.h:167
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:176
Hexagon Common GEP
LLVMContext & getContext() const
Get the context in which this basic block lives.
Definition: BasicBlock.cpp:32
StringRef getName() const
DINodeArray getElements() const
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1241
unsigned getTag() const
Array subrange.
uint64_t getSizeInBits() const
static DIType * stripQualifiers(DIType *Ty)
#define DEBUG_TYPE
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim)
This class represents a no-op cast from one type to another.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
Definition: Instruction.h:234
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition: Constants.h:137
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:429
static const std::string PatchableExtSecName
The section name to identify a patchable external global.
Definition: BPFCORE.h:19
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
Definition: Instructions.h:875
Value * getCalledValue() const
Definition: InstrTypes.h:1280
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
This is an important base class in LLVM.
Definition: Constant.h:41
CountType getCount() const
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
self_iterator getIterator()
Definition: ilist_node.h:81
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:219
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Definition: STLExtras.h:197
const InstListType & getInstList() const
Return the underlying instruction list container.
Definition: BasicBlock.h:333
Base class for types.
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
Module.h This file contains the declarations for the Module class.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:638
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
ModulePass * createBPFAbstractMemberAccess()
iterator_range< user_iterator > users()
Definition: Value.h:419
void setMetadata(unsigned KindID, MDNode *MD)
Set a particular kind of metadata attachment.
Definition: Metadata.cpp:1430
iterator insert(iterator where, pointer New)
Definition: ilist.h:226
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:175
#define I(x, y, z)
Definition: MD5.cpp:58
iterator_range< debug_compile_units_iterator > debug_compile_units() const
Return an iterator for all DICompileUnits listed in this Module&#39;s llvm.dbg.cu named metadata node and...
Definition: Module.h:781
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:224
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
static const std::string AmaAttr
The attribute attached to globals representing a member offset.
Definition: BPFCORE.h:17
const std::string to_string(const T &Value)
Definition: ScopedPrinter.h:61
static GetElementPtrInst * CreateInBounds(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Create an "inbounds" getelementptr.
Definition: Instructions.h:935
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
#define LLVM_DEBUG(X)
Definition: Debug.h:122
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:173
const BasicBlock * getParent() const
Definition: Instruction.h:66