//===-- TypeFinder.cpp - Implement the TypeFinder class -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TypeFinder class for the IR library.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/TypeFinder.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
using namespace llvm;

void TypeFinder::run(const Module &M, bool onlyNamed) {
  OnlyNamed = onlyNamed;

  // 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());
    if (const Value *Aliasee = I->getAliasee())
      incorporateValue(Aliasee);
  }

  // Get types from functions.
  SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
  for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
    incorporateType(FI->getType());

    // First incorporate the arguments.
    for (Function::const_arg_iterator AI = FI->arg_begin(),
           AE = FI->arg_end(); AI != AE; ++AI)
      incorporateValue(AI);

    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.
        incorporateType(I.getType());

        // Incorporate non-instruction operand types. (We are incorporating all
        // instructions with this loop.)
        for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
             OI != OE; ++OI)
          if (!isa<Instruction>(OI))
            incorporateValue(*OI);

        // Incorporate types hiding in metadata.
        I.getAllMetadataOtherThanDebugLoc(MDForInst);
        for (unsigned i = 0, e = MDForInst.size(); i != e; ++i)
          incorporateMDNode(MDForInst[i].second);

        MDForInst.clear();
      }
  }

  for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
         E = M.named_metadata_end(); I != E; ++I) {
    const NamedMDNode *NMD = I;
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
      incorporateMDNode(NMD->getOperand(i));
  }
}

void TypeFinder::clear() {
  VisitedConstants.clear();
  VisitedTypes.clear();
  StructTypes.clear();
}

/// incorporateType - This method adds the type to the list of used structures
/// if it's not in there already.
void TypeFinder::incorporateType(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 (StructType *STy = dyn_cast<StructType>(Ty))
    if (!OnlyNamed || STy->hasName())
      StructTypes.push_back(STy);

  // 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 TypeFinder::incorporateValue(const Value *V) {
  if (const MDNode *M = dyn_cast<MDNode>(V))
    return incorporateMDNode(M);

  if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;

  // Already visited?
  if (!VisitedConstants.insert(V).second)
    return;

  // Check this type.
  incorporateType(V->getType());

  // If this is an instruction, we incorporate it separately.
  if (isa<Instruction>(V))
    return;

  // Look in operands for types.
  const User *U = cast<User>(V);
  for (Constant::const_op_iterator I = U->op_begin(),
         E = U->op_end(); I != E;++I)
    incorporateValue(*I);
}

/// incorporateMDNode - This method is used to walk the operands of an MDNode to
/// find types hiding within.
void TypeFinder::incorporateMDNode(const MDNode *V) {
  // Already visited?
  if (!VisitedConstants.insert(V).second)
    return;

  // Look in operands for types.
  for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i)
    if (Value *Op = V->getOperand(i))
      incorporateValue(Op);
}
