#include "llvm/IR/TypeFinder.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include <utility>
using namespace llvm;
void TypeFinder::run(const Module &M, bool onlyNamed) {
OnlyNamed = onlyNamed;
for (const auto &G : M.globals()) {
incorporateType(G.getType());
if (G.hasInitializer())
incorporateValue(G.getInitializer());
}
for (const auto &A : M.aliases()) {
incorporateType(A.getType());
if (const Value *Aliasee = A.getAliasee())
incorporateValue(Aliasee);
}
SmallVector<std::pair<unsigned, MDNode *>, 4> MDForInst;
for (const Function &FI : M) {
incorporateType(FI.getType());
for (const Use &U : FI.operands())
incorporateValue(U.get());
for (const auto &A : FI.args())
incorporateValue(&A);
for (const BasicBlock &BB : FI)
for (const Instruction &I : BB) {
incorporateType(I.getType());
for (const auto &O : I.operands())
if (&*O && !isa<Instruction>(&*O))
incorporateValue(&*O);
I.getAllMetadataOtherThanDebugLoc(MDForInst);
for (const auto &MD : MDForInst)
incorporateMDNode(MD.second);
MDForInst.clear();
}
}
for (const auto &NMD : M.named_metadata())
for (const auto &MDOp : NMD.operands())
incorporateMDNode(MDOp);
}
void TypeFinder::clear() {
VisitedConstants.clear();
VisitedTypes.clear();
StructTypes.clear();
}
void TypeFinder::incorporateType(Type *Ty) {
if (!VisitedTypes.insert(Ty).second)
return;
SmallVector<Type *, 4> TypeWorklist;
TypeWorklist.push_back(Ty);
do {
Ty = TypeWorklist.pop_back_val();
if (StructType *STy = dyn_cast<StructType>(Ty))
if (!OnlyNamed || STy->hasName())
StructTypes.push_back(STy);
for (Type::subtype_reverse_iterator I = Ty->subtype_rbegin(),
E = Ty->subtype_rend();
I != E; ++I)
if (VisitedTypes.insert(*I).second)
TypeWorklist.push_back(*I);
} while (!TypeWorklist.empty());
}
void TypeFinder::incorporateValue(const Value *V) {
if (const auto *M = dyn_cast<MetadataAsValue>(V)) {
if (const auto *N = dyn_cast<MDNode>(M->getMetadata()))
return incorporateMDNode(N);
if (const auto *MDV = dyn_cast<ValueAsMetadata>(M->getMetadata()))
return incorporateValue(MDV->getValue());
return;
}
if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;
if (!VisitedConstants.insert(V).second)
return;
incorporateType(V->getType());
if (isa<Instruction>(V))
return;
const User *U = cast<User>(V);
for (const auto &I : U->operands())
incorporateValue(&*I);
}
void TypeFinder::incorporateMDNode(const MDNode *V) {
if (!VisitedMetadata.insert(V).second)
return;
for (Metadata *Op : V->operands()) {
if (!Op)
continue;
if (auto *N = dyn_cast<MDNode>(Op)) {
incorporateMDNode(N);
continue;
}
if (auto *C = dyn_cast<ConstantAsMetadata>(Op)) {
incorporateValue(C->getValue());
continue;
}
}
}