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);
}
------------------------------------------------------------------------------------------------------
The resulting error message from the verification step is:
Stored value type does not match pointer operand type!
store i32 3, i32* %n_addr
i32Broken module found, compilation aborted!
Stack dump:
0. Program arguments: opt --load obj/pass/ce_opt_pass.so -hello power.ir
1. Running pass 'Function Pass Manager' on module
'power.ir'.
2. Running pass 'Module Verifier' on function
'@mypower_spec'
I do not understand, what is going wrong here. When calling the exact same
function "specializeFunction" from a main program, which simply reads
a
bitcode file,
calls "specializeFunction" on the only function definition in it and
writing it to another file, everything works fine. The resulting bitcode file
can
be disassembled or optimized without
problems. What am I doing wrong?
Any help would be appreciated,
Martin