/// AddCatchInfo - Extract the personality and type infos from an eh.selector
/// call, and add them to the specified machine basic block.
void llvm::AddCatchInfo(CallInst &I, MachineModuleInfo *MMI,
                        MachineBasicBlock *MBB) {
  // Inform the MachineModuleInfo of the personality for this landing pad.
  ConstantExpr *CE = cast<ConstantExpr>(I.getOperand(2));
  assert(CE->getOpcode() == Instruction::BitCast &&
         isa<Function>(CE->getOperand(0)) &&
         "Personality should be a function");
  MMI->addPersonality(MBB, cast<Function>(CE->getOperand(0)));

  // Gather all the type infos for this landing pad and pass them along to
  // MachineModuleInfo.
  std::vector<GlobalVariable *> TyInfo;
  unsigned N = I.getNumOperands();

  for (unsigned i = N - 1; i > 2; --i) {
    if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(i))) {
      unsigned FilterLength = CI->getZExtValue();
      unsigned FirstCatch = i + FilterLength + !FilterLength;
      assert (FirstCatch <= N && "Invalid filter length");

      if (FirstCatch < N) {
        TyInfo.reserve(N - FirstCatch);
        for (unsigned j = FirstCatch; j < N; ++j)
          TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
        MMI->addCatchTypeInfo(MBB, TyInfo);
        TyInfo.clear();
      }

      if (!FilterLength) {
        // Cleanup.
        MMI->addCleanup(MBB);
      } else {
        // Filter.
        TyInfo.reserve(FilterLength - 1);
        for (unsigned j = i + 1; j < FirstCatch; ++j)
          TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
        MMI->addFilterTypeInfo(MBB, TyInfo);
        TyInfo.clear();
      }

      N = i;
    }
  }

  if (N > 3) {
    TyInfo.reserve(N - 3);
    for (unsigned j = 3; j < N; ++j)
      TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
    MMI->addCatchTypeInfo(MBB, TyInfo);
  }
}
/// IsConstantOffsetFromGlobal - If this constant is actually a constant offset
/// from a global, return the global and the constant.  Because of
/// constantexprs, this function is recursive.
static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV,
                                       int64_t &Offset, const TargetData &TD) {
  // Trivial case, constant is the global.
  if ((GV = dyn_cast<GlobalValue>(C))) {
    Offset = 0;
    return true;
  }
  
  // Otherwise, if this isn't a constant expr, bail out.
  ConstantExpr *CE = dyn_cast<ConstantExpr>(C);
  if (!CE) return false;
  
  // Look through ptr->int and ptr->ptr casts.
  if (CE->getOpcode() == Instruction::PtrToInt ||
      CE->getOpcode() == Instruction::BitCast)
    return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD);
  
  // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5)    
  if (CE->getOpcode() == Instruction::GetElementPtr) {
    // Cannot compute this if the element type of the pointer is missing size
    // info.
    if (!cast<PointerType>(CE->getOperand(0)->getType())->getElementType()->isSized())
      return false;
    
    // If the base isn't a global+constant, we aren't either.
    if (!IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD))
      return false;
    
    // Otherwise, add any offset that our operands provide.
    gep_type_iterator GTI = gep_type_begin(CE);
    for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i, ++GTI) {
      ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(i));
      if (!CI) return false;  // Index isn't a simple constant?
      if (CI->getZExtValue() == 0) continue;  // Not adding anything.
      
      if (const StructType *ST = dyn_cast<StructType>(*GTI)) {
        // N = N + Offset
        Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue());
      } else {
        const SequentialType *SQT = cast<SequentialType>(*GTI);
        Offset += TD.getTypeSize(SQT->getElementType())*CI->getSExtValue();
      }
    }
    return true;
  }
  
  return false;
}
Example #3
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 #4
0
void ControlFlowIntegrity::PatchDtorFunctions(void) {
  GlobalVariable *global_dtors = _M.getNamedGlobal("llvm.global_dtors");

  // check for dtor section
  if (!global_dtors || !global_dtors->getOperand(0)) {
    return;
  }

  Constant *c = global_dtors->getInitializer();
  if (!c)
    report_fatal_error("llvm.global_dtors without initializer!", false);

  ConstantArray *CA = dyn_cast<ConstantArray>(c);
  if (!CA)
    report_fatal_error("Cast to ConstantArray failed", true);

  for (Value *Op : ValueOpRange(*CA)) {
    ConstantStruct *CS = dyn_cast<ConstantStruct>(Op);
    if (!CS)
      report_fatal_error("Cast to ConstantStruct failed", true);

    Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      break; // found a NULL termintator, stop here

    Function *F = dyn_cast_or_null<Function>(FP);
    if (F == NULL) {
      // Strip off constant expression cast
      ConstantExpr *CE = dyn_cast<ConstantExpr>(FP);
      if (!CE)
        report_fatal_error("Cast to ConstantExpr failed", true);
      if (CE->isCast()) {
        FP = CE->getOperand(0);
      }
      F = dyn_cast_or_null<Function>(FP);
    }

    if (!F)
      report_fatal_error("Cast to Function failed", true);

    // set visibility to hidden (do not export), unless it is already
    // local (for ex. static), in which case we have to make it non-static
    if (F->hasLocalLinkage()) {
      F->setLinkage(llvm::GlobalValue::ExternalLinkage);
    }
    F->setVisibility(GlobalValue::HiddenVisibility);

    _FiniFunctions.insert(F->getName());
  }

  if (global_dtors->getNumUses() > 0)
    report_fatal_error("llvm.global_dtors uses count is > 0!", false);

  global_dtors->removeFromParent();

}
Example #5
0
/// Return true if the specified constant can be handled by the code generator.
/// We don't want to generate something like:
///   void *X = &X/42;
/// because the code generator doesn't have a relocation that can handle that.
///
/// This function should be called if C was not found (but just got inserted)
/// in SimpleConstants to avoid having to rescan the same constants all the
/// time.
static bool
isSimpleEnoughValueToCommitHelper(Constant *C,
                                  SmallPtrSetImpl<Constant *> &SimpleConstants,
                                  const DataLayout &DL) {
  // Simple global addresses are supported, do not allow dllimport or
  // thread-local globals.
  if (auto *GV = dyn_cast<GlobalValue>(C))
    return !GV->hasDLLImportStorageClass() && !GV->isThreadLocal();

  // Simple integer, undef, constant aggregate zero, etc are all supported.
  if (C->getNumOperands() == 0 || isa<BlockAddress>(C))
    return true;

  // Aggregate values are safe if all their elements are.
  if (isa<ConstantArray>(C) || isa<ConstantStruct>(C) ||
      isa<ConstantVector>(C)) {
    for (Value *Op : C->operands())
      if (!isSimpleEnoughValueToCommit(cast<Constant>(Op), SimpleConstants, DL))
        return false;
    return true;
  }

  // We don't know exactly what relocations are allowed in constant expressions,
  // so we allow &global+constantoffset, which is safe and uniformly supported
  // across targets.
  ConstantExpr *CE = cast<ConstantExpr>(C);
  switch (CE->getOpcode()) {
  case Instruction::BitCast:
    // Bitcast is fine if the casted value is fine.
    return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);

  case Instruction::IntToPtr:
  case Instruction::PtrToInt:
    // int <=> ptr is fine if the int type is the same size as the
    // pointer type.
    if (DL.getTypeSizeInBits(CE->getType()) !=
        DL.getTypeSizeInBits(CE->getOperand(0)->getType()))
      return false;
    return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);

  // GEP is fine if it is simple + constant offset.
  case Instruction::GetElementPtr:
    for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
      if (!isa<ConstantInt>(CE->getOperand(i)))
        return false;
    return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);

  case Instruction::Add:
    // We allow simple+cst.
    if (!isa<ConstantInt>(CE->getOperand(1)))
      return false;
    return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);
  }
  return false;
}
static GlobalValue *getAliaseeGV(GlobalAlias *GA) {
  Constant *C = GA->getAliasee();
  assert(C && "Must alias something");

  if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
    return GV;

  ConstantExpr *CE = cast<ConstantExpr>(C);
  assert((CE->getOpcode() == Instruction::BitCast ||
          CE->getOpcode() == Instruction::AddrSpaceCast ||
          CE->getOpcode() == Instruction::GetElementPtr) &&
         "Unsupported aliasee");

  return cast<GlobalValue>(CE->getOperand(0));
}
Example #7
0
GlobalValue *GlobalAlias::getAliasedGlobal() {
  Constant *C = getAliasee();
  if (C == 0) return 0;
  
  if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
    return GV;

  ConstantExpr *CE = cast<ConstantExpr>(C);
  assert((CE->getOpcode() == Instruction::BitCast ||
          CE->getOpcode() == Instruction::AddrSpaceCast ||
          CE->getOpcode() == Instruction::GetElementPtr) &&
         "Unsupported aliasee");
  
  return cast<GlobalValue>(CE->getOperand(0));
}
Example #8
0
static Constant*
sd_getDestructorFunction(Constant* vtblElement) {
  ConstantExpr* bcExpr = NULL;

  // if this a constant bitcast expression, this might be a vthunk
  if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) && bcExpr->getOpcode() == BITCAST_OPCODE) {
    Constant* operand = bcExpr->getOperand(0);

    // this is a vthunk
    if (sd_isDestructorName(operand->getName())) {
      return operand;
    }
  }

  return NULL;
}
Example #9
0
static Constant*
sd_isRTTI(Constant* vtblElement) {
  ConstantExpr* bcExpr = NULL;

  // if this a constant bitcast expression, this might be a vthunk
  if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) &&
      bcExpr->getOpcode() == Instruction::BitCast) {
    Constant* operand = bcExpr->getOperand(0);

    // this is a vthunk
    if (operand->getName().startswith("_ZTI")) {
      return operand;
    }
  }

  return NULL;
}
Example #10
0
std::string readAnnotate(Function *f) {
  std::string annotation = "";

  // Get annotation variable
  GlobalVariable *glob =
      f->getParent()->getGlobalVariable("llvm.global.annotations");

  if (glob != NULL) {
    // Get the array
    if (ConstantArray *ca = dyn_cast<ConstantArray>(glob->getInitializer())) {
      for (unsigned i = 0; i < ca->getNumOperands(); ++i) {
        // Get the struct
        if (ConstantStruct *structAn =
                dyn_cast<ConstantStruct>(ca->getOperand(i))) {
          if (ConstantExpr *expr =
                  dyn_cast<ConstantExpr>(structAn->getOperand(0))) {
            // If it's a bitcast we can check if the annotation is concerning
            // the current function
            if (expr->getOpcode() == Instruction::BitCast &&
                expr->getOperand(0) == f) {
              ConstantExpr *note = cast<ConstantExpr>(structAn->getOperand(1));
              // If it's a GetElementPtr, that means we found the variable
              // containing the annotations
              if (note->getOpcode() == Instruction::GetElementPtr) {
                if (GlobalVariable *annoteStr =
                        dyn_cast<GlobalVariable>(note->getOperand(0))) {
                  if (ConstantDataSequential *data =
                          dyn_cast<ConstantDataSequential>(
                              annoteStr->getInitializer())) {
                    if (data->isString()) {
                      annotation += data->getAsString().lower() + " ";
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return annotation;
}
Example #11
0
void ControlFlowIntegrity::ParseAnnotations(void) {
  GlobalVariable *global_ctors = _M.getNamedGlobal("llvm.global.annotations");

  // check for ctor section
  if (!global_ctors || !global_ctors->getOperand(0)) {
    return;
  }

  Constant *c = global_ctors->getInitializer();
  if (!c)
    report_fatal_error("llvm.global.annotations without initializer!", false);

  ConstantArray *CA = dyn_cast<ConstantArray>(c);
  if (!CA)
    report_fatal_error("Cast to ConstantArray failed", true);

  for (Value *Op : ValueOpRange(*CA)) {
    ConstantStruct *CS = dyn_cast<ConstantStruct>(Op);
    if (!CS)
      report_fatal_error("Cast to ConstantStruct failed", true);

    Constant *FP = CS->getOperand(0);
    if (FP->isNullValue())
      break; // found a NULL termintator, stop here

    ConstantExpr *CE;
    Function *F = dyn_cast_or_null<Function>(FP);

    if (F == NULL) {
      // Strip off constant expression cast
      CE = dyn_cast<ConstantExpr>(FP);
      if (!CE)
        report_fatal_error("Cast to ConstantExpr failed", true);
      if (CE->isCast()) {
        FP = CE->getOperand(0);
        F = dyn_cast_or_null<Function>(FP);
      }
    }

    if (!F)
      report_fatal_error("Cast to Function failed", true);

    Constant *SP = CS->getOperand(1);
    if (SP->isNullValue())
      break; // found a NULL termintator, stop here

    // Strip off constant expression cast
    CE = dyn_cast<ConstantExpr>(SP);
    if (!CE)
      report_fatal_error("Cast to ConstantExpr failed", true);
    if (CE->isCast()) {
      SP = CE->getOperand(0);
    }

    Value *V = SP->getOperand(0);
    GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(V);
    if (!GV)
      report_fatal_error("Cast to GlobalVariable failed", false);
    assert(GV && "cast to GlobalVariable failed");

    Constant *cval = GV->getInitializer();
    const StringRef s = (cast<ConstantDataArray>(cval))->getAsCString();
    if (s == ANNOTATION_IGNORE_BLOCK) {
      _IgnoredBlocksFunctions.insert(F->getName());
    }
  }

  if (global_ctors->getNumUses() > 0)
    report_fatal_error("llvm.global.annotations uses count is > 0", false);
}
Example #12
0
//
// Method: runOnModule()
//
// Description:
//  Entry point for this LLVM pass.
//  Search for all call sites to casted functions.
//  Check if they only differ in an argument type
//  Cast the argument, and call the original function
//
// Inputs:
//  M - A reference to the LLVM module to transform
//
// Outputs:
//  M - The transformed LLVM module.
//
// Return value:
//  true  - The module was modified.
//  false - The module was not modified.
//
bool ArgCast::runOnModule(Module& M) {

  std::vector<CallInst*> worklist;
  for (Module::iterator I = M.begin(); I != M.end(); ++I) {
    if (I->mayBeOverridden())
      continue;
    // Find all uses of this function
    for(Value::user_iterator ui = I->user_begin(), ue = I->user_end(); ui != ue; ) {
      // check if is ever casted to a different function type
      ConstantExpr *CE = dyn_cast<ConstantExpr>(*ui++);
      if(!CE)
        continue;
      if (CE->getOpcode() != Instruction::BitCast)
        continue;
      if(CE->getOperand(0) != I)
        continue;
      const PointerType *PTy = dyn_cast<PointerType>(CE->getType());
      if (!PTy)
        continue;
      const Type *ETy = PTy->getElementType();
      const FunctionType *FTy  = dyn_cast<FunctionType>(ETy); 
      if(!FTy)
        continue;
      // casting to a varargs funtion
      // or function with same number of arguments
      // possibly varying types of arguments
      
      if(FTy->getNumParams() != I->arg_size() && !FTy->isVarArg())
        continue;
      for(Value::user_iterator uii = CE->user_begin(),
          uee = CE->user_end(); uii != uee; ++uii) {
        // Find all uses of the casted value, and check if it is 
        // used in a Call Instruction
        if (CallInst* CI = dyn_cast<CallInst>(*uii)) {
          // Check that it is the called value, and not an argument
          if(CI->getCalledValue() != CE) 
            continue;
          // Check that the number of arguments passed, and expected
          // by the function are the same.
          if(!I->isVarArg()) {
            if(CI->getNumOperands() != I->arg_size() + 1)
              continue;
          } else {
            if(CI->getNumOperands() < I->arg_size() + 1)
              continue;
          }
          // If so, add to worklist
          worklist.push_back(CI);
        }
      }
    }
  }

  // Proces the worklist of potential call sites to transform
  while(!worklist.empty()) {
    CallInst *CI = worklist.back();
    worklist.pop_back();
    // Get the called Function
    Function *F = cast<Function>(CI->getCalledValue()->stripPointerCasts());
    const FunctionType *FTy = F->getFunctionType();

    SmallVector<Value*, 8> Args;
    unsigned i =0;
    for(i =0; i< FTy->getNumParams(); ++i) {
      Type *ArgType = CI->getOperand(i+1)->getType();
      Type *FormalType = FTy->getParamType(i);
      // If the types for this argument match, just add it to the
      // parameter list. No cast needs to be inserted.
      if(ArgType == FormalType) {
        Args.push_back(CI->getOperand(i+1));
      }
      else if(ArgType->isPointerTy() && FormalType->isPointerTy()) {
        CastInst *CastI = CastInst::CreatePointerCast(CI->getOperand(i+1), 
                                                      FormalType, "", CI);
        Args.push_back(CastI);
      } else if (ArgType->isIntegerTy() && FormalType->isIntegerTy()) {
        unsigned SrcBits = ArgType->getScalarSizeInBits();
        unsigned DstBits = FormalType->getScalarSizeInBits();
        if(SrcBits > DstBits) {
          CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), 
                                                        FormalType, true, "", CI);
          Args.push_back(CastI);
        } else {
          if (F->getAttributes().hasAttribute(i+1, Attribute::SExt)) {
            CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), 
                                                          FormalType, true, "", CI);
            Args.push_back(CastI);
          } else if (F->getAttributes().hasAttribute(i+1, Attribute::ZExt)) {
            CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), 
                                                          FormalType, false, "", CI);
            Args.push_back(CastI);
          } else {
            // Use ZExt in default case.
            // Derived from InstCombine. Also, the only reason this should happen
            // is mismatched prototypes.
            // Seen in case of integer constants which get interpreted as i32, 
            // even if being used as i64.
            // TODO: is this correct?
            CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), 
                                                          FormalType, false, "", CI);
            Args.push_back(CastI);
          } 
        } 
      } else {
        DEBUG(ArgType->dump());
        DEBUG(FormalType->dump());
        break;
      }
    }

    // If we found an argument we could not cast, try the next instruction
    if(i != FTy->getNumParams()) {
      continue;
    }

    if(FTy->isVarArg()) {
      for(; i< CI->getNumOperands() - 1 ;i++) {
        Args.push_back(CI->getOperand(i+1));
      }
    }

    // else replace the call instruction
    CallInst *CINew = CallInst::Create(F, Args, "", CI);
    CINew->setCallingConv(CI->getCallingConv());
    CINew->setAttributes(CI->getAttributes());
    if(!CI->use_empty()) {
      CastInst *RetCast;
      if(CI->getType() != CINew->getType()) {
        if(CI->getType()->isPointerTy() && CINew->getType()->isPointerTy())
          RetCast = CastInst::CreatePointerCast(CINew, CI->getType(), "", CI);
        else if(CI->getType()->isIntOrIntVectorTy() && CINew->getType()->isIntOrIntVectorTy())
          RetCast = CastInst::CreateIntegerCast(CINew, CI->getType(), false, "", CI);
        else if(CI->getType()->isIntOrIntVectorTy() && CINew->getType()->isPointerTy())
          RetCast = CastInst::CreatePointerCast(CINew, CI->getType(), "", CI);
        else if(CI->getType()->isPointerTy() && CINew->getType()->isIntOrIntVectorTy()) 
          RetCast = new IntToPtrInst(CINew, CI->getType(), "", CI);
        else {
          // TODO: I'm not sure what right behavior is here, but this case should be handled.
          llvm_unreachable("Unexpected type conversion in call!");
          abort();
        }
        CI->replaceAllUsesWith(RetCast);
      } else {
        CI->replaceAllUsesWith(CINew);
      }
    }

    // Debug printing
    DEBUG(errs() << "ARGCAST:");
    DEBUG(errs() << "ERASE:");
    DEBUG(CI->dump());
    DEBUG(errs() << "ARGCAST:");
    DEBUG(errs() << "ADDED:");
    DEBUG(CINew->dump());

    CI->eraseFromParent();
    numChanged++;
  }
  return true;
}
Example #13
-1
        virtual bool runOnFunction(Function &F) {
            //F.dump();
            bool changed = false;
            for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) {
                LoadInst *li = dyn_cast<LoadInst>(&*inst_it);
                if (!li) continue;

                ConstantExpr *ce = dyn_cast<ConstantExpr>(li->getOperand(0));
                // Not 100% sure what the isGEPWithNoNotionalOverIndexing() means, but
                // at least it checks if it's a gep:
                if (ce && ce->isGEPWithNoNotionalOverIndexing() && ce->getOperand(0)->getType() == g.llvm_flavor_type_ptr) {
                    changed = handleFlavor(li, ce);
                }

                GlobalVariable *gv = dyn_cast<GlobalVariable>(li->getOperand(0));
                if (!gv) continue;

                llvm::Type* gv_t = gv->getType();

                if (gv_t == g.llvm_bool_type_ptr->getPointerTo()) {
                    changed = handleBool(li, gv) || changed;
                    continue;
                }

                if (gv_t == g.llvm_class_type_ptr->getPointerTo()) {
                    changed = handleCls(li, gv) || changed;
                    continue;
                }
            }

            return changed;
        }