-namespace {
- class TypeFinder {
- // To avoid walking constant expressions multiple times and other IR
- // objects, we keep several helper maps.
- DenseSet<const Value*> VisitedConstants;
- DenseSet<const Type*> VisitedTypes;
-
- TypePrinting &TP;
- std::vector<const Type*> &NumberedTypes;
- public:
- TypeFinder(TypePrinting &tp, std::vector<const Type*> &numberedTypes)
- : TP(tp), NumberedTypes(numberedTypes) {}
-
- void Run(const Module &M) {
- // Get types from the type symbol table. This gets opaque types referened
- // only through derived named types.
- const TypeSymbolTable &ST = M.getTypeSymbolTable();
- for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end();
- TI != E; ++TI)
- IncorporateType(TI->second);
-
- // Get types from global variables.
- for (Module::const_global_iterator I = M.global_begin(),
- E = M.global_end(); I != E; ++I) {
- IncorporateType(I->getType());
- if (I->hasInitializer())
- IncorporateValue(I->getInitializer());
- }
-
- // Get types from aliases.
- for (Module::const_alias_iterator I = M.alias_begin(),
- E = M.alias_end(); I != E; ++I) {
- IncorporateType(I->getType());
- IncorporateValue(I->getAliasee());
- }
-
- // Get types from functions.
- for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
- IncorporateType(FI->getType());
-
- for (Function::const_iterator BB = FI->begin(), E = FI->end();
- BB != E;++BB)
- for (BasicBlock::const_iterator II = BB->begin(),
- E = BB->end(); II != E; ++II) {
- const Instruction &I = *II;
- // Incorporate the type of the instruction and all its operands.
- IncorporateType(I.getType());
- for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
- OI != OE; ++OI)
- IncorporateValue(*OI);
- }
- }
- }
-
- private:
- void IncorporateType(const Type *Ty) {
- // Check to see if we're already visited this type.
- if (!VisitedTypes.insert(Ty).second)
- return;
-
- // If this is a structure or opaque type, add a name for the type.
- if (((isa<StructType>(Ty) && cast<StructType>(Ty)->getNumElements())
- || isa<OpaqueType>(Ty)) && !TP.hasTypeName(Ty)) {
- TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size())));
- NumberedTypes.push_back(Ty);
- }
-
- // Recursively walk all contained types.
- for (Type::subtype_iterator I = Ty->subtype_begin(),
- E = Ty->subtype_end(); I != E; ++I)
- IncorporateType(*I);
- }
-
- /// IncorporateValue - This method is used to walk operand lists finding
- /// types hiding in constant expressions and other operands that won't be
- /// walked in other ways. GlobalValues, basic blocks, instructions, and
- /// inst operands are all explicitly enumerated.
- void IncorporateValue(const Value *V) {
- if (V == 0 || !isa<Constant>(V) || isa<GlobalValue>(V)) return;
-
- // Already visited?
- if (!VisitedConstants.insert(V).second)
- return;
-
- // Check this type.
- IncorporateType(V->getType());
-
- // Look in operands for types.
- const Constant *C = cast<Constant>(V);
- for (Constant::const_op_iterator I = C->op_begin(),
- E = C->op_end(); I != E;++I)
- IncorporateValue(*I);
- }
- };
-} // end anonymous namespace
-
-
-/// AddModuleTypesToPrinter - Add all of the symbolic type names for types in
-/// the specified module to the TypePrinter and all numbered types to it and the
-/// NumberedTypes table.
-static void AddModuleTypesToPrinter(TypePrinting &TP,
- std::vector<const Type*> &NumberedTypes,
- const Module *M) {
- if (M == 0) return;
-
- // If the module has a symbol table, take all global types and stuff their
- // names into the TypeNames map.
- const TypeSymbolTable &ST = M->getTypeSymbolTable();
- for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end();
- TI != E; ++TI) {
- const Type *Ty = cast<Type>(TI->second);
-
- // As a heuristic, don't insert pointer to primitive types, because
- // they are used too often to have a single useful name.
- if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- const Type *PETy = PTy->getElementType();
- if ((PETy->isPrimitiveType() || PETy->isInteger()) &&
- !isa<OpaqueType>(PETy))
- continue;