0
votes
#include "llvm/Pass.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

using namespace llvm;

namespace {
  struct replacepass : public FunctionPass {
    static char ID;
    ReplacePass() : FunctionPass(ID) {}

    virtual bool runOnFunction(Function &F) {
      AllocaInst* instToReplace = ??? 
      BasicBlock::iterator ii(instToReplace);
      ReplaceInstWithInst(instToReplace->getParent()->getInstList(), ii, new AllocaInst(Type::Int32Ty, 0, instToReplace));
      return true;
    }
  };
}

char ReplacePass::ID = 0;

static void registerReplacePass(const PassManagerBuilder &, legacy::PassManagerBase &PM) {
    PM.add(new ReplacePass());
}
static RegisterStandardPasses
    RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, registerReplacePass);

Hi, I'm trying to understand the LLVM passes but I'm kinda stuck.
I wanted to start with a simple thing, like replacing stack-based memory allocation alloca with heap-based memory allocation malloc.
Using GDB I saw that the alloca instruction doesn't have "a name" so, I think, I can't use the getFunction utility.
Something that came into my mind is searching for the alloca opcode and replacing it with the malloc opcode.
But the LLVM docs is not the best doc I've ever seen so I don't really know if I can do such a thing.
Can you give me some suggestions, please?


EDIT:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <alloca.h>

using namespace ::std;

void func() {
 int *p = (int *)alloca(20);
 char *s = (char *)alloca(150);
}

int main (void) {
    cout << "Hello, LLVM\n";
    char *arr = (char *)malloc(10);
    func();
    free (arr)
    return 0;
}

EDIT 2:

#include "llvm/Pass.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <string.h>

using namespace llvm;

namespace {
    struct ReplacePass : public FunctionPass {
        static char ID;
        ReplacePass() : FunctionPass(ID) {}

        virtual bool runOnFunction(Function &F) {
            // iterate over the basic blocks of a function
            for (auto &BB : F) {
                // iterate over the instructions of a basic block
                for (auto &I : BB) {
                    if (AllocaInst *CI = dyn_cast<AllocaInst>(&I)) {
                        if (!((I.getName()).empty()))
                        {
                            const char *s = I.getOpcodeName();
                            if(strcmp(s, "alloca") == 0){
                                errs().write_escaped(I.getName()) << " is an " << I.getOpcodeName();
                                errs() << "\n";
                            }
                            if(strcmp(s, "malloc") == 0){
                                errs().write_escaped(I.getName()) << " is a " << I.getOpcodeName();
                                errs() << "\n";
                            }
                        }
                    }
                }
            }
            return false;
        }
    };
}

char ReplacePass::ID = 0;

static void registerReplacePass(const PassManagerBuilder &, legacy::PassManagerBase &PM) {
    PM.add(new ReplacePass());
}
static RegisterStandardPasses
    RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, registerReplacePass);

I wrote the above code but it doesn't work because 1) malloc and alloca are both called "alloca" in LLVM and 2) they have the same opcode (26)

1

1 Answers

1
votes

You can iterate on Function's BasicBlocks with begin() and on BB's Instructions in the same way. Alternatively, you can make your pass to work on BasicBlock level. When analysing Instruction use isa<InstType> to find out its type.

I also find it strange you didn't liked LLVM docs. This manual, for example, was super useful to me.

EDIT:

To see LLVM representation of the code you are working on use CppBackend. Compile your code with clang -march=cpp and it will produce a C++ source, that make up your code using LLVM API. There you would see how every instruction is created and, therefore, how they differ.

Another useful tool is -emit-llvm flag with conjuction of -S flag. Running clang -emit-llvm -S would produce you an LLVM IR assembly that makes up your code.

Regarding your problem, i think you are misunderstood LLVM's alloca sematics. The AllocaInst corresponds to, roughly int a=1 in C code. What you are looking for is CallInst to "alloca" and "malloc" functions.