//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/MutateStructTypes.h"
+#include "llvm/Transforms/IPO/MutateStructTypes.h"
#include "llvm/DerivedTypes.h"
-#include "llvm/Method.h"
+#include "llvm/Module.h"
+#include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
#include "llvm/GlobalVariable.h"
#include "llvm/SymbolTable.h"
-#include "llvm/iOther.h"
+#include "llvm/iPHINode.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
+#include "llvm/iOther.h"
+#include "llvm/Argument.h"
+#include "Support/STLExtras.h"
#include <algorithm>
+using std::map;
+using std::vector;
+
+//FIXME: These headers are only included because the analyses are killed!!!
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Analysis/FindUsedTypes.h"
+#include "llvm/Analysis/FindUnsafePointerTypes.h"
+//FIXME end
// To enable debugging, uncomment this...
//#define DEBUG_MST(x) x
-#ifdef DEBUG_MST
-#include "llvm/Assembly/Writer.h"
-#else
+#ifndef DEBUG_MST
#define DEBUG_MST(x) // Disable debug code
#endif
struct ValuePlaceHolder : public Instruction {
ValuePlaceHolder(const Type *Ty) : Instruction(Ty, UserOp1, "") {}
- virtual Instruction *clone() const { abort(); }
+ virtual Instruction *clone() const { abort(); return 0; }
virtual const char *getOpcodeName() const { return "placeholder"; }
};
if (Ty->isPrimitiveType() ||
isa<OpaqueType>(Ty)) return Ty; // Don't convert primitives
- map<const Type *, PATypeHolder<Type> >::iterator I = TypeMap.find(Ty);
+ map<const Type *, PATypeHolder>::iterator I = TypeMap.find(Ty);
if (I != TypeMap.end()) return I->second;
const Type *DestTy = 0;
- PATypeHolder<Type> PlaceHolder = OpaqueType::get();
- TypeMap.insert(make_pair(Ty, PlaceHolder.get()));
+ PATypeHolder PlaceHolder = OpaqueType::get();
+ TypeMap.insert(std::make_pair(Ty, PlaceHolder.get()));
switch (Ty->getPrimitiveID()) {
- case Type::MethodTyID: {
- const MethodType *MT = cast<MethodType>(Ty);
+ case Type::FunctionTyID: {
+ const FunctionType *MT = cast<FunctionType>(Ty);
const Type *RetTy = ConvertType(MT->getReturnType());
vector<const Type*> ArgTypes;
- for (MethodType::ParamTypes::const_iterator I = MT->getParamTypes().begin(),
+ for (FunctionType::ParamTypes::const_iterator I = MT->getParamTypes().begin(),
E = MT->getParamTypes().end(); I != E; ++I)
ArgTypes.push_back(ConvertType(*I));
- DestTy = MethodType::get(RetTy, ArgTypes, MT->isVarArg());
+ DestTy = FunctionType::get(RetTy, ArgTypes, MT->isVarArg());
break;
}
case Type::StructTyID: {
case Type::PointerTyID:
DestTy = PointerType::get(
- ConvertType(cast<PointerType>(Ty)->getValueType()));
+ ConvertType(cast<PointerType>(Ty)->getElementType()));
break;
default:
assert(0 && "Unknown type!");
// Refine our little placeholder value into a real type...
cast<DerivedType>(PlaceHolder.get())->refineAbstractTypeTo(DestTy);
- TypeMap.insert(make_pair(Ty, PlaceHolder.get()));
+ TypeMap.insert(std::make_pair(Ty, PlaceHolder.get()));
return PlaceHolder.get();
}
// AdjustIndices - Convert the indexes specifed by Idx to the new changed form
// using the specified OldTy as the base type being indexed into.
//
-void MutateStructTypes::AdjustIndices(const StructType *OldTy,
- vector<ConstPoolVal*> &Idx,
+void MutateStructTypes::AdjustIndices(const CompositeType *OldTy,
+ vector<Value*> &Idx,
unsigned i = 0) {
assert(i < Idx.size() && "i out of range!");
- const StructType *NewST = cast<StructType>(ConvertType(OldTy));
- if (NewST == OldTy) return; // No adjustment unless type changes
-
- // Figure out what the current index is...
- unsigned ElNum = cast<ConstPoolUInt>(Idx[i])->getValue();
- assert(ElNum < OldTy->getElementTypes().size());
-
- map<const StructType*, TransformType>::iterator I = Transforms.find(OldTy);
- if (I != Transforms.end()) {
- assert(ElNum < I->second.second.size());
- // Apply the XForm specified by Transforms map...
- unsigned NewElNum = I->second.second[ElNum];
- Idx[i] = ConstPoolUInt::get(Type::UByteTy, NewElNum);
+ const CompositeType *NewCT = cast<CompositeType>(ConvertType(OldTy));
+ if (NewCT == OldTy) return; // No adjustment unless type changes
+
+ if (const StructType *OldST = dyn_cast<StructType>(OldTy)) {
+ // Figure out what the current index is...
+ unsigned ElNum = cast<ConstantUInt>(Idx[i])->getValue();
+ assert(ElNum < OldST->getElementTypes().size());
+
+ map<const StructType*, TransformType>::iterator I = Transforms.find(OldST);
+ if (I != Transforms.end()) {
+ assert(ElNum < I->second.second.size());
+ // Apply the XForm specified by Transforms map...
+ unsigned NewElNum = I->second.second[ElNum];
+ Idx[i] = ConstantUInt::get(Type::UByteTy, NewElNum);
+ }
}
// Recursively process subtypes...
if (i+1 < Idx.size())
- AdjustIndices(cast<StructType>(OldTy->getElementTypes()[ElNum].get()),
- Idx, i+1);
+ AdjustIndices(cast<CompositeType>(OldTy->getTypeAtIndex(Idx[i])), Idx, i+1);
}
// Ignore null values and simple constants..
if (V == 0) return 0;
- if (ConstPoolVal *CPV = dyn_cast<ConstPoolVal>(V)) {
+ if (Constant *CPV = dyn_cast<Constant>(V)) {
if (V->getType()->isPrimitiveType())
return CPV;
- if (isa<ConstPoolPointerNull>(CPV))
- return ConstPoolPointerNull::get(
+ if (isa<ConstantPointerNull>(CPV))
+ return ConstantPointerNull::get(
cast<PointerType>(ConvertType(V->getType())));
assert(0 && "Unable to convert constpool val of this type!");
}
- // Check to see if this is an out of method reference first...
+ // Check to see if this is an out of function reference first...
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
// Check to see if the value is in the map...
map<const GlobalValue*, GlobalValue*>::iterator I = GlobalMap.find(GV);
}
-// Ctor - Take a map that specifies what transformation to do for each field
-// of the specified structure types. There is one element of the vector for
-// each field of the structure. The value specified indicates which slot of
+// setTransforms - Take a map that specifies what transformation to do for each
+// field of the specified structure types. There is one element of the vector
+// for each field of the structure. The value specified indicates which slot of
// the destination structure the field should end up in. A negative value
// indicates that the field should be deleted entirely.
//
-MutateStructTypes::MutateStructTypes(const map<const StructType*,
- vector<int> > &XForm) {
+void MutateStructTypes::setTransforms(const TransformsType &XForm) {
// Loop over the types and insert dummy entries into the type map so that
// recursive types are resolved properly...
for (map<const StructType*, vector<int> >::const_iterator I = XForm.begin(),
E = XForm.end(); I != E; ++I) {
const StructType *OldTy = I->first;
- TypeMap.insert(make_pair(OldTy, OpaqueType::get()));
+ TypeMap.insert(std::make_pair(OldTy, OpaqueType::get()));
}
// Loop over the type specified and figure out what types they should become
}
// Create a new type that corresponds to the destination type
- PATypeHolder<StructType> NSTy = StructType::get(NewType);
+ PATypeHolder NSTy = StructType::get(NewType);
// Refine the old opaque type to the new type to properly handle recursive
// types...
cast<DerivedType>(OldTypeStub)->refineAbstractTypeTo(NSTy);
// Add the transformation to the Transforms map.
- Transforms.insert(make_pair(OldTy, make_pair(NSTy, InVec)));
+ Transforms.insert(std::make_pair(OldTy,
+ std::make_pair(cast<StructType>(NSTy.get()), InVec)));
DEBUG_MST(cerr << "Mutate " << OldTy << "\nTo " << NSTy << endl);
}
}
+void MutateStructTypes::clearTransforms() {
+ Transforms.clear();
+ TypeMap.clear();
+ GlobalMap.clear();
+ assert(LocalValueMap.empty() &&
+ "Local Value Map should always be empty between transformations!");
+}
-// doPassInitialization - This loops over global constants defined in the
+// doInitialization - This loops over global constants defined in the
// module, converting them to their new type.
//
-bool MutateStructTypes::doPassInitialization(Module *M) {
- // Loop through the methods in the module and create a new version of the
- // method to contained the transformed code. Don't use an iterator, because
+void MutateStructTypes::processGlobals(Module *M) {
+ // Loop through the functions in the module and create a new version of the
+ // function to contained the transformed code. Don't use an iterator, because
// we will be adding values to the end of the vector, and it could be
// reallocated. Also, we don't want to process the values that we add.
//
- unsigned NumMethods = M->size();
- for (unsigned i = 0; i < NumMethods; ++i) {
- Method *Meth = M->begin()[i];
+ unsigned NumFunctions = M->size();
+ for (unsigned i = 0; i < NumFunctions; ++i) {
+ Function *Meth = M->begin()[i];
if (!Meth->isExternal()) {
- const MethodType *NewMTy =
- cast<MethodType>(ConvertType(Meth->getMethodType()));
+ const FunctionType *NewMTy =
+ cast<FunctionType>(ConvertType(Meth->getFunctionType()));
- // Create a new method to put stuff into...
- Method *NewMeth = new Method(NewMTy, Meth->getName());
+ // Create a new function to put stuff into...
+ Function *NewMeth = new Function(NewMTy, Meth->hasInternalLinkage(),
+ Meth->getName());
if (Meth->hasName())
Meth->setName("OLD."+Meth->getName());
- // Insert the new method into the method list... to be filled in later...
- M->getMethodList().push_back(NewMeth);
+ // Insert the new function into the method list... to be filled in later..
+ M->getFunctionList().push_back(NewMeth);
// Keep track of the association...
GlobalMap[Meth] = NewMeth;
}
}
}
-
- return true;
}
-// doPassFinalization - For this pass, all this does is remove the old versions
-// of the methods and global variables that we no longer need.
-bool MutateStructTypes::doPassFinalization(Module *M) {
- // The first half of the methods in the module have to go.
- unsigned NumMethods = M->size();
- unsigned NumGVars = M->gsize();
- assert((NumMethods & 1) == 0 && "Number of methods is odd!");
-
+// removeDeadGlobals - For this pass, all this does is remove the old versions
+// of the functions and global variables that we no longer need.
+void MutateStructTypes::removeDeadGlobals(Module *M) {
// Prepare for deletion of globals by dropping their interdependencies...
for(Module::iterator I = M->begin(); I != M->end(); ++I) {
if (GlobalMap.find(*I) != GlobalMap.end())
- (*I)->Method::dropAllReferences();
+ (*I)->Function::dropAllReferences();
}
- // Run through and delete the methods and global variables...
+ // Run through and delete the functions and global variables...
#if 0 // TODO: HANDLE GLOBAL VARIABLES
M->getGlobalList().delete_span(M->gbegin(), M->gbegin()+NumGVars/2);
#endif
for(Module::iterator I = M->begin(); I != M->end();) {
if (GlobalMap.find(*I) != GlobalMap.end())
- delete M->getMethodList().remove(I);
+ delete M->getFunctionList().remove(I);
else
++I;
}
-
- return true;
}
-// doPerMethodWork - This transforms the instructions of the method to use the
+// transformMethod - This transforms the instructions of the function to use the
// new types.
//
-bool MutateStructTypes::doPerMethodWork(Method *m) {
- const Method *M = m;
+void MutateStructTypes::transformMethod(Function *m) {
+ const Function *M = m;
map<const GlobalValue*, GlobalValue*>::iterator GMI = GlobalMap.find(M);
if (GMI == GlobalMap.end())
- return false; // Do not affect one of our new methods that we are creating
+ return; // Do not affect one of our new functions that we are creating
- Method *NewMeth = cast<Method>(GMI->second);
+ Function *NewMeth = cast<Function>(GMI->second);
// Okay, first order of business, create the arguments...
- for (unsigned i = 0; i < M->getArgumentList().size(); ++i) {
- const MethodArgument *OMA = M->getArgumentList()[i];
- MethodArgument *NMA = new MethodArgument(ConvertType(OMA->getType()),
- OMA->getName());
- NewMeth->getArgumentList().push_back(NMA);
- LocalValueMap[OMA] = NMA; // Keep track of value mapping
+ for (unsigned i = 0, e = M->getArgumentList().size(); i != e; ++i) {
+ const Argument *OFA = M->getArgumentList()[i];
+ Argument *NFA = new Argument(ConvertType(OFA->getType()), OFA->getName());
+ NewMeth->getArgumentList().push_back(NFA);
+ LocalValueMap[OFA] = NFA; // Keep track of value mapping
}
// Loop over all of the basic blocks copying instructions over...
- for (Method::const_iterator BBI = M->begin(), BBE = M->end(); BBI != BBE;
+ for (Function::const_iterator BBI = M->begin(), BBE = M->end(); BBI != BBE;
++BBI) {
// Create a new basic block and establish a mapping between the old and new
const BasicBlock *BB = *BBI;
BasicBlock *NewBB = cast<BasicBlock>(ConvertValue(BB));
- NewMeth->getBasicBlocks().push_back(NewBB); // Add block to method
+ NewMeth->getBasicBlocks().push_back(NewBB); // Add block to function
// Copy over all of the instructions in the basic block...
for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end();
case Instruction::Store:
case Instruction::GetElementPtr: {
const MemAccessInst *MAI = cast<MemAccessInst>(I);
- vector<ConstPoolVal*> Indices = MAI->getIndices();
+ vector<Value*> Indices(MAI->idx_begin(), MAI->idx_end());
const Value *Ptr = MAI->getPointerOperand();
Value *NewPtr = ConvertValue(Ptr);
if (!Indices.empty()) {
- const Type *PTy = cast<PointerType>(Ptr->getType())->getValueType();
- AdjustIndices(cast<StructType>(PTy), Indices);
+ const Type *PTy = cast<PointerType>(Ptr->getType())->getElementType();
+ AdjustIndices(cast<CompositeType>(PTy), Indices);
}
- if (const LoadInst *LI = dyn_cast<LoadInst>(I)) {
+ if (isa<LoadInst>(I)) {
NewI = new LoadInst(NewPtr, Indices);
- } else if (const StoreInst *SI = dyn_cast<StoreInst>(I)) {
+ } else if (isa<StoreInst>(I)) {
NewI = new StoreInst(ConvertValue(I->getOperand(0)), NewPtr, Indices);
- } else if (const GetElementPtrInst *GEP =
- dyn_cast<GetElementPtrInst>(I)) {
+ } else if (isa<GetElementPtrInst>(I)) {
NewI = new GetElementPtrInst(NewPtr, Indices);
} else {
assert(0 && "Unknown memory access inst!!!");
}
LocalValueMap.clear();
+}
+
+
+bool MutateStructTypes::run(Module *M) {
+ processGlobals(M);
+
+ for_each(M->begin(), M->end(),
+ bind_obj(this, &MutateStructTypes::transformMethod));
+
+ removeDeadGlobals(M);
return true;
}
+
+// getAnalysisUsageInfo - This function needs the results of the
+// FindUsedTypes and FindUnsafePointerTypes analysis passes...
+//
+void MutateStructTypes::getAnalysisUsageInfo(Pass::AnalysisSet &Required,
+ Pass::AnalysisSet &Destroyed,
+ Pass::AnalysisSet &Provided) {
+ Destroyed.push_back(FindUsedTypes::ID);
+ Destroyed.push_back(FindUnsafePointerTypes::ID);
+ Destroyed.push_back(CallGraph::ID);
+}