Example #1
0
void InstrProfiling::emitUses() {
  if (UsedVars.empty())
    return;

  GlobalVariable *LLVMUsed = M->getGlobalVariable("llvm.used");
  std::vector<Constant *> MergedVars;
  if (LLVMUsed) {
    // Collect the existing members of llvm.used.
    ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
    for (unsigned I = 0, E = Inits->getNumOperands(); I != E; ++I)
      MergedVars.push_back(Inits->getOperand(I));
    LLVMUsed->eraseFromParent();
  }

  Type *i8PTy = Type::getInt8PtrTy(M->getContext());
  // Add uses for our data.
  for (auto *Value : UsedVars)
    MergedVars.push_back(
        ConstantExpr::getBitCast(cast<Constant>(Value), i8PTy));

  // Recreate llvm.used.
  ArrayType *ATy = ArrayType::get(i8PTy, MergedVars.size());
  LLVMUsed =
      new GlobalVariable(*M, ATy, false, GlobalValue::AppendingLinkage,
                         ConstantArray::get(ATy, MergedVars), "llvm.used");

  LLVMUsed->setSection("llvm.metadata");
}
Example #2
0
/// Given a specified llvm.global_ctors list, remove the listed elements.
static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
  // Filter out the initializer elements to remove.
  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
  SmallVector<Constant *, 10> CAList;
  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
    if (!CtorsToRemove.test(I))
      CAList.push_back(OldCA->getOperand(I));

  // Create the new array initializer.
  ArrayType *ATy =
      ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
  Constant *CA = ConstantArray::get(ATy, CAList);

  // If we didn't change the number of elements, don't create a new GV.
  if (CA->getType() == OldCA->getType()) {
    GCL->setInitializer(CA);
    return;
  }

  // Create the new global and insert it next to the existing list.
  GlobalVariable *NGV =
      new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
                         CA, "", GCL->getThreadLocalMode());
  GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV);
  NGV->takeName(GCL);

  // Nuke the old list, replacing any uses with the new one.
  if (!GCL->use_empty()) {
    Constant *V = NGV;
    if (V->getType() != GCL->getType())
      V = ConstantExpr::getBitCast(V, GCL->getType());
    GCL->replaceAllUsesWith(V);
  }
  GCL->eraseFromParent();
}
Example #3
0
/// runStaticConstructorsDestructors - This method is used to execute all of
/// the static constructors or destructors for a module, depending on the
/// value of isDtors.
void ExecutionEngine::runStaticConstructorsDestructors(Module *module, bool isDtors) {
  const char *Name = isDtors ? "llvm.global_dtors" : "llvm.global_ctors";
  
  // Execute global ctors/dtors for each module in the program.
  
 GlobalVariable *GV = module->getNamedGlobal(Name);

 // If this global has internal linkage, or if it has a use, then it must be
 // an old-style (llvmgcc3) static ctor with __main linked in and in use.  If
 // this is the case, don't execute any of the global ctors, __main will do
 // it.
 if (!GV || GV->isDeclaration() || GV->hasLocalLinkage()) return;
 
 // Should be an array of '{ int, void ()* }' structs.  The first value is
 // the init priority, which we ignore.
 ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
 if (!InitList) return;
 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
   if (ConstantStruct *CS = 
       dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
     if (CS->getNumOperands() != 2) return; // Not array of 2-element structs.
   
     Constant *FP = CS->getOperand(1);
     if (FP->isNullValue())
       break;  // Found a null terminator, exit.
   
     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
       if (CE->isCast())
         FP = CE->getOperand(0);
     if (Function *F = dyn_cast<Function>(FP)) {
       // Execute the ctor/dtor function!
       runFunction(F, std::vector<GenericValue>());
     }
   }
}
void ClassHierarchyUtils::findClassHierarchy(Module& M) {
  // Extract class hierarchy using std::type_info structures rather than debug
  // info. The former works even for when there are anonymous namespaces.
  // (for more info, see http://mentorembedded.github.io/cxx-abi/abi.html)
  // 
  // Class names are usually global, except in the case of anonymous namespaces, in which case
  // they may be renamed during linking. This renaming is not consistent across type_info and
  // vtables. For example, the following are for the same class:
  // _ZTIN7content12_GLOBAL__N_115HeaderFlattenerE60908 and
  // _ZTVN7content12_GLOBAL__N_115HeaderFlattenerE60906.
  // 
  // (renamed from
  // _ZTVN7content12_GLOBAL__N_115HeaderFlattenerE and
  // _ZTIN7content12_GLOBAL__N_115HeaderFlattenerE).
  //
  // VTables give us the corresponding type_info, so we process them first and store
  // the VT <-> TI mappings, as this will be useful later.
  for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) {
    GlobalVariable* VT = &*I;
    if (VT->getName().startswith("_ZTV")) {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n");
      if (VT->hasInitializer()) {
        ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer());
        // all occurrences of a type_info object refer to this class's type_info, so we
        // can pick the first array
        ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(0));
        for (int i=0; i<VTinitElem->getNumOperands(); i++) {
          // type_info will be the first global variable in the array.
          // It's not always at a fixed index so we have to search for it...
          // The first one corresponds to the primary vtable, all others
          // correspond to secondary vtables. All type_info occurrences will
          // be the same.
          if (GlobalVariable* TI = dyn_cast<GlobalVariable>(VTinitElem->getOperand(i)->stripPointerCasts())) {
            if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
              report_fatal_error(TI->getName() + " <-> " + VT->getName() + " mapping already exists!");
            }
            // Record TI <-> VT mappings, as they will be useful later
            typeInfoToVTable[TI] = VT;
            vTableToTypeInfo[VT] = TI;
            break;  // we only need to process the first one
          }
        }
      }
      else {
        SDEBUG("soaap.util.classhierarchy", 1, dbgs() << "WARNING: VTable " << VT->getName() << " does not have initializer\n");
      }
    }
  }

  // Process type_info structures, recording class-hierarchy information and base offsets
  for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) {
    GlobalVariable* G = &*I;
    if (G->getName().startswith("_ZTI")) {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found type_info: " << G->getName() << "\n");
      processTypeInfo(G, M);
    }
  }

  SDEBUG("soaap.util.classhierarchy", 3, ppClassHierarchy(classToSubclasses));
}
static void readFuncList(GlobalVariable *Array, std::vector<Constant*> *Funcs) {
  if (!Array->hasInitializer())
    return;
  Constant *Init = Array->getInitializer();
  ArrayType *Ty = dyn_cast<ArrayType>(Init->getType());
  if (!Ty) {
    errs() << "Initializer: " << *Array->getInitializer() << "\n";
    report_fatal_error("ExpandCtors: Initializer is not of array type");
  }
  if (Ty->getNumElements() == 0)
    return;
  ConstantArray *InitList = dyn_cast<ConstantArray>(Init);
  if (!InitList) {
    errs() << "Initializer: " << *Array->getInitializer() << "\n";
    report_fatal_error("ExpandCtors: Unexpected initializer ConstantExpr");
  }
  std::vector<FuncArrayEntry> FuncsToSort;
  for (unsigned Index = 0; Index < InitList->getNumOperands(); ++Index) {
    ConstantStruct *CS = cast<ConstantStruct>(InitList->getOperand(Index));
    FuncArrayEntry Entry;
    Entry.priority = cast<ConstantInt>(CS->getOperand(0))->getZExtValue();
    Entry.func = CS->getOperand(1);
    FuncsToSort.push_back(Entry);
  }

  std::sort(FuncsToSort.begin(), FuncsToSort.end(), compareEntries);
  for (std::vector<FuncArrayEntry>::iterator Iter = FuncsToSort.begin();
       Iter != FuncsToSort.end();
       ++Iter) {
    Funcs->push_back(Iter->func);
  }
}
Example #6
0
void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageData) {
  CoverageData->setSection(getCoverageSection());
  CoverageData->setAlignment(8);

  Constant *Init = CoverageData->getInitializer();
  // We're expecting { i32, i32, i32, i32, [n x { i8*, i32, i32 }], [m x i8] }
  // for some C. If not, the frontend's given us something broken.
  assert(Init->getNumOperands() == 6 && "bad number of fields in coverage map");
  assert(isa<ConstantArray>(Init->getAggregateElement(4)) &&
         "invalid function list in coverage map");
  ConstantArray *Records = cast<ConstantArray>(Init->getAggregateElement(4));
  for (unsigned I = 0, E = Records->getNumOperands(); I < E; ++I) {
    Constant *Record = Records->getOperand(I);
    Value *V = const_cast<Value *>(Record->getOperand(0))->stripPointerCasts();

    assert(isa<GlobalVariable>(V) && "Missing reference to function name");
    GlobalVariable *Name = cast<GlobalVariable>(V);

    // If we have region counters for this name, we've already handled it.
    auto It = RegionCounters.find(Name);
    if (It != RegionCounters.end())
      continue;

    // Move the name variable to the right section.
    Name->setSection(getNameSection());
    Name->setAlignment(1);
  }
}
Example #7
0
void ClassHierarchyUtils::findClassHierarchy(Module& M) {
  // extract call hierarchy using std::type_info structures rather
  // than debug info. The former works even for when there are anonymous
  // namespaces. type_info structs can be obtained from vtable globals.
  // (for more info, see http://mentorembedded.github.io/cxx-abi/abi.html)
  for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) {
    GlobalVariable* G = &*I;
    if (G->getName().startswith("_ZTV")) {
      if (G->hasInitializer()) {
        SDEBUG("soaap.util.classhierarchy", 3, G->dump());
        ConstantArray* Ginit = cast<ConstantArray>(G->getInitializer());
        // Ginit[1] is the type_info global for this vtable's type
        bool typeInfoFound = false;
        bool primaryVTable = true;
        for (int i=0; i<Ginit->getNumOperands(); i++) {
          // typeinfo will be the first global variable in the array.
          // It's not always at a fixed index so we have to search for it...
          if (GlobalVariable* TI = dyn_cast<GlobalVariable>(Ginit->getOperand(i)->stripPointerCasts())) {
            //TI->dump();
            typeInfoToVTable[TI] = G;
            vTableToTypeInfo[G] = TI;
            processTypeInfo(TI); // process TI recursively (it contains refs to super-class TIs)
            typeInfoFound = true;
            if (primaryVTable) {
              primaryVTable = false;
              vTableToSecondaryVTableMaps[G][0] = i+1;  // i+1 is also the size of the vtable header            
            }
            else {
              // offset_to_top is at the previous index 
              ConstantExpr* offsetValCast = cast<ConstantExpr>(Ginit->getOperand(i-1)->stripPointerCasts());
              ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0)); 
              int offsetToTop = offsetVal->getSExtValue();
              if (offsetToTop > 0) {
                dbgs() << "ERROR: offsetToTop is positive!\n";
                G->dump();
              }
              else {
                offsetToTop *= -1;
              }
              
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n");
              vTableToSecondaryVTableMaps[G][offsetToTop] = i+1;
            }
          }
        }

        if (!typeInfoFound) {
          dbgs() << "ERROR: vtable initializer is not a global variable...\n";
          dbgs() << *G << " = " << *Ginit << "\n";
        }
      }
    }
  }
  
  SDEBUG("soaap.util.classhierarchy", 3, ppClassHierarchy(classToSubclasses));
}
Example #8
0
bool SDFix::fixDestructors2() {
  bool replaced = false;

  for (GlobalVariable& gv : module->getGlobalList()) {
    if (! sd_isVtableName_ref(gv.getName()))
      continue;
    else if (! gv.hasInitializer())
      continue;

    Constant* init = gv.getInitializer();
    assert(init);
    ConstantArray* vtable = dyn_cast<ConstantArray>(init);
    assert(vtable);

    for(unsigned i=0; i<vtable->getNumOperands(); i++) {
      Constant* destructor = sd_getDestructorFunction(vtable->getOperand(i));

      if (destructor == NULL)
        continue;

      // get the type from its name
      unsigned s = destructor->getName().size();
      char type = destructor->getName()[s-3];
      assert('0' <= type && type <= '2');
      unsigned typeInt = type - '0';

      DestructorInfo di(destructor, i);

      if(di.isDefined)
        continue;

      // this only handles the 1 -> 2 conversion
      assert(typeInt == 1);

      Function* f1 = di.getFunction();
      assert(f1);
      std::string gv2Name = f1->getName();
      unsigned l = gv2Name.length();
      gv2Name = gv2Name.replace(l-3, 1, "2");

      Function* f2 = module->getFunction(gv2Name);
      assert(f2 && ! f2->isDeclaration());

      sd_print("Replacing %s with %s inside %s\n",
               f1->getName().data(),
               gv2Name.c_str(),
               gv.getName().data());

      f1->replaceAllUsesWith(f2);
      replaced = true;

    }
  }

  return replaced;
}
Example #9
0
/// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and
/// M1 has all of the global variables.  If M2 contains any functions that are
/// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
/// prune appropriate entries out of M1s list.
static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
                                DenseMap<const Value*, Value*> ValueMap) {
  GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
  if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() ||
      !GV->use_empty()) return;
  
  std::vector<std::pair<Function*, int> > M1Tors, M2Tors;
  ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
  if (!InitList) return;
  
  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){
      if (CS->getNumOperands() != 2) return;  // Not array of 2-element structs.
      
      if (CS->getOperand(1)->isNullValue())
        break;  // Found a null terminator, stop here.
      
      ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
      int Priority = CI ? CI->getSExtValue() : 0;
      
      Constant *FP = CS->getOperand(1);
      if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
        if (CE->isCast())
          FP = CE->getOperand(0);
      if (Function *F = dyn_cast<Function>(FP)) {
        if (!F->isDeclaration())
          M1Tors.push_back(std::make_pair(F, Priority));
        else {
          // Map to M2's version of the function.
          F = cast<Function>(ValueMap[F]);
          M2Tors.push_back(std::make_pair(F, Priority));
        }
      }
    }
  }
  
  GV->eraseFromParent();
  if (!M1Tors.empty()) {
    Constant *M1Init = GetTorInit(M1Tors);
    new GlobalVariable(*M1, M1Init->getType(), false,
                       GlobalValue::AppendingLinkage,
                       M1Init, GlobalName);
  }

  GV = M2->getNamedGlobal(GlobalName);
  assert(GV && "Not a clone of M1?");
  assert(GV->use_empty() && "llvm.ctors shouldn't have uses!");

  GV->eraseFromParent();
  if (!M2Tors.empty()) {
    Constant *M2Init = GetTorInit(M2Tors);
    new GlobalVariable(*M2, M2Init->getType(), false,
                       GlobalValue::AppendingLinkage,
                       M2Init, GlobalName);
  }
}
Example #10
0
static void findUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSetImpl<GlobalValue*> &UsedValues) {
  if (!LLVMUsed) return;

  ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
    if (GlobalValue *GV =
        dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
      UsedValues.insert(GV);
}
Example #11
0
/// Find values that are marked as llvm.used.
static void FindUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
  if (LLVMUsed == 0) return;
  ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());

  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) {
    Value *Operand = Inits->getOperand(i)->stripPointerCastsNoFollowAliases();
    GlobalValue *GV = cast<GlobalValue>(Operand);
    UsedValues.insert(GV);
  }
}
Example #12
0
/// Given a llvm.global_ctors list that we can understand,
/// return a list of the functions and null terminator as a vector.
static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
  if (GV->getInitializer()->isNullValue())
    return std::vector<Function *>();
  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
  std::vector<Function *> Result;
  Result.reserve(CA->getNumOperands());
  for (auto &V : CA->operands()) {
    ConstantStruct *CS = cast<ConstantStruct>(V);
    Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
  }
  return Result;
}
Example #13
0
static std::vector<Function*> parseGlobalCtors(GlobalVariable *GV) {
	if (GV->getInitializer()->isNullValue())
		return std::vector<Function *>();
	ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
	std::vector<Function *> Result;
	Result.reserve(CA->getNumOperands());
	for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) {
		ConstantStruct *CS = cast<ConstantStruct>(*i);
		Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
	}
	return Result;
}
/// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each
/// global in the specified llvm.used list as being used with this directive.
void AsmPrinter::EmitLLVMUsedList(Constant *List) {
  const char *Directive = TAI->getUsedDirective();

  // Should be an array of 'sbyte*'.
  ConstantArray *InitList = dyn_cast<ConstantArray>(List);
  if (InitList == 0) return;
  
  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    O << Directive;
    EmitConstantValueOnly(InitList->getOperand(i));
    O << "\n";
  }
}
Example #15
0
void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageNamesVar) {

  ConstantArray *Names =
      cast<ConstantArray>(CoverageNamesVar->getInitializer());
  for (unsigned I = 0, E = Names->getNumOperands(); I < E; ++I) {
    Constant *NC = Names->getOperand(I);
    Value *V = NC->stripPointerCasts();
    assert(isa<GlobalVariable>(V) && "Missing reference to function name");
    GlobalVariable *Name = cast<GlobalVariable>(V);

    Name->setLinkage(GlobalValue::PrivateLinkage);
    ReferencedNames.push_back(Name);
  }
}
Example #16
0
/// EmitXXStructorList - Emit the ctor or dtor list.  This just emits out the 
/// function pointers, ignoring the init priority.
void ELFWriter::EmitXXStructorList(Constant *List, ELFSection &Xtor) {
  // Should be an array of '{ int, void ()* }' structs.  The first value is the
  // init priority, which we ignore.
  if (!isa<ConstantArray>(List)) return;
  ConstantArray *InitList = cast<ConstantArray>(List);
  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
    if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){
      if (CS->getNumOperands() != 2) return;  // Not array of 2-element structs.

      if (CS->getOperand(1)->isNullValue())
        return;  // Found a null terminator, exit printing.
      // Emit the function pointer.
      EmitGlobalConstant(CS->getOperand(1), Xtor);
    }
}
Example #17
0
/// AnalyzeModule - Scan the module for global debug information.
///
void MachineModuleInfo::AnalyzeModule(Module &M) {
  // Insert functions in the llvm.used array (but not llvm.compiler.used) into
  // UsedFunctions.
  GlobalVariable *GV = M.getGlobalVariable("llvm.used");
  if (!GV || !GV->hasInitializer()) return;

  // Should be an array of 'i8*'.
  ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
  if (InitList == 0) return;

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
    if (Function *F =
          dyn_cast<Function>(InitList->getOperand(i)->stripPointerCasts()))
      UsedFunctions.insert(F);
}
Example #18
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;
}
Example #19
0
/// VisitGlobalInit - The specified lattice value corresponds to a field (or
/// several) in the specified global.  Merge all of the overlapping initializer
/// values into LV (up-to and until it becomes overdefined).
///
static bool VisitGlobalInit(LatticeValue *LV, Constant *Init,
                            unsigned FieldOffset) {
  const TargetData &TD = LV->getParentGraph().getTargetData();

  if (Init->isNullValue())
    return LV->visitGlobalInit(Constant::getNullValue(LV->getFieldType()));
  if (isa<UndefValue>(Init))
    return LV->visitGlobalInit(UndefValue::get(LV->getFieldType()));

  if (LV->getNode()->isArray() &&
      TD.getTypeSize(Init->getType()) > LV->getNode()->getSize()) {
    ConstantArray *CA = cast<ConstantArray>(Init);
    for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
      if (VisitGlobalInit(LV, CA->getOperand(i), FieldOffset))
        return true;
    return false;
  }

NextStep:  // Manual tail recursion

  if (Init->isNullValue())
    return LV->visitGlobalInit(Constant::getNullValue(LV->getFieldType()));
  if (isa<UndefValue>(Init))
    return LV->visitGlobalInit(UndefValue::get(LV->getFieldType()));
  if (Init->getType()->isFirstClassType()) {
    assert(FieldOffset == 0 && "GV Init mismatch!");
    return LV->visitGlobalInit(Init);
  }
  
  if (const StructType *STy = dyn_cast<StructType>(Init->getType())) {
    const StructLayout *SL = TD.getStructLayout(STy);
    unsigned Field = SL->getElementContainingOffset(FieldOffset);
    FieldOffset -= SL->MemberOffsets[Field];
    Init = cast<ConstantStruct>(Init)->getOperand(Field);
    goto NextStep;
  } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Init->getType())) {
    unsigned ElSz = TD.getTypeSize(ATy->getElementType());
    unsigned Idx = FieldOffset / ElSz;
    FieldOffset -= Idx*ElSz;
    Init = cast<ConstantArray>(Init)->getOperand(Idx);
    goto NextStep;
  } else {
    assert(0 && "Unexpected initializer type!");
    return true;
  }
}
Example #20
0
bool CheckInserter::doFinalization(Module &M) {
  // We couldn't directly add an element to a constant array, because doing so
  // changes the type of the constant array.

  // element type of llvm.global_ctors
  StructType *ST = StructType::get(IntType,
                                   PointerType::getUnqual(InitFiniType),
                                   NULL); // end with null

  // Move all existing elements of <GlobalName> to <Constants>.
  vector<Constant *> Constants;
  if (GlobalVariable *GlobalCtors = M.getNamedGlobal("llvm.global_ctors")) {
    ConstantArray *CA = cast<ConstantArray>(GlobalCtors->getInitializer());
    for (unsigned j = 0; j < CA->getNumOperands(); ++j) {
      ConstantStruct *CS = cast<ConstantStruct>(CA->getOperand(j));
      assert(CS->getType() == ST);
      // Assume nobody is using the highest priority, so that <F> will be the
      // first to run as a ctor.
      assert(!cast<ConstantInt>(CS->getOperand(0))->isMinValue(true));
      Constants.push_back(CS);
    }
    GlobalCtors->eraseFromParent();
  }
  // Add <F> with the highest priority.
  Constants.push_back(ConstantStruct::get(ST,
                                          ConstantInt::get(IntType, INT_MIN),
                                          EnterProcess,
                                          NULL));
  // Create the new llvm.global_ctors.
  ArrayType *ArrType = ArrayType::get(ST, Constants.size());
  new GlobalVariable(M,
                     ArrType,
                     true,
                     GlobalValue::AppendingLinkage,
                     ConstantArray::get(ArrType, Constants),
                     "llvm.global_ctors");

  return true;
}
Example #21
0
//
// Method: postOrderInline()
//
// Description:
//  This methods does a post order traversal of the call graph and performs
//  bottom-up inlining of the DSGraphs.
//
void
BUDataStructures::postOrderInline (Module & M) {
  // Variables used for Tarjan SCC-finding algorithm.  These are passed into
  // the recursive function used to find SCCs.
  std::vector<const Function*> Stack;
  std::map<const Function*, unsigned> ValMap;
  unsigned NextID = 1;


  // Do post order traversal on the global ctors. Use this information to update
  // the globals graph.
  const char *Name = "llvm.global_ctors";
  GlobalVariable *GV = M.getNamedGlobal(Name);
  if (GV && !(GV->isDeclaration()) && !(GV->hasLocalLinkage())) {
    // Should be an array of '{ int, void ()* }' structs.  The first value is
    // the init priority, which we ignore.
    ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
    if (InitList) {
      for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
        if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
          if (CS->getNumOperands() != 2)
            break; // Not array of 2-element structs.
          Constant *FP = CS->getOperand(1);
          if (FP->isNullValue())
            break;  // Found a null terminator, exit.

          if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
            if (CE->isCast())
              FP = CE->getOperand(0);
          Function *F = dyn_cast<Function>(FP);
          if (F && !F->isDeclaration() && !ValMap.count(F)) {
            calculateGraphs(F, Stack, NextID, ValMap);
            CloneAuxIntoGlobal(getDSGraph(*F));
          }
        }
      GlobalsGraph->removeTriviallyDeadNodes();
      GlobalsGraph->maskIncompleteMarkers();

      // Mark external globals incomplete.
      GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals);
      GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
      GlobalsGraph->computeIntPtrFlags();

      //
      // Create equivalence classes for aliasing globals so that we only need to
      // record one global per DSNode.
      //
      formGlobalECs();
      // propogte information calculated
      // from the globals graph to the other graphs.
      for (Module::iterator F = M.begin(); F != M.end(); ++F) {
        if (!(F->isDeclaration())){
          DSGraph *Graph  = getDSGraph(*F);
          cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes |
                           DSGraph::DontCloneAuxCallNodes);
          Graph->buildCallGraph(callgraph, GlobalFunctionList, filterCallees);
          Graph->maskIncompleteMarkers();
          Graph->markIncompleteNodes(DSGraph::MarkFormalArgs |
                                     DSGraph::IgnoreGlobals);
          Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
          Graph->computeIntPtrFlags();
        }
      }
    }
  }

  //
  // Start the post order traversal with the main() function.  If there is no
  // main() function, don't worry; we'll have a separate traversal for inlining
  // graphs for functions not reachable from main().
  //
  Function *MainFunc = M.getFunction ("main");
  if (MainFunc && !MainFunc->isDeclaration()) {
    calculateGraphs(MainFunc, Stack, NextID, ValMap);
    CloneAuxIntoGlobal(getDSGraph(*MainFunc));
  }

  //
  // Calculate the graphs for any functions that are unreachable from main...
  //
  for (Function &F : M)
    if (!F.isDeclaration() && !ValMap.count(&F)) {
      if (MainFunc)
        DEBUG(errs() << debugname << ": Function unreachable from main: "
        << F.getName() << "\n");
      calculateGraphs(&F, Stack, NextID, ValMap);     // Calculate all graphs.
      CloneAuxIntoGlobal(getDSGraph(F));

      // Mark this graph as processed.  Do this by finding all functions
      // in the graph that map to it, and mark them visited.
      // Note that this really should be handled neatly by calculateGraphs
      // itself, not here.  However this catches the worst offenders.
      DSGraph *G = getDSGraph(F);
      for(DSGraph::retnodes_iterator RI = G->retnodes_begin(),
          RE = G->retnodes_end(); RI != RE; ++RI) {
        if (getDSGraph(*RI->first) == G) {
          if (!ValMap.count(RI->first))
            ValMap[RI->first] = ~0U;
          else
            assert(ValMap[RI->first] == ~0U);
        }
      }
    }
  return;
}
Example #22
0
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);
          }
        }
      }
    }