#include "llvm/Module.h"
#include "llvm/InstrTypes.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GVMaterializer.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/LeakDetector.h"
#include "SymbolTableListTraitsImpl.h"
#include <algorithm>
#include <cstdarg>
#include <cstdlib>
using namespace llvm;
template class llvm::SymbolTableListTraits<Function, Module>;
template class llvm::SymbolTableListTraits<GlobalVariable, Module>;
template class llvm::SymbolTableListTraits<GlobalAlias, Module>;
Module::Module(StringRef MID, LLVMContext& C)
: Context(C), Materializer(NULL), ModuleID(MID) {
ValSymTab = new ValueSymbolTable();
NamedMDSymTab = new StringMap<NamedMDNode *>();
Context.addModule(this);
}
Module::~Module() {
Context.removeModule(this);
dropAllReferences();
GlobalList.clear();
FunctionList.clear();
AliasList.clear();
LibraryList.clear();
NamedMDList.clear();
delete ValSymTab;
delete static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab);
}
Module::Endianness Module::getEndianness() const {
StringRef temp = DataLayout;
Module::Endianness ret = AnyEndianness;
while (!temp.empty()) {
std::pair<StringRef, StringRef> P = getToken(temp, "-");
StringRef token = P.first;
temp = P.second;
if (token[0] == 'e') {
ret = LittleEndian;
} else if (token[0] == 'E') {
ret = BigEndian;
}
}
return ret;
}
Module::PointerSize Module::getPointerSize() const {
StringRef temp = DataLayout;
Module::PointerSize ret = AnyPointerSize;
while (!temp.empty()) {
std::pair<StringRef, StringRef> TmpP = getToken(temp, "-");
temp = TmpP.second;
TmpP = getToken(TmpP.first, ":");
StringRef token = TmpP.second, signalToken = TmpP.first;
if (signalToken[0] == 'p') {
int size = 0;
getToken(token, ":").first.getAsInteger(10, size);
if (size == 32)
ret = Pointer32;
else if (size == 64)
ret = Pointer64;
}
}
return ret;
}
GlobalValue *Module::getNamedValue(StringRef Name) const {
return cast_or_null<GlobalValue>(getValueSymbolTable().lookup(Name));
}
unsigned Module::getMDKindID(StringRef Name) const {
return Context.getMDKindID(Name);
}
void Module::getMDKindNames(SmallVectorImpl<StringRef> &Result) const {
return Context.getMDKindNames(Result);
}
Constant *Module::getOrInsertFunction(StringRef Name,
FunctionType *Ty,
AttrListPtr AttributeList) {
GlobalValue *F = getNamedValue(Name);
if (F == 0) {
Function *New = Function::Create(Ty, GlobalVariable::ExternalLinkage, Name);
if (!New->isIntrinsic()) New->setAttributes(AttributeList);
FunctionList.push_back(New);
return New; }
if (F->hasLocalLinkage()) {
F->setName("");
Constant *NewF = getOrInsertFunction(Name, Ty);
F->setName(Name);
return NewF;
}
if (F->getType() != PointerType::getUnqual(Ty))
return ConstantExpr::getBitCast(F, PointerType::getUnqual(Ty));
return F;
}
Constant *Module::getOrInsertTargetIntrinsic(StringRef Name,
FunctionType *Ty,
AttrListPtr AttributeList) {
GlobalValue *F = getNamedValue(Name);
if (F == 0) {
Function *New = Function::Create(Ty, GlobalVariable::ExternalLinkage, Name);
New->setAttributes(AttributeList);
FunctionList.push_back(New);
return New; }
return F;
}
Constant *Module::getOrInsertFunction(StringRef Name,
FunctionType *Ty) {
AttrListPtr AttributeList = AttrListPtr::get((AttributeWithIndex *)0, 0);
return getOrInsertFunction(Name, Ty, AttributeList);
}
Constant *Module::getOrInsertFunction(StringRef Name,
AttrListPtr AttributeList,
Type *RetTy, ...) {
va_list Args;
va_start(Args, RetTy);
std::vector<Type*> ArgTys;
while (Type *ArgTy = va_arg(Args, Type*))
ArgTys.push_back(ArgTy);
va_end(Args);
return getOrInsertFunction(Name,
FunctionType::get(RetTy, ArgTys, false),
AttributeList);
}
Constant *Module::getOrInsertFunction(StringRef Name,
Type *RetTy, ...) {
va_list Args;
va_start(Args, RetTy);
std::vector<Type*> ArgTys;
while (Type *ArgTy = va_arg(Args, Type*))
ArgTys.push_back(ArgTy);
va_end(Args);
return getOrInsertFunction(Name,
FunctionType::get(RetTy, ArgTys, false),
AttrListPtr::get((AttributeWithIndex *)0, 0));
}
Function *Module::getFunction(StringRef Name) const {
return dyn_cast_or_null<Function>(getNamedValue(Name));
}
GlobalVariable *Module::getGlobalVariable(StringRef Name,
bool AllowLocal) const {
if (GlobalVariable *Result =
dyn_cast_or_null<GlobalVariable>(getNamedValue(Name)))
if (AllowLocal || !Result->hasLocalLinkage())
return Result;
return 0;
}
Constant *Module::getOrInsertGlobal(StringRef Name, Type *Ty) {
GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(getNamedValue(Name));
if (GV == 0) {
GlobalVariable *New =
new GlobalVariable(*this, Ty, false, GlobalVariable::ExternalLinkage,
0, Name);
return New; }
if (GV->getType() != PointerType::getUnqual(Ty))
return ConstantExpr::getBitCast(GV, PointerType::getUnqual(Ty));
return GV;
}
GlobalAlias *Module::getNamedAlias(StringRef Name) const {
return dyn_cast_or_null<GlobalAlias>(getNamedValue(Name));
}
NamedMDNode *Module::getNamedMetadata(const Twine &Name) const {
SmallString<256> NameData;
StringRef NameRef = Name.toStringRef(NameData);
return static_cast<StringMap<NamedMDNode*> *>(NamedMDSymTab)->lookup(NameRef);
}
NamedMDNode *Module::getOrInsertNamedMetadata(StringRef Name) {
NamedMDNode *&NMD =
(*static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab))[Name];
if (!NMD) {
NMD = new NamedMDNode(Name);
NMD->setParent(this);
NamedMDList.push_back(NMD);
}
return NMD;
}
void Module::eraseNamedMetadata(NamedMDNode *NMD) {
static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab)->erase(NMD->getName());
NamedMDList.erase(NMD);
}
void Module::setMaterializer(GVMaterializer *GVM) {
assert(!Materializer &&
"Module already has a GVMaterializer. Call MaterializeAllPermanently"
" to clear it out before setting another one.");
Materializer.reset(GVM);
}
bool Module::isMaterializable(const GlobalValue *GV) const {
if (Materializer)
return Materializer->isMaterializable(GV);
return false;
}
bool Module::isDematerializable(const GlobalValue *GV) const {
if (Materializer)
return Materializer->isDematerializable(GV);
return false;
}
bool Module::Materialize(GlobalValue *GV, std::string *ErrInfo) {
if (Materializer)
return Materializer->Materialize(GV, ErrInfo);
return false;
}
void Module::Dematerialize(GlobalValue *GV) {
if (Materializer)
return Materializer->Dematerialize(GV);
}
bool Module::MaterializeAll(std::string *ErrInfo) {
if (!Materializer)
return false;
return Materializer->MaterializeModule(this, ErrInfo);
}
bool Module::MaterializeAllPermanently(std::string *ErrInfo) {
if (MaterializeAll(ErrInfo))
return true;
Materializer.reset();
return false;
}
void Module::dropAllReferences() {
for(Module::iterator I = begin(), E = end(); I != E; ++I)
I->dropAllReferences();
for(Module::global_iterator I = global_begin(), E = global_end(); I != E; ++I)
I->dropAllReferences();
for(Module::alias_iterator I = alias_begin(), E = alias_end(); I != E; ++I)
I->dropAllReferences();
}
void Module::addLibrary(StringRef Lib) {
for (Module::lib_iterator I = lib_begin(), E = lib_end(); I != E; ++I)
if (*I == Lib)
return;
LibraryList.push_back(Lib);
}
void Module::removeLibrary(StringRef Lib) {
LibraryListType::iterator I = LibraryList.begin();
LibraryListType::iterator E = LibraryList.end();
for (;I != E; ++I)
if (*I == Lib) {
LibraryList.erase(I);
return;
}
}
namespace {
class TypeFinder {
DenseSet<const Value*> VisitedConstants;
DenseSet<Type*> VisitedTypes;
std::vector<StructType*> &StructTypes;
public:
TypeFinder(std::vector<StructType*> &structTypes)
: StructTypes(structTypes) {}
void run(const Module &M) {
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());
}
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);
}
SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
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;
incorporateType(I.getType());
for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
OI != OE; ++OI)
incorporateValue(*OI);
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));
}
}
private:
void incorporateType(Type *Ty) {
if (!VisitedTypes.insert(Ty).second)
return;
if (StructType *STy = dyn_cast<StructType>(Ty))
StructTypes.push_back(STy);
for (Type::subtype_iterator I = Ty->subtype_begin(),
E = Ty->subtype_end(); I != E; ++I)
incorporateType(*I);
}
void incorporateValue(const Value *V) {
if (const MDNode *M = dyn_cast<MDNode>(V))
return incorporateMDNode(M);
if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;
if (!VisitedConstants.insert(V).second)
return;
incorporateType(V->getType());
const User *U = cast<User>(V);
for (Constant::const_op_iterator I = U->op_begin(),
E = U->op_end(); I != E;++I)
incorporateValue(*I);
}
void incorporateMDNode(const MDNode *V) {
if (!VisitedConstants.insert(V).second)
return;
for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i)
if (Value *Op = V->getOperand(i))
incorporateValue(Op);
}
};
}
void Module::findUsedStructTypes(std::vector<StructType*> &StructTypes) const {
TypeFinder(StructTypes).run(*this);
}