Hi all,
I'm rather new to LLVM and intend to dive into partial evaluation with LLVM.
I tried to run the example from http://llvm.org/devmtg/2008-08-23/llvm_partial.pdf, which worked after some adaptations, which were necessary, because
LLVM evolved since
the slides were made. However, I also tried to get the same example running as an optimization pass following the instructions in
http://llvm.org/docs/WritingAnLLVMPass.html.
I am using LLVM 2.9 on Linux.
It seems that opt runs a verification step after each pass, which rejected the modifications my pass made. So here's the code (more or less the
original code with only slight
modififications to get things to compile with LLVM 2.9):
#include "specializeFunc.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Transforms/Utils/Cloning.h"
using namespace std;
using namespace llvm;
static Function *cloneFunctionInfo(const Function *F,
ValueToValueMapTy& ValueMap)
{
vector<const Type*> ArgTypes;
// The user might be deleting arguments to the function by specifying them in
// the ValueMap. If so, we need to not add the arguments to the arg ty vector
//
for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
I != E; ++I)
if (ValueMap.count(I) == 0) // Haven't mapped the argument to anything yet?
ArgTypes.push_back(I->getType());
// Create a new function type...
FunctionType *FTy = FunctionType::get(F->getFunctionType()->getReturnType(),
ArgTypes, F->getFunctionType()->isVarArg());
// Create the new function...
Function *NewF = Function::Create(FTy, F->getLinkage(), F->getName());
// Loop over the arguments, copying the names of the mapped arguments over...
Function::arg_iterator DestI = NewF->arg_begin();
for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
I != E; ++I)
if (ValueMap.count(I) == 0) {
// Is this argument preserved?
DestI->setName(I->getName()); // Copy the name over...
ValueMap[I] = DestI++;
// Add mapping to ValueMap
}
return NewF;
}
//*******************************************************************************
void specializeFunction(Module& m, Function& f, LLVMContext& context)
{
ValueToValueMapTy valueMap;
Function *specFunc = cloneFunctionInfo(&f, valueMap);
specFunc->setName(specFunc->getNameStr() + "_spec");
for (Function::arg_iterator j = f.arg_begin(); j != f.arg_end(); ++j)
{
Argument* arg = j;
Value* val;
if (arg->getNameStr() == "n")
{
val = ConstantInt::get(Type::getInt32Ty(context), 3);
valueMap[arg] = val;
}
}
SmallVector<ReturnInst*, 8> returns;
CloneAndPruneFunctionInto(specFunc, &f, valueMap, false, returns);
m.getFunctionList().push_back(specFunc);
}
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/LLVMContext.h"
#include "../specFunc/specializeFunc.h"
using namespace std;
using namespace llvm;
namespace {
static LLVMContext context;
struct Hello : public ModulePass {
static char ID;
Hello() : ModulePass(ID)
{
}
virtual bool runOnModule(Module& m)
{
for (Module::iterator i = m.begin(); i != m.end(); ++i)
{
string name = i->getNameStr();
if (!i->isDeclaration() && name.substr(name.length() - 5) != "_spec")
specializeFunction(m, *i, context);
}
return false;
}
};
char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass", false, false);
}