Beispiel #1
0
// what a hack
static Function *getStubFunctionForCtorList(Module *m,
                                            GlobalVariable *gv, 
                                            std::string name) {
  assert(!gv->isDeclaration() && !gv->hasInternalLinkage() &&
         "do not support old LLVM style constructor/destructor lists");

  std::vector<Type *> nullary;

  Function *fn = Function::Create(FunctionType::get(Type::getVoidTy(m->getContext()),
						    nullary, false),
				  GlobalVariable::InternalLinkage, 
				  name,
                              m);
  BasicBlock *bb = BasicBlock::Create(m->getContext(), "entry", fn);
  
  // From lli:
  // Should be an array of '{ int, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  ConstantArray *arr = dyn_cast<ConstantArray>(gv->getInitializer());
  if (arr) {
    for (unsigned i=0; i<arr->getNumOperands(); i++) {
      ConstantStruct *cs = cast<ConstantStruct>(arr->getOperand(i));
#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5)
      // There is a third *optional* element in global_ctor elements (``i8
      // @data``).
      assert((cs->getNumOperands() == 2 || cs->getNumOperands() == 3) &&
             "unexpected element in ctor initializer list");
#else
      assert(cs->getNumOperands()==2 && "unexpected element in ctor initializer list");
#endif
      Constant *fp = cs->getOperand(1);      
      if (!fp->isNullValue()) {
        if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp))
          fp = ce->getOperand(0);

        if (Function *f = dyn_cast<Function>(fp)) {
	  CallInst::Create(f, "", bb);
        } else {
          assert(0 && "unable to get function pointer from ctor initializer list");
        }
      }
    }
  }
  
  ReturnInst::Create(m->getContext(), bb);

  return fn;
}
Beispiel #2
0
CtorDtorIterator::Element CtorDtorIterator::operator*() const {
  ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
  assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");

  Constant *FuncC = CS->getOperand(1);
  Function *Func = nullptr;

  // Extract function pointer, pulling off any casts.
  while (FuncC) {
    if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
      Func = F;
      break;
    } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
      if (CE->isCast())
        FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0));
      else
        break;
    } else {
      // This isn't anything we recognize. Bail out with Func left set to null.
      break;
    }
  }

  ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
  Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
  if (Data && !isa<GlobalValue>(Data))
    Data = nullptr;
  return Element(Priority->getZExtValue(), Func, Data);
}
Beispiel #3
0
void ClassHierarchyUtils::processTypeInfo(GlobalVariable* TI) {
  if (find(classes.begin(), classes.end(), TI) == classes.end()) {
    classes.push_back(TI);

    // extract direct base classes from type_info
    if (TI->hasInitializer()) {
      ConstantStruct* TIinit = cast<ConstantStruct>(TI->getInitializer());

      int TInumOperands = TIinit->getNumOperands();
      if (TInumOperands > 2) {
        // we have >= 1 base class(es).
        if (TInumOperands == 3) {
          // abi::__si_class_type_info
          GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(2)->stripPointerCasts());
          classToSubclasses[baseTI].push_back(TI);
          //dbgs() << "  " << *baseTI << "\n";
          classToBaseOffset[TI][baseTI] = 0;
          processTypeInfo(baseTI);
          
        }
        else {
          // abi::__vmi_class_type_info
          // (skip over first two additional fields, which are "flags" and "base_count")
          for (int i=4; i<TInumOperands; i+=2) {
            GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(i)->stripPointerCasts());
            classToSubclasses[baseTI].push_back(TI);
            int offset_flags = cast<ConstantInt>(TIinit->getOperand(i+1))->getSExtValue();
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << TI->getName() << " -> " << baseTI->getName() << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset_flags = " << offset_flags << "\n");
            int offset = offset_flags >> 8; // TODO: is this value defined as a constant somewhere?
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset = " << offset << "\n");
            classToBaseOffset[TI][baseTI] = offset;
            //dbgs() << "  " << *baseTI << "\n";
            processTypeInfo(baseTI);
          }
        }
      }
    }
void MemoryInstrumenter::lowerGlobalCtors(Module &M) {
  // Find llvm.global_ctors.
  GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors");
  if (!GV)
    return;
  assert(!GV->isDeclaration() && !GV->hasLocalLinkage());

  // Should be an array of '{ int, void ()* }' structs.  The first value is
  // the init priority, which must be 65535 if the bitcode is generated using
  // clang.
  if (ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer())) {
    for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
      ConstantStruct *CS =
        dyn_cast<ConstantStruct>(InitList->getOperand(i));
      assert(CS);
      assert(CS->getNumOperands() == 2);

      // Get the priority.
      ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
      assert(Priority);
      // TODO: For now, we assume all priorities must be 65535.
      assert(Priority->equalsInt(65535));

      // Get the constructor function.
      Constant *FP = CS->getOperand(1);
      if (FP->isNullValue())
        break;  // Found a null terminator, exit.

      // Explicitly call the constructor at the main entry.
      CallInst::Create(FP, "", Main->begin()->getFirstNonPHI());
    }
  }

  // Clear the global_ctors array.
  // Use eraseFromParent() instead of removeFromParent().
  GV->eraseFromParent();
}
void ClassHierarchyUtils::processTypeInfo(GlobalVariable* TI, Module& M) {
  if (find(classes.begin(), classes.end(), TI) == classes.end()) {
    SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Adding class " << TI->getName() << "\n");
    classes.push_back(TI);

    // First process the correspoding virtual table. We store the indexes of the primary
    // and secondary vtables, indexed by the corresponding subobject offset. This will allow
    // us to quickly jump to a particular sub-vtable.
    if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
      GlobalVariable* VT = typeInfoToVTable[TI]; 
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n");
      ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer());
      for (int i=0; i<VTinit->getNumOperands(); i++) {
        ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(i));
        for (int j=0; j<VTinitElem->getNumOperands(); j++) {
          // Each sub-vtable is preceded by a reference to the class's type_info instance.
          // (See https://mentorembedded.github.io/cxx-abi/abi.html).
          if (TI == VTinitElem->getOperand(j)->stripPointerCasts()) {
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found TI at index " << i << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Storing mapping " << VT->getName() << " <-> " << TI->getName() << "\n");
            
            // the offset to top is the offset from the vptr pointing to this
            // sub-vtable, back to the top of the object. This will be negative,
            // but the absolute value gives us the offset from the start of the
            // object (i.e. first vptr), to the subobject.
            int offsetToTop = 0;
            if (ConstantExpr* offsetValCast = dyn_cast<ConstantExpr>(VTinitElem->getOperand(j-1)->stripPointerCasts())) {
              ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0));
              offsetToTop = offsetVal->getSExtValue(); // will be 0 for the primary
            }
            if (offsetToTop > 0) {
              report_fatal_error("ERROR: offsetToTop is positive!");
            }
            else {
              offsetToTop *= -1;
            }
            
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n")
            vTableToSecondaryVTableMaps[VT][offsetToTop] = pair<int, int>(i, j+1);
          }
        }
      }
    }
    else {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No vtable found for " << TI->getName() << "\n");
    }

    // Now process the type_info struct, extract direct base class info (what
    // their subobject offsets are, or if they are virtual then their
    // virtual-base-offset-offset)
    if (TI->hasInitializer()) {
      ConstantStruct* TIinit = cast<ConstantStruct>(TI->getInitializer());

      int TInumOperands = TIinit->getNumOperands();
      if (TInumOperands > 2) { // first two operands are vptr and type name
        // we have >= 1 base class(es).
        if (TInumOperands == 3) {
          // abi::__si_class_type_info: single, public, non-virtual base at
          // offset 0
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__si_class_type_info\n");
          GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(2)->stripPointerCasts());
          classToSubclasses[baseTI].push_back(TI);
          //dbgs() << "  " << *baseTI << "\n";
          classToBaseOffset[TI][baseTI] = 0;
          processTypeInfo(baseTI, M);
        }
        else {
          // abi::__vmi_class_type_info: all other cases
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__vmi_class_type_info\n");
          // (skip over first two additional fields, which are "flags" and "base_count")
          for (int i=4; i<TInumOperands; i+=2) {
            GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(i)->stripPointerCasts());
            classToSubclasses[baseTI].push_back(TI);
            long offset_flags = cast<ConstantInt>(TIinit->getOperand(i+1))->getSExtValue();
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << TI->getName() << " -> " << baseTI->getName() << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset_flags = " << offset_flags << "\n");
            ptrdiff_t offset = offset_flags >> offset_shift;
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset = " << offset << "\n");
            // If this a virtual base class, then we obtain the
            // vbase-offset-offset.  This is the offset from the start of the
            // derived class's (primary) vtable to the location containing the
            // vbase-offset, which is the offset from the start of the object
            // to the virtual base's subobject. Note that virtual base
            // subobjects only exist once and are laid out after all other
            // non-virtual objects. We keep track of the vbase-offset-offset,
            // so that we can find the vbase offset when going down the class
            // hierarchy. (The vbase offset may differ every time but the
            // vbase-offset-offset will remain the same relative to the current
            // class's vtable in subclasses).
            if (offset_flags & virtual_mask) { // is this a virtual base class?
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "virtual base class: " << baseTI->getName() << "\n");
              int vbaseOffsetOffset = offset/sizeof(long); // this should be negative
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-offset: " << vbaseOffsetOffset << "\n");
              classToVBaseOffsetOffset[TI][baseTI] = vbaseOffsetOffset;
              if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
                GlobalVariable* VT = typeInfoToVTable[TI];
                int vbaseOffsetIdx = vTableToSecondaryVTableMaps[VT][0].second+vbaseOffsetOffset;
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-idx: " << vbaseOffsetIdx << "\n");
              }
              else {
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No VTable for " << TI->getName() << "\n");
              }
            }
            else {
              // In the non-virtual base class case, we just record the subobj
              // offset. This is the offset from the start of the derived
              // object to the base class's subobject. We use this information
              // together with the offset-to-top info we obtained from the
              // vtable to find the base class's subvtable. Note that the
              // relative position of the base class subobj within the current
              // derived object will always remain the same, even in
              // subclasses.
              classToBaseOffset[TI][baseTI] = offset;
            }
            //dbgs() << "  " << *baseTI << "\n";
            processTypeInfo(baseTI, M);
          }
        }
      }
    }
/// analyzeDestructor - Given the heap.metadata argument to swift_allocObject,
/// take a look a the destructor and try to decide if it has side effects or any
/// other bad effects that can prevent it from being optimized.
static DtorKind analyzeDestructor(Value *P) {
  // If we have a null pointer for the metadata info, the dtor has no side
  // effects.  Actually, the final release would crash.  This is really only
  // useful for writing testcases.
  if (isa<ConstantPointerNull>(P->stripPointerCasts()))
    return DtorKind::NoSideEffects;

  // We have to have a known heap metadata value, reject dynamically computed
  // ones, or places
  GlobalVariable *GV = dyn_cast<GlobalVariable>(P->stripPointerCasts());
  if (GV == 0 || GV->mayBeOverridden()) return DtorKind::Unknown;

  ConstantStruct *CS = dyn_cast_or_null<ConstantStruct>(GV->getInitializer());
  if (CS == 0 || CS->getNumOperands() == 0) return DtorKind::Unknown;

  // FIXME: Would like to abstract the dtor slot (#0) out from this to somewhere
  // unified.
  enum { DTorSlotOfHeapMetadata = 0 };
  Function *DtorFn =dyn_cast<Function>(CS->getOperand(DTorSlotOfHeapMetadata));
  if (DtorFn == 0 || DtorFn->mayBeOverridden() || DtorFn->hasExternalLinkage())
    return DtorKind::Unknown;

  // Okay, we have a body, and we can trust it.  If the function is marked
  // readonly, then we know it can't have any interesting side effects, so we
  // don't need to analyze it at all.
  if (DtorFn->onlyReadsMemory())
    return DtorKind::NoSideEffects;

  // The first argument is the object being destroyed.
  assert(DtorFn->arg_size() == 1 && !DtorFn->isVarArg() &&
         "expected a single object argument to destructors");
  Value *ThisObject = &*DtorFn->arg_begin();

  // Scan the body of the function, looking for anything scary.
  for (BasicBlock &BB : *DtorFn) {
    for (Instruction &I : BB) {
      // Note that the destructor may not be in any particular canonical form.
      switch (classifyInstruction(I)) {
      // These instructions should not reach here based on the pass ordering.
      // i.e. LLVMARCOpt -> LLVMContractOpt.
      case RT_RetainN:
      case RT_UnknownRetainN:
      case RT_BridgeRetainN:
      case RT_ReleaseN:
      case RT_UnknownReleaseN:
      case RT_BridgeReleaseN:
        llvm_unreachable("These are only created by LLVMARCContract !");
      case RT_NoMemoryAccessed:
      case RT_AllocObject:
      case RT_FixLifetime:
      case RT_CheckUnowned:
        // Skip over random instructions that don't touch memory in the caller.
        continue;

      case RT_RetainUnowned:
      case RT_BridgeRetain:          // x = swift_bridgeRetain(y)
      case RT_Retain: {      // swift_retain(obj)

        // Ignore retains of the "self" object, no resurrection is possible.
        Value *ThisRetainedObject = cast<CallInst>(I).getArgOperand(0);
        if (ThisRetainedObject->stripPointerCasts() ==
            ThisObject->stripPointerCasts())
          continue;
        // Otherwise, we may be retaining something scary.
        break;
      }

      case RT_Release: {
        // If we get to a release that is provably to this object, then we can
        // ignore it.
        Value *ThisReleasedObject = cast<CallInst>(I).getArgOperand(0);

        if (ThisReleasedObject->stripPointerCasts() ==
            ThisObject->stripPointerCasts())
          continue;
        // Otherwise, we may be retaining something scary.
        break;
      }

      case RT_ObjCRelease:
      case RT_ObjCRetain:
      case RT_UnknownRetain:
      case RT_UnknownRelease:
      case RT_BridgeRelease:
        // Objective-C retain and release can have arbitrary side effects.
        break;

      case RT_Unknown:
        // Ignore all instructions with no side effects.
        if (!I.mayHaveSideEffects()) continue;

        // store, memcpy, memmove *to* the object can be dropped.
        if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
          if (SI->getPointerOperand()->stripInBoundsOffsets() == ThisObject)
            continue;
        }

        if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&I)) {
          if (MI->getDest()->stripInBoundsOffsets() == ThisObject)
            continue;
        }

        // Otherwise, we can't remove the deallocation completely.
        break;
      }

      // Okay, the function has some side effects, if it doesn't capture the
      // object argument, at least that is something.
      return DtorFn->doesNotCapture(0) ? DtorKind::NoEscape : DtorKind::Unknown;
    }
  }

  // If we didn't find any side effects, we win.
  return DtorKind::NoSideEffects;
}