First steps with LLVM and partial evaluation

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);

}

Martin Apel wrote:

static LLVMContext context;

That's your bug.

Here's the situation that contexts help with. Suppose you write a library that uses LLVM under the hood (graphics, let's say), and I write another one that uses LLVM and does audio processing. Someone then decides to write a video game that uses both of our libraries. As long as we each use a separate context, everything about llvm will stay entirely and completely segregated and we'll never interfere with each other.

The module and the function your pass runs on and all of the types in it were created with a certain LLVMContext, but then you tried to mix your own LLVMContext in there. Don't do that, always pull the context from the IR that you're given. llvm::Value has a getContext() method on it.

Nick

Hi Nick,

thanks a lot, this did the trick. I tried to define my own context as locally as I could, but this didn't help. Now that I know, what I had to look
for, I even found the place in the documentation, where this is described.

Martin