LLVM  15.0.0git
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 // 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"
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"
93 #include <stack>
94 
95 #define DEBUG_TYPE "bpf-abstract-member-access"
96 
97 namespace llvm {
100 
102  Instruction *Input,
103  Instruction *Before) {
105  M, Intrinsic::bpf_passthrough, {Input->getType(), Input->getType()});
106  Constant *SeqNumVal = ConstantInt::get(Type::getInt32Ty(BB->getContext()),
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 {
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 
206 INITIALIZE_PASS(BPFAbstractMemberAccessLegacyPass, DEBUG_TYPE,
207  "BPF Abstract Member Access", false, false)
208 
210  return new BPFAbstractMemberAccessLegacyPass(TM);
211 }
212 
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));
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));
332  report_fatal_error("Incorrect flag for llvm.bpf.preserve.type.info intrinsic");
334  CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_EXISTENCE;
336  CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_MATCH;
337  else
338  CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_SIZE;
339  return true;
340  }
341  if (GV->getName().startswith("llvm.bpf.preserve.enum.value")) {
342  CInfo.Kind = BPFPreserveFieldInfoAI;
343  CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
344  if (!CInfo.Metadata)
345  report_fatal_error("Missing metadata for llvm.preserve.enum.value intrinsic");
346  uint64_t Flag = getConstant(Call->getArgOperand(2));
348  report_fatal_error("Incorrect flag for llvm.bpf.preserve.enum.value intrinsic");
350  CInfo.AccessIndex = BPFCoreSharedInfo::ENUM_VALUE_EXISTENCE;
351  else
352  CInfo.AccessIndex = BPFCoreSharedInfo::ENUM_VALUE;
353  return true;
354  }
355 
356  return false;
357 }
358 
359 void BPFAbstractMemberAccess::replaceWithGEP(std::vector<CallInst *> &CallList,
360  uint32_t DimensionIndex,
361  uint32_t GEPIndex) {
362  for (auto Call : CallList) {
363  uint32_t Dimension = 1;
364  if (DimensionIndex > 0)
365  Dimension = getConstant(Call->getArgOperand(DimensionIndex));
366 
367  Constant *Zero =
368  ConstantInt::get(Type::getInt32Ty(Call->getParent()->getContext()), 0);
369  SmallVector<Value *, 4> IdxList;
370  for (unsigned I = 0; I < Dimension; ++I)
371  IdxList.push_back(Zero);
372  IdxList.push_back(Call->getArgOperand(GEPIndex));
373 
375  getBaseElementType(Call), Call->getArgOperand(0), IdxList, "", Call);
376  Call->replaceAllUsesWith(GEP);
377  Call->eraseFromParent();
378  }
379 }
380 
381 bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Function &F) {
382  std::vector<CallInst *> PreserveArrayIndexCalls;
383  std::vector<CallInst *> PreserveUnionIndexCalls;
384  std::vector<CallInst *> PreserveStructIndexCalls;
385  bool Found = false;
386 
387  for (auto &BB : F)
388  for (auto &I : BB) {
389  auto *Call = dyn_cast<CallInst>(&I);
390  CallInfo CInfo;
391  if (!IsPreserveDIAccessIndexCall(Call, CInfo))
392  continue;
393 
394  Found = true;
395  if (CInfo.Kind == BPFPreserveArrayAI)
396  PreserveArrayIndexCalls.push_back(Call);
397  else if (CInfo.Kind == BPFPreserveUnionAI)
398  PreserveUnionIndexCalls.push_back(Call);
399  else
400  PreserveStructIndexCalls.push_back(Call);
401  }
402 
403  // do the following transformation:
404  // . addr = preserve_array_access_index(base, dimension, index)
405  // is transformed to
406  // addr = GEP(base, dimenion's zero's, index)
407  // . addr = preserve_union_access_index(base, di_index)
408  // is transformed to
409  // addr = base, i.e., all usages of "addr" are replaced by "base".
410  // . addr = preserve_struct_access_index(base, gep_index, di_index)
411  // is transformed to
412  // addr = GEP(base, 0, gep_index)
413  replaceWithGEP(PreserveArrayIndexCalls, 1, 2);
414  replaceWithGEP(PreserveStructIndexCalls, 0, 1);
415  for (auto Call : PreserveUnionIndexCalls) {
416  Call->replaceAllUsesWith(Call->getArgOperand(0));
417  Call->eraseFromParent();
418  }
419 
420  return Found;
421 }
422 
423 /// Check whether the access index chain is valid. We check
424 /// here because there may be type casts between two
425 /// access indexes. We want to ensure memory access still valid.
426 bool BPFAbstractMemberAccess::IsValidAIChain(const MDNode *ParentType,
427  uint32_t ParentAI,
428  const MDNode *ChildType) {
429  if (!ChildType)
430  return true; // preserve_field_info, no type comparison needed.
431 
432  const DIType *PType = stripQualifiers(cast<DIType>(ParentType));
433  const DIType *CType = stripQualifiers(cast<DIType>(ChildType));
434 
435  // Child is a derived/pointer type, which is due to type casting.
436  // Pointer type cannot be in the middle of chain.
437  if (isa<DIDerivedType>(CType))
438  return false;
439 
440  // Parent is a pointer type.
441  if (const auto *PtrTy = dyn_cast<DIDerivedType>(PType)) {
442  if (PtrTy->getTag() != dwarf::DW_TAG_pointer_type)
443  return false;
444  return stripQualifiers(PtrTy->getBaseType()) == CType;
445  }
446 
447  // Otherwise, struct/union/array types
448  const auto *PTy = dyn_cast<DICompositeType>(PType);
449  const auto *CTy = dyn_cast<DICompositeType>(CType);
450  assert(PTy && CTy && "ParentType or ChildType is null or not composite");
451 
452  uint32_t PTyTag = PTy->getTag();
453  assert(PTyTag == dwarf::DW_TAG_array_type ||
454  PTyTag == dwarf::DW_TAG_structure_type ||
455  PTyTag == dwarf::DW_TAG_union_type);
456 
457  uint32_t CTyTag = CTy->getTag();
458  assert(CTyTag == dwarf::DW_TAG_array_type ||
459  CTyTag == dwarf::DW_TAG_structure_type ||
460  CTyTag == dwarf::DW_TAG_union_type);
461 
462  // Multi dimensional arrays, base element should be the same
463  if (PTyTag == dwarf::DW_TAG_array_type && PTyTag == CTyTag)
464  return PTy->getBaseType() == CTy->getBaseType();
465 
466  DIType *Ty;
467  if (PTyTag == dwarf::DW_TAG_array_type)
468  Ty = PTy->getBaseType();
469  else
470  Ty = dyn_cast<DIType>(PTy->getElements()[ParentAI]);
471 
472  return dyn_cast<DICompositeType>(stripQualifiers(Ty)) == CTy;
473 }
474 
475 void BPFAbstractMemberAccess::traceAICall(CallInst *Call,
476  CallInfo &ParentInfo) {
477  for (User *U : Call->users()) {
478  Instruction *Inst = dyn_cast<Instruction>(U);
479  if (!Inst)
480  continue;
481 
482  if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
483  traceBitCast(BI, Call, ParentInfo);
484  } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
485  CallInfo ChildInfo;
486 
487  if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
488  IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
489  ChildInfo.Metadata)) {
490  AIChain[CI] = std::make_pair(Call, ParentInfo);
491  traceAICall(CI, ChildInfo);
492  } else {
493  BaseAICalls[Call] = ParentInfo;
494  }
495  } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
496  if (GI->hasAllZeroIndices())
497  traceGEP(GI, Call, ParentInfo);
498  else
499  BaseAICalls[Call] = ParentInfo;
500  } else {
501  BaseAICalls[Call] = ParentInfo;
502  }
503  }
504 }
505 
506 void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast,
507  CallInst *Parent,
508  CallInfo &ParentInfo) {
509  for (User *U : BitCast->users()) {
510  Instruction *Inst = dyn_cast<Instruction>(U);
511  if (!Inst)
512  continue;
513 
514  if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
515  traceBitCast(BI, Parent, ParentInfo);
516  } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
517  CallInfo ChildInfo;
518  if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
519  IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
520  ChildInfo.Metadata)) {
521  AIChain[CI] = std::make_pair(Parent, ParentInfo);
522  traceAICall(CI, ChildInfo);
523  } else {
524  BaseAICalls[Parent] = ParentInfo;
525  }
526  } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
527  if (GI->hasAllZeroIndices())
528  traceGEP(GI, Parent, ParentInfo);
529  else
530  BaseAICalls[Parent] = ParentInfo;
531  } else {
532  BaseAICalls[Parent] = ParentInfo;
533  }
534  }
535 }
536 
537 void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
538  CallInfo &ParentInfo) {
539  for (User *U : GEP->users()) {
540  Instruction *Inst = dyn_cast<Instruction>(U);
541  if (!Inst)
542  continue;
543 
544  if (auto *BI = dyn_cast<BitCastInst>(Inst)) {
545  traceBitCast(BI, Parent, ParentInfo);
546  } else if (auto *CI = dyn_cast<CallInst>(Inst)) {
547  CallInfo ChildInfo;
548  if (IsPreserveDIAccessIndexCall(CI, ChildInfo) &&
549  IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex,
550  ChildInfo.Metadata)) {
551  AIChain[CI] = std::make_pair(Parent, ParentInfo);
552  traceAICall(CI, ChildInfo);
553  } else {
554  BaseAICalls[Parent] = ParentInfo;
555  }
556  } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
557  if (GI->hasAllZeroIndices())
558  traceGEP(GI, Parent, ParentInfo);
559  else
560  BaseAICalls[Parent] = ParentInfo;
561  } else {
562  BaseAICalls[Parent] = ParentInfo;
563  }
564  }
565 }
566 
567 void BPFAbstractMemberAccess::collectAICallChains(Function &F) {
568  AIChain.clear();
569  BaseAICalls.clear();
570 
571  for (auto &BB : F)
572  for (auto &I : BB) {
573  CallInfo CInfo;
574  auto *Call = dyn_cast<CallInst>(&I);
575  if (!IsPreserveDIAccessIndexCall(Call, CInfo) ||
576  AIChain.find(Call) != AIChain.end())
577  continue;
578 
579  traceAICall(Call, CInfo);
580  }
581 }
582 
583 uint64_t BPFAbstractMemberAccess::getConstant(const Value *IndexValue) {
584  const ConstantInt *CV = dyn_cast<ConstantInt>(IndexValue);
585  assert(CV);
586  return CV->getValue().getZExtValue();
587 }
588 
589 /// Get the start and the end of storage offset for \p MemberTy.
590 void BPFAbstractMemberAccess::GetStorageBitRange(DIDerivedType *MemberTy,
591  Align RecordAlignment,
592  uint32_t &StartBitOffset,
593  uint32_t &EndBitOffset) {
594  uint32_t MemberBitSize = MemberTy->getSizeInBits();
595  uint32_t MemberBitOffset = MemberTy->getOffsetInBits();
596 
597  if (RecordAlignment > 8) {
598  // If the Bits are within an aligned 8-byte, set the RecordAlignment
599  // to 8, other report the fatal error.
600  if (MemberBitOffset / 64 != (MemberBitOffset + MemberBitSize) / 64)
601  report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
602  "requiring too big alignment");
603  RecordAlignment = Align(8);
604  }
605 
606  uint32_t AlignBits = RecordAlignment.value() * 8;
607  if (MemberBitSize > AlignBits)
608  report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
609  "bitfield size greater than record alignment");
610 
611  StartBitOffset = MemberBitOffset & ~(AlignBits - 1);
612  if ((StartBitOffset + AlignBits) < (MemberBitOffset + MemberBitSize))
613  report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
614  "cross alignment boundary");
615  EndBitOffset = StartBitOffset + AlignBits;
616 }
617 
618 uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
619  DICompositeType *CTy,
620  uint32_t AccessIndex,
621  uint32_t PatchImm,
622  MaybeAlign RecordAlignment) {
623  if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE)
624  return 1;
625 
626  uint32_t Tag = CTy->getTag();
627  if (InfoKind == BPFCoreSharedInfo::FIELD_BYTE_OFFSET) {
628  if (Tag == dwarf::DW_TAG_array_type) {
629  auto *EltTy = stripQualifiers(CTy->getBaseType());
630  PatchImm += AccessIndex * calcArraySize(CTy, 1) *
631  (EltTy->getSizeInBits() >> 3);
632  } else if (Tag == dwarf::DW_TAG_structure_type) {
633  auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
634  if (!MemberTy->isBitField()) {
635  PatchImm += MemberTy->getOffsetInBits() >> 3;
636  } else {
637  unsigned SBitOffset, NextSBitOffset;
638  GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset,
639  NextSBitOffset);
640  PatchImm += SBitOffset >> 3;
641  }
642  }
643  return PatchImm;
644  }
645 
646  if (InfoKind == BPFCoreSharedInfo::FIELD_BYTE_SIZE) {
647  if (Tag == dwarf::DW_TAG_array_type) {
648  auto *EltTy = stripQualifiers(CTy->getBaseType());
649  return calcArraySize(CTy, 1) * (EltTy->getSizeInBits() >> 3);
650  } else {
651  auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
652  uint32_t SizeInBits = MemberTy->getSizeInBits();
653  if (!MemberTy->isBitField())
654  return SizeInBits >> 3;
655 
656  unsigned SBitOffset, NextSBitOffset;
657  GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset,
658  NextSBitOffset);
659  SizeInBits = NextSBitOffset - SBitOffset;
660  if (SizeInBits & (SizeInBits - 1))
661  report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info");
662  return SizeInBits >> 3;
663  }
664  }
665 
666  if (InfoKind == BPFCoreSharedInfo::FIELD_SIGNEDNESS) {
667  const DIType *BaseTy;
668  if (Tag == dwarf::DW_TAG_array_type) {
669  // Signedness only checked when final array elements are accessed.
670  if (CTy->getElements().size() != 1)
671  report_fatal_error("Invalid array expression for llvm.bpf.preserve.field.info");
672  BaseTy = stripQualifiers(CTy->getBaseType());
673  } else {
674  auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
675  BaseTy = stripQualifiers(MemberTy->getBaseType());
676  }
677 
678  // Only basic types and enum types have signedness.
679  const auto *BTy = dyn_cast<DIBasicType>(BaseTy);
680  while (!BTy) {
681  const auto *CompTy = dyn_cast<DICompositeType>(BaseTy);
682  // Report an error if the field expression does not have signedness.
683  if (!CompTy || CompTy->getTag() != dwarf::DW_TAG_enumeration_type)
684  report_fatal_error("Invalid field expression for llvm.bpf.preserve.field.info");
685  BaseTy = stripQualifiers(CompTy->getBaseType());
686  BTy = dyn_cast<DIBasicType>(BaseTy);
687  }
688  uint32_t Encoding = BTy->getEncoding();
689  return (Encoding == dwarf::DW_ATE_signed || Encoding == dwarf::DW_ATE_signed_char);
690  }
691 
692  if (InfoKind == BPFCoreSharedInfo::FIELD_LSHIFT_U64) {
693  // The value is loaded into a value with FIELD_BYTE_SIZE size,
694  // and then zero or sign extended to U64.
695  // FIELD_LSHIFT_U64 and FIELD_RSHIFT_U64 are operations
696  // to extract the original value.
697  const Triple &Triple = TM->getTargetTriple();
698  DIDerivedType *MemberTy = nullptr;
699  bool IsBitField = false;
700  uint32_t SizeInBits;
701 
702  if (Tag == dwarf::DW_TAG_array_type) {
703  auto *EltTy = stripQualifiers(CTy->getBaseType());
704  SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits();
705  } else {
706  MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
707  SizeInBits = MemberTy->getSizeInBits();
708  IsBitField = MemberTy->isBitField();
709  }
710 
711  if (!IsBitField) {
712  if (SizeInBits > 64)
713  report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
714  return 64 - SizeInBits;
715  }
716 
717  unsigned SBitOffset, NextSBitOffset;
718  GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset);
719  if (NextSBitOffset - SBitOffset > 64)
720  report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
721 
722  unsigned OffsetInBits = MemberTy->getOffsetInBits();
723  if (Triple.getArch() == Triple::bpfel)
724  return SBitOffset + 64 - OffsetInBits - SizeInBits;
725  else
726  return OffsetInBits + 64 - NextSBitOffset;
727  }
728 
729  if (InfoKind == BPFCoreSharedInfo::FIELD_RSHIFT_U64) {
730  DIDerivedType *MemberTy = nullptr;
731  bool IsBitField = false;
732  uint32_t SizeInBits;
733  if (Tag == dwarf::DW_TAG_array_type) {
734  auto *EltTy = stripQualifiers(CTy->getBaseType());
735  SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits();
736  } else {
737  MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]);
738  SizeInBits = MemberTy->getSizeInBits();
739  IsBitField = MemberTy->isBitField();
740  }
741 
742  if (!IsBitField) {
743  if (SizeInBits > 64)
744  report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
745  return 64 - SizeInBits;
746  }
747 
748  unsigned SBitOffset, NextSBitOffset;
749  GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset);
750  if (NextSBitOffset - SBitOffset > 64)
751  report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
752 
753  return 64 - SizeInBits;
754  }
755 
756  llvm_unreachable("Unknown llvm.bpf.preserve.field.info info kind");
757 }
758 
759 bool BPFAbstractMemberAccess::HasPreserveFieldInfoCall(CallInfoStack &CallStack) {
760  // This is called in error return path, no need to maintain CallStack.
761  while (CallStack.size()) {
762  auto StackElem = CallStack.top();
763  if (StackElem.second.Kind == BPFPreserveFieldInfoAI)
764  return true;
765  CallStack.pop();
766  }
767  return false;
768 }
769 
770 /// Compute the base of the whole preserve_* intrinsics chains, i.e., the base
771 /// pointer of the first preserve_*_access_index call, and construct the access
772 /// string, which will be the name of a global variable.
773 Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
774  CallInfo &CInfo,
775  std::string &AccessKey,
776  MDNode *&TypeMeta) {
777  Value *Base = nullptr;
778  std::string TypeName;
779  CallInfoStack CallStack;
780 
781  // Put the access chain into a stack with the top as the head of the chain.
782  while (Call) {
783  CallStack.push(std::make_pair(Call, CInfo));
784  CInfo = AIChain[Call].second;
785  Call = AIChain[Call].first;
786  }
787 
788  // The access offset from the base of the head of chain is also
789  // calculated here as all debuginfo types are available.
790 
791  // Get type name and calculate the first index.
792  // We only want to get type name from typedef, structure or union.
793  // If user wants a relocation like
794  // int *p; ... __builtin_preserve_access_index(&p[4]) ...
795  // or
796  // int a[10][20]; ... __builtin_preserve_access_index(&a[2][3]) ...
797  // we will skip them.
798  uint32_t FirstIndex = 0;
799  uint32_t PatchImm = 0; // AccessOffset or the requested field info
801  while (CallStack.size()) {
802  auto StackElem = CallStack.top();
803  Call = StackElem.first;
804  CInfo = StackElem.second;
805 
806  if (!Base)
807  Base = CInfo.Base;
808 
809  DIType *PossibleTypeDef = stripQualifiers(cast<DIType>(CInfo.Metadata),
810  false);
811  DIType *Ty = stripQualifiers(PossibleTypeDef);
812  if (CInfo.Kind == BPFPreserveUnionAI ||
813  CInfo.Kind == BPFPreserveStructAI) {
814  // struct or union type. If the typedef is in the metadata, always
815  // use the typedef.
816  TypeName = std::string(PossibleTypeDef->getName());
817  TypeMeta = PossibleTypeDef;
818  PatchImm += FirstIndex * (Ty->getSizeInBits() >> 3);
819  break;
820  }
821 
822  assert(CInfo.Kind == BPFPreserveArrayAI);
823 
824  // Array entries will always be consumed for accumulative initial index.
825  CallStack.pop();
826 
827  // BPFPreserveArrayAI
828  uint64_t AccessIndex = CInfo.AccessIndex;
829 
830  DIType *BaseTy = nullptr;
831  bool CheckElemType = false;
832  if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) {
833  // array type
834  assert(CTy->getTag() == dwarf::DW_TAG_array_type);
835 
836 
837  FirstIndex += AccessIndex * calcArraySize(CTy, 1);
838  BaseTy = stripQualifiers(CTy->getBaseType());
839  CheckElemType = CTy->getElements().size() == 1;
840  } else {
841  // pointer type
842  auto *DTy = cast<DIDerivedType>(Ty);
843  assert(DTy->getTag() == dwarf::DW_TAG_pointer_type);
844 
845  BaseTy = stripQualifiers(DTy->getBaseType());
846  CTy = dyn_cast<DICompositeType>(BaseTy);
847  if (!CTy) {
848  CheckElemType = true;
849  } else if (CTy->getTag() != dwarf::DW_TAG_array_type) {
850  FirstIndex += AccessIndex;
851  CheckElemType = true;
852  } else {
853  FirstIndex += AccessIndex * calcArraySize(CTy, 0);
854  }
855  }
856 
857  if (CheckElemType) {
858  auto *CTy = dyn_cast<DICompositeType>(BaseTy);
859  if (!CTy) {
860  if (HasPreserveFieldInfoCall(CallStack))
861  report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic");
862  return nullptr;
863  }
864 
865  unsigned CTag = CTy->getTag();
866  if (CTag == dwarf::DW_TAG_structure_type || CTag == dwarf::DW_TAG_union_type) {
867  TypeName = std::string(CTy->getName());
868  } else {
869  if (HasPreserveFieldInfoCall(CallStack))
870  report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic");
871  return nullptr;
872  }
873  TypeMeta = CTy;
874  PatchImm += FirstIndex * (CTy->getSizeInBits() >> 3);
875  break;
876  }
877  }
878  assert(TypeName.size());
879  AccessKey += std::to_string(FirstIndex);
880 
881  // Traverse the rest of access chain to complete offset calculation
882  // and access key construction.
883  while (CallStack.size()) {
884  auto StackElem = CallStack.top();
885  CInfo = StackElem.second;
886  CallStack.pop();
887 
888  if (CInfo.Kind == BPFPreserveFieldInfoAI) {
889  InfoKind = CInfo.AccessIndex;
890  if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE)
891  PatchImm = 1;
892  break;
893  }
894 
895  // If the next Call (the top of the stack) is a BPFPreserveFieldInfoAI,
896  // the action will be extracting field info.
897  if (CallStack.size()) {
898  auto StackElem2 = CallStack.top();
899  CallInfo CInfo2 = StackElem2.second;
900  if (CInfo2.Kind == BPFPreserveFieldInfoAI) {
901  InfoKind = CInfo2.AccessIndex;
902  assert(CallStack.size() == 1);
903  }
904  }
905 
906  // Access Index
907  uint64_t AccessIndex = CInfo.AccessIndex;
908  AccessKey += ":" + std::to_string(AccessIndex);
909 
910  MDNode *MDN = CInfo.Metadata;
911  // At this stage, it cannot be pointer type.
912  auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN)));
913  PatchImm = GetFieldInfo(InfoKind, CTy, AccessIndex, PatchImm,
914  CInfo.RecordAlignment);
915  }
916 
917  // Access key is the
918  // "llvm." + type name + ":" + reloc type + ":" + patched imm + "$" +
919  // access string,
920  // uniquely identifying one relocation.
921  // The prefix "llvm." indicates this is a temporary global, which should
922  // not be emitted to ELF file.
923  AccessKey = "llvm." + TypeName + ":" + std::to_string(InfoKind) + ":" +
924  std::to_string(PatchImm) + "$" + AccessKey;
925 
926  return Base;
927 }
928 
929 MDNode *BPFAbstractMemberAccess::computeAccessKey(CallInst *Call,
930  CallInfo &CInfo,
931  std::string &AccessKey,
932  bool &IsInt32Ret) {
933  DIType *Ty = stripQualifiers(cast<DIType>(CInfo.Metadata), false);
934  assert(!Ty->getName().empty());
935 
936  int64_t PatchImm;
937  std::string AccessStr("0");
938  if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_EXISTENCE ||
939  CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_MATCH) {
940  PatchImm = 1;
941  } else if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_SIZE) {
942  // typedef debuginfo type has size 0, get the eventual base type.
943  DIType *BaseTy = stripQualifiers(Ty, true);
944  PatchImm = BaseTy->getSizeInBits() / 8;
945  } else {
946  // ENUM_VALUE_EXISTENCE and ENUM_VALUE
947  IsInt32Ret = false;
948 
949  // The argument could be a global variable or a getelementptr with base to
950  // a global variable depending on whether the clang option `opaque-options`
951  // is set or not.
952  const GlobalVariable *GV =
953  cast<GlobalVariable>(Call->getArgOperand(1)->stripPointerCasts());
954  assert(GV->hasInitializer());
955  const ConstantDataArray *DA = cast<ConstantDataArray>(GV->getInitializer());
956  assert(DA->isString());
957  StringRef ValueStr = DA->getAsString();
958 
959  // ValueStr format: <EnumeratorStr>:<Value>
960  size_t Separator = ValueStr.find_first_of(':');
961  StringRef EnumeratorStr = ValueStr.substr(0, Separator);
962 
963  // Find enumerator index in the debuginfo
964  DIType *BaseTy = stripQualifiers(Ty, true);
965  const auto *CTy = cast<DICompositeType>(BaseTy);
966  assert(CTy->getTag() == dwarf::DW_TAG_enumeration_type);
967  int EnumIndex = 0;
968  for (const auto Element : CTy->getElements()) {
969  const auto *Enum = cast<DIEnumerator>(Element);
970  if (Enum->getName() == EnumeratorStr) {
971  AccessStr = std::to_string(EnumIndex);
972  break;
973  }
974  EnumIndex++;
975  }
976 
977  if (CInfo.AccessIndex == BPFCoreSharedInfo::ENUM_VALUE) {
978  StringRef EValueStr = ValueStr.substr(Separator + 1);
979  PatchImm = std::stoll(std::string(EValueStr));
980  } else {
981  PatchImm = 1;
982  }
983  }
984 
985  AccessKey = "llvm." + Ty->getName().str() + ":" +
986  std::to_string(CInfo.AccessIndex) + std::string(":") +
987  std::to_string(PatchImm) + std::string("$") + AccessStr;
988 
989  return Ty;
990 }
991 
992 /// Call/Kind is the base preserve_*_access_index() call. Attempts to do
993 /// transformation to a chain of relocable GEPs.
994 bool BPFAbstractMemberAccess::transformGEPChain(CallInst *Call,
995  CallInfo &CInfo) {
996  std::string AccessKey;
997  MDNode *TypeMeta;
998  Value *Base = nullptr;
999  bool IsInt32Ret;
1000 
1001  IsInt32Ret = CInfo.Kind == BPFPreserveFieldInfoAI;
1002  if (CInfo.Kind == BPFPreserveFieldInfoAI && CInfo.Metadata) {
1003  TypeMeta = computeAccessKey(Call, CInfo, AccessKey, IsInt32Ret);
1004  } else {
1005  Base = computeBaseAndAccessKey(Call, CInfo, AccessKey, TypeMeta);
1006  if (!Base)
1007  return false;
1008  }
1009 
1010  BasicBlock *BB = Call->getParent();
1011  GlobalVariable *GV;
1012 
1013  if (GEPGlobals.find(AccessKey) == GEPGlobals.end()) {
1014  IntegerType *VarType;
1015  if (IsInt32Ret)
1016  VarType = Type::getInt32Ty(BB->getContext()); // 32bit return value
1017  else
1018  VarType = Type::getInt64Ty(BB->getContext()); // 64bit ptr or enum value
1019 
1020  GV = new GlobalVariable(*M, VarType, false, GlobalVariable::ExternalLinkage,
1021  nullptr, AccessKey);
1023  GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
1024  GEPGlobals[AccessKey] = GV;
1025  } else {
1026  GV = GEPGlobals[AccessKey];
1027  }
1028 
1029  if (CInfo.Kind == BPFPreserveFieldInfoAI) {
1030  // Load the global variable which represents the returned field info.
1031  LoadInst *LDInst;
1032  if (IsInt32Ret)
1033  LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", Call);
1034  else
1035  LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call);
1036 
1037  Instruction *PassThroughInst =
1038  BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call);
1039  Call->replaceAllUsesWith(PassThroughInst);
1040  Call->eraseFromParent();
1041  return true;
1042  }
1043 
1044  // For any original GEP Call and Base %2 like
1045  // %4 = bitcast %struct.net_device** %dev1 to i64*
1046  // it is transformed to:
1047  // %6 = load llvm.sk_buff:0:50$0:0:0:2:0
1048  // %7 = bitcast %struct.sk_buff* %2 to i8*
1049  // %8 = getelementptr i8, i8* %7, %6
1050  // %9 = bitcast i8* %8 to i64*
1051  // using %9 instead of %4
1052  // The original Call inst is removed.
1053 
1054  // Load the global variable.
1055  auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call);
1056 
1057  // Generate a BitCast
1058  auto *BCInst = new BitCastInst(Base, Type::getInt8PtrTy(BB->getContext()));
1059  BB->getInstList().insert(Call->getIterator(), BCInst);
1060 
1061  // Generate a GetElementPtr
1062  auto *GEP = GetElementPtrInst::Create(Type::getInt8Ty(BB->getContext()),
1063  BCInst, LDInst);
1064  BB->getInstList().insert(Call->getIterator(), GEP);
1065 
1066  // Generate a BitCast
1067  auto *BCInst2 = new BitCastInst(GEP, Call->getType());
1068  BB->getInstList().insert(Call->getIterator(), BCInst2);
1069 
1070  // For the following code,
1071  // Block0:
1072  // ...
1073  // if (...) goto Block1 else ...
1074  // Block1:
1075  // %6 = load llvm.sk_buff:0:50$0:0:0:2:0
1076  // %7 = bitcast %struct.sk_buff* %2 to i8*
1077  // %8 = getelementptr i8, i8* %7, %6
1078  // ...
1079  // goto CommonExit
1080  // Block2:
1081  // ...
1082  // if (...) goto Block3 else ...
1083  // Block3:
1084  // %6 = load llvm.bpf_map:0:40$0:0:0:2:0
1085  // %7 = bitcast %struct.sk_buff* %2 to i8*
1086  // %8 = getelementptr i8, i8* %7, %6
1087  // ...
1088  // goto CommonExit
1089  // CommonExit
1090  // SimplifyCFG may generate:
1091  // Block0:
1092  // ...
1093  // if (...) goto Block_Common else ...
1094  // Block2:
1095  // ...
1096  // if (...) goto Block_Common else ...
1097  // Block_Common:
1098  // PHI = [llvm.sk_buff:0:50$0:0:0:2:0, llvm.bpf_map:0:40$0:0:0:2:0]
1099  // %6 = load PHI
1100  // %7 = bitcast %struct.sk_buff* %2 to i8*
1101  // %8 = getelementptr i8, i8* %7, %6
1102  // ...
1103  // goto CommonExit
1104  // For the above code, we cannot perform proper relocation since
1105  // "load PHI" has two possible relocations.
1106  //
1107  // To prevent above tail merging, we use __builtin_bpf_passthrough()
1108  // where one of its parameters is a seq_num. Since two
1109  // __builtin_bpf_passthrough() funcs will always have different seq_num,
1110  // tail merging cannot happen. The __builtin_bpf_passthrough() will be
1111  // removed in the beginning of Target IR passes.
1112  //
1113  // This approach is also used in other places when global var
1114  // representing a relocation is used.
1115  Instruction *PassThroughInst =
1116  BPFCoreSharedInfo::insertPassThrough(M, BB, BCInst2, Call);
1117  Call->replaceAllUsesWith(PassThroughInst);
1118  Call->eraseFromParent();
1119 
1120  return true;
1121 }
1122 
1123 bool BPFAbstractMemberAccess::doTransformation(Function &F) {
1124  bool Transformed = false;
1125 
1126  // Collect PreserveDIAccessIndex Intrinsic call chains.
1127  // The call chains will be used to generate the access
1128  // patterns similar to GEP.
1129  collectAICallChains(F);
1130 
1131  for (auto &C : BaseAICalls)
1132  Transformed = transformGEPChain(C.first, C.second) || Transformed;
1133 
1134  return removePreserveAccessIndexIntrinsic(F) || Transformed;
1135 }
1136 
1139  return BPFAbstractMemberAccess(TM).run(F) ? PreservedAnalyses::none()
1141 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
llvm::DICompositeType::getBaseType
DIType * getBaseType() const
Definition: DebugInfoMetadata.h:1175
llvm::BPFCoreSharedInfo::MAX_PRESERVE_ENUM_VALUE_FLAG
@ MAX_PRESERVE_ENUM_VALUE_FLAG
Definition: BPFCORE.h:59
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::DIType
Base class for types.
Definition: DebugInfoMetadata.h:658
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:113
llvm::Intrinsic::getDeclaration
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
Definition: Function.cpp:1419
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:291
llvm::DIType::getSizeInBits
uint64_t getSizeInBits() const
Definition: DebugInfoMetadata.h:697
DebugInfoMetadata.h
llvm::Function
Definition: Function.h:60
Pass.h
llvm::BitCastInst
This class represents a no-op cast from one type to another.
Definition: Instructions.h:5212
llvm::ConstantInt::getValue
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition: Constants.h:133
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
SkipDIDerivedTag
static bool SkipDIDerivedTag(unsigned Tag, bool skipTypedef)
Definition: BPFAbstractMemberAccess.cpp:228
llvm::GlobalVariable
Definition: GlobalVariable.h:39
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:155
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Module.h
llvm::BPFCoreSharedInfo::SeqNum
static uint32_t SeqNum
llvm.bpf.passthrough builtin seq number
Definition: BPFCORE.h:68
getBaseElementType
static Type * getBaseElementType(const CallInst *Call)
Definition: BPFAbstractMemberAccess.cpp:272
calcArraySize
static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim)
Definition: BPFAbstractMemberAccess.cpp:257
BPF.h
llvm::dwarf::Tag
Tag
Definition: Dwarf.h:105
llvm::BPFCoreSharedInfo::TYPE_EXISTENCE
@ TYPE_EXISTENCE
Definition: BPFCORE.h:31
llvm::Type::getInt8Ty
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:237
llvm::Type::getInt32Ty
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:239
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::BPFCoreSharedInfo::FIELD_RSHIFT_U64
@ FIELD_RSHIFT_U64
Definition: BPFCORE.h:28
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::GlobalVariable::hasInitializer
bool hasInitializer() const
Definitions have initializers, declarations don't.
Definition: GlobalVariable.h:91
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::StringRef::substr
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:615
llvm::CallInfo
Definition: GVNHoist.cpp:217
Instruction.h
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
llvm::DISubrange::getCount
BoundType getCount() const
Definition: DebugInfoMetadata.cpp:378
llvm::BPFCoreSharedInfo::MAX_PRESERVE_TYPE_INFO_FLAG
@ MAX_PRESERVE_TYPE_INFO_FLAG
Definition: BPFCORE.h:52
llvm::User
Definition: User.h:44
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::CallInst::Create
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Definition: Instructions.h:1504
llvm::BPFCoreSharedInfo::FIELD_EXISTENCE
@ FIELD_EXISTENCE
Definition: BPFCORE.h:25
llvm::DINode::getTag
dwarf::Tag getTag() const
Definition: DebugInfoMetadata.cpp:184
llvm::BPFCoreSharedInfo::FIELD_SIGNEDNESS
@ FIELD_SIGNEDNESS
Definition: BPFCORE.h:26
llvm::DIType::getName
StringRef getName() const
Definition: DebugInfoMetadata.h:704
llvm::DISubrange
Array subrange.
Definition: DebugInfoMetadata.h:300
llvm::M68kBeads::DA
@ DA
Definition: M68kBaseInfo.h:59
llvm::MaybeAlign
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:117
llvm::IntegerType
Class to represent integer types.
Definition: DerivedTypes.h:40
llvm::Instruction
Definition: Instruction.h:42
llvm::GlobalVariable::addAttribute
void addAttribute(Attribute::AttrKind Kind)
Add attribute to this global.
Definition: GlobalVariable.h:187
llvm::MCID::Flag
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:147
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:143
llvm::APInt::getZExtValue
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1466
llvm::BPFAbstractMemberAccessPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition: BPFAbstractMemberAccess.cpp:1138
llvm::ConstantInt::get
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:924
Align
uint64_t Align
Definition: ELFObjHandler.cpp:81
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::MCID::Call
@ Call
Definition: MCInstrDesc.h:155
llvm::Metadata
Root of the metadata hierarchy.
Definition: Metadata.h:62
llvm::Triple::getArch
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition: Triple.h:345
llvm::BPFCoreSharedInfo::PRESERVE_TYPE_INFO_MATCH
@ PRESERVE_TYPE_INFO_MATCH
Definition: BPFCORE.h:50
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:249
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Type.h
llvm::dxil::PointerTypeAnalysis::run
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
Definition: PointerTypeAnalysis.cpp:101
llvm::BPFCoreSharedInfo::MAX_FIELD_RELOC_KIND
@ MAX_FIELD_RELOC_KIND
Definition: BPFCORE.h:37
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition: GlobalVariable.h:135
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::StringRef::empty
constexpr LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::DICompositeType::getElements
DINodeArray getElements() const
Definition: DebugInfoMetadata.h:1176
llvm::BPFCoreSharedInfo::ENUM_VALUE
@ ENUM_VALUE
Definition: BPFCORE.h:34
uint64_t
llvm::BPFCoreSharedInfo::FIELD_BYTE_OFFSET
@ FIELD_BYTE_OFFSET
Definition: BPFCORE.h:23
llvm::ConstantDataArray
An array constant whose element type is a simple 1/2/4/8-byte integer or float/double,...
Definition: Constants.h:679
llvm::BPFCoreSharedInfo::insertPassThrough
static Instruction * insertPassThrough(Module *M, BasicBlock *BB, Instruction *Input, Instruction *Before)
Insert a bpf passthrough builtin function.
Definition: BPFAbstractMemberAccess.cpp:101
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::GetElementPtrInst
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Definition: Instructions.h:916
llvm::GetElementPtrInst::CreateInBounds
static GetElementPtrInst * CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Create an "inbounds" getelementptr.
Definition: Instructions.h:969
llvm::BPFCoreSharedInfo::PRESERVE_TYPE_INFO_EXISTENCE
@ PRESERVE_TYPE_INFO_EXISTENCE
Definition: BPFCORE.h:48
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
DEBUG_TYPE
#define DEBUG_TYPE
Definition: BPFAbstractMemberAccess.cpp:95
llvm::pdb::PDB_SymType::Dimension
@ Dimension
llvm::Triple::bpfel
@ bpfel
Definition: Triple.h:56
llvm::DIType::isBitField
bool isBitField() const
Definition: DebugInfoMetadata.h:734
llvm::BPFCoreSharedInfo::TYPE_SIZE
@ TYPE_SIZE
Definition: BPFCORE.h:32
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::MDNode
Metadata node.
Definition: Metadata.h:944
llvm::BPFCoreSharedInfo::FIELD_BYTE_SIZE
@ FIELD_BYTE_SIZE
Definition: BPFCORE.h:24
llvm::GetElementPtrInst::Create
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Definition: Instructions.h:942
llvm::DICompositeType
Composite types.
Definition: DebugInfoMetadata.h:1042
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
Dwarf.h
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::createBPFAbstractMemberAccess
FunctionPass * createBPFAbstractMemberAccess(BPFTargetMachine *TM)
uint32_t
llvm::ilist_node_impl::getIterator
self_iterator getIterator()
Definition: ilist_node.h:82
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::pdb::PDB_SymType::Enum
@ Enum
llvm::BPFCoreSharedInfo::PRESERVE_ENUM_VALUE_EXISTENCE
@ PRESERVE_ENUM_VALUE_EXISTENCE
Definition: BPFCORE.h:56
llvm::BPFCoreSharedInfo::ENUM_VALUE_EXISTENCE
@ ENUM_VALUE_EXISTENCE
Definition: BPFCORE.h:33
llvm::LoadInst
An instruction for reading from memory.
Definition: Instructions.h:173
llvm::BPFTargetMachine
Definition: BPFTargetMachine.h:20
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::DIType::getOffsetInBits
uint64_t getOffsetInBits() const
Definition: DebugInfoMetadata.h:700
llvm::Type::getInt64Ty
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:240
llvm::AMDGPU::HSAMD::Kernel::Arg::Key::TypeName
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
Definition: AMDGPUMetadata.h:175
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
llvm::Align::value
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
stripQualifiers
static DIType * stripQualifiers(DIType *Ty, bool skipTypedef=true)
Definition: BPFAbstractMemberAccess.cpp:239
GlobalVariable.h
BPFCORE.h
PassManager.h
llvm::DIDerivedType
Derived types.
Definition: DebugInfoMetadata.h:924
llvm::GlobalValue::ExternalLinkage
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:48
llvm::BPFCoreSharedInfo::AmaAttr
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
Definition: BPFCORE.h:63
llvm::GlobalObject::setMetadata
void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
Definition: Metadata.cpp:1332
Instructions.h
User.h
llvm::BPFCoreSharedInfo::FIELD_LSHIFT_U64
@ FIELD_LSHIFT_U64
Definition: BPFCORE.h:27
llvm::to_string
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:85
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:42
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1461
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::StringRef::find_first_of
LLVM_NODISCARD 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.
Definition: StringRef.h:414
GEP
Hexagon Common GEP
Definition: HexagonCommonGEP.cpp:171
INITIALIZE_PASS
INITIALIZE_PASS(BPFAbstractMemberAccessLegacyPass, DEBUG_TYPE, "BPF Abstract Member Access", false, false) FunctionPass *llvm
Definition: BPFAbstractMemberAccess.cpp:206
BasicBlockUtils.h
Value.h
llvm::BPFCoreSharedInfo::TYPE_MATCH
@ TYPE_MATCH
Definition: BPFCORE.h:35
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Value::users
iterator_range< user_iterator > users()
Definition: Value.h:421
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
BPFTargetMachine.h