Frage

For my source code, I have the following IR:

; ModuleID = '<stdin>'


@.str = private unnamed_addr constant [9 x i8] c"SOME_ENV_VAR\00", align 1
@.str1 = private unnamed_addr constant [26 x i8] c"Need to set $ENV_Variable.\0A\00", align 1

; Function Attrs: nounwind
define void @foo(i8* %bar) #0 {
entry:
  %bar.addr = alloca i8*, align 4
  %baz = alloca i8*, align 4
  store i8* %bar, i8** %bar.addr, align 4
  %call = call i8* @getenv(i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0)) #2
  store i8* %call, i8** %baz, align 4
  %0 = load i8** %baz, align 4
  %cmp = icmp eq i8* %0, null
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([26 x i8]* @.str1, i32 0, i32 0))
  br label %if.end

if.else:                                          ; preds = %entry
  %1 = load i8** %bar.addr, align 4
  %2 = load i8** %baz, align 4
  %call2 = call i8* @strcpy(i8* %1, i8* %2) #2
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  ret void
}

; Function Attrs: nounwind
declare i8* @getenv(i8*) #0

declare i32 @printf(i8*, ...) #1

; Function Attrs: nounwind
declare i8* @strcpy(i8*, i8*) #0

I intend to write a pass, which when compiled (using LLVM), produces bitcode where the call to strcpy(dest,src) is replaced with strncpy(dest,src,n).

I've written the following code so far:

#include <stdlib.h>
#include <stdio.h>
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/IR/IRBuilder.h"

using namespace llvm;
namespace
{
Module* makeLLVMModule() {


    Module* mod = new Module(llvm::StringRef("CustomPass"),getGlobalContext());

    Constant* c = mod->getOrInsertFunction(llvm::StringRef("foo"),Type::getInt32Ty(getGlobalContext()),NULL); 

    Function* foo = cast<Function>(c);
    Function::arg_iterator args =foo->arg_begin();
    Value* bar = args++;

    BasicBlock* Entry = BasicBlock::Create(getGlobalContext(),llvm::Twine("Entry"), foo);
    BasicBlock* False = BasicBlock::Create(getGlobalContext(),llvm::Twine("False"), foo);
    BasicBlock* True = BasicBlock::Create(getGlobalContext(),llvm::Twine("True"), foo);

    char* pPath;
    pPath = getenv("SOME_ENV_VAR");

    IRBuilder<> builder(Entry);
    Value* envVarDoesntExist = builder.CreateICmpEQ(llvm::StringRef(pPath),Constant::getNullValue(Value),llvm::Twine("temp"));
    //---1
    builder.CreateCondBr(envVarDoesntExist, False, True);

    builder.SetInsertPoint(True);
    builder.CreateCall3(strncpy,bar,llvm::StringRef(pPath),45,llvm::Twine("temp"));
    //---2 

    builder.SetInsertPoint(False);
    builder.CreateCall(printf,llvm::StringRef("Need to set $ENV_Variable.\n"),llvm::Twine("temp"));
    //---1
    return mod;        

    }

}

char funcP::ID = 0;
static RegisterPass<funcP> X("funcp", "funcP", false, false);
  1. From ---1:How to convert llvm::StringRef to Value* ?
  2. From ---2:How to convert char* to Value*
  3. Could Constant::getNullValue(Value) be used for getting a NULL value?
War es hilfreich?

Lösung

I intend to write a pass, which when compiled (using LLVM), produces bitcode where the call to strcpy(dest,src) is replaced with strncpy(dest,src,n).

Then what you need to do is to locate the call instruction and change it. There's no need to recreate the entire flow, it's already in your source code.

All you need to do is to create a function pass, iterate over all the instructions in the function, and if the instruction is a call instruction and the callee's name is strcpy then create a new call instruction to your new function, then replace the old instruction with the new instruction.

Also there seems to be some fundamental misunderstanding in your code between values in the compiler (such as 45 and all the StringRefs) and values in the code you are processing (instances of one of the subtypes of llvm::Value). Specifically, you can't just use 45 as a parameter to a function in the code you are processing - you have to create a constant int from that number, and then you can use that constant.

One final note - you can implicitly construct a StringRef from a const char*, you don't need to explicitly call the StringRef's constructor all over the place. Same with Twine.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top