Использование CloneFunctionInto() от llvm

Мне нужно клонировать функцию в другую функцию с помощью CloneFunctionInto в проходе функции LLVM, чтобы сохранить исходный граф потока управления от любых изменений, которые я могу внести в первую очередь.

http://llvm.org/docs/doxygen/html/Cloning_8h_source.html

void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = 0, ValueMapTypeRemapper *TypeMapper = 0);

Может ли кто-нибудь помочь мне с этим, потому что у меня есть некоторые недостающие части, такие как ClonedCodeInfo а также ValueMapTypeRemapper?

Пожалуйста, дайте мне пример, чтобы лучше понять

Спасибо

2 ответа

Вытаскивая из кислорода, ClonedCodeInfo Класс может использоваться для получения информации о функции, которую вы только что клонировали, а именно, содержит ли функция вызовы или динамические инструкции alloca.

Опять документация для ValueMapTypeRemapper говорит нам, что это абстрактный базовый класс, который требует от любого подкласса remapType() метод. Как следует из названия, это может быть использовано для замены определенных типов в вашей функции другими типами.

Вот пример кода:

class MessageUpdater: public ValueMapTypeRemapper
{
public:
    Type *remapType(Type *SrcTy)
    {
        std::map<Type *, Type *>::iterator i, e;
        for (i = foo.begin(), e = foo.end(); i != e; ++i) {
            if (SrcTy == i->first) {
                return i->second;
            }
        }

        assert(0 && "Type not found in map!");
        return 0;
    }
    std::map<Type *, Type *> foo;
};

И вы можете назвать это так:

MessageUpdater foobar;

foobar.foo.insert(std::make_pair(fromStruct, toStruct));
foobar.foo.insert(std::make_pair(fromStructPtr, toStructPtr));
foobar.foo.insert(std::make_pair(fromStructPtrPtr, toStructPtrPtr));

for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) {
    foobar.foo.insert(std::make_pair(I->getType(), I->getType()));
}

std::map<Type *, Type *>::iterator i, e;
for (i = foobar.foo.begin(), e = foobar.foo.end(); i != e; ++i) {
    errs() << *i->first << " maps to " << *i->second << "\n";
}

CloneFunctionInto(newFun, f, vmap, false, Returns, "", 0, &foobar);

Вы заметите, что вы не обязаны проходить ClonedCodeInfo объект в эту функцию, и поэтому я просто передать в 0.

      here is a small example:
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/AsmParser/Parser.h"
//#include "llvm/IR/IRBuilder.h"
//#include "llvm/ExecutionEngine/MCJIT.h"
//#include "llvm/Support/TargetSelect.h"
//#include "llvm/IR/TypeBuilder.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <iostream>
#include <algorithm>
#include <vector>
using namespace llvm;
using namespace std;
 

int main(){
    static LLVMContext TheContext;
    char irFile1[] = "wait.ll";
    //LLVMContext &Context1 = getGlobalContext();
    SMDiagnostic Err1;
    std::unique_ptr<Module> Mod1= parseIRFile(irFile1, Err1, TheContext);
    for(auto iter = Mod1->begin() ; iter != Mod1->end(); iter++){
        string name((*iter).getName());
        std::cout << name <<std::endl;
        ;;
    }
    // auto &functionList = Mod1->getFunctionList();
    // for(auto tFun : functionList){
        
    //     // if(tFun->getName() != "main"){
    //     //     funVec.emplace_back(tFun);
    //     // }else{
    //     //     printf("%s\n" , tFun->getName());
    //     // }
        
    // }

//     char irFile2[] = "insert.ll";
//    // LLVMContext &Context2 = getGlobalContext();
//     SMDiagnostic Err2;
//     std::unique_ptr<Module> Mod2= parseIRFile(irFile2, Err2, TheContext);
    Module *relaseMod1 = Mod1.release();
    SMDiagnostic error;
    StringRef ImplAssembly = R"(
        define dso_local void @_Z3fooPiS_(i32* %0, i32* %1) #0 {
  %3 = alloca i32*, align 8
  %4 = alloca i32*, align 8
  store i32* %0, i32** %3, align 8
  store i32* %1, i32** %4, align 8
  %5 = load i32*, i32** %3, align 8
  store i32 1, i32* %5, align 4
  %6 = load i32*, i32** %4, align 8
  store i32 1, i32* %6, align 4
  ret void
}
    )";
    auto InjectedModule = parseAssemblyString(ImplAssembly, error, relaseMod1->getContext());
    auto* ImplFunction = InjectedModule->getFunction("_Z3fooPiS_");
    // std::vector<string> funVec;
    // for(auto iter = Mod2->begin() ; iter != Mod2->end(); iter++){
       
    //     string name((*iter).getName());
        
    //     ;;
    //     if(name != "main")
    //     {
    //         funVec.emplace_back(name);
    //         std::cout << name <<std::endl;
    //     }
        
    // }
    // std::vector<llvm::Function*> funVec;
    // for(auto tFun : Mod2->functions ()){
    //     if(tFun->getName() != "main"){
    //         funVec.emplace_back(tFun);
    //     }else{
    //         printf("%s\n" , tFun->getName());
    //     }
        
    // }

    //auto InjectedModule = parseAssemblyString(ImplAssembly, error, M.getContext());
    
    //llvm::Function* ImplFunction = Mod2->getFunction(funVec[0]);
    //ImplFunction->print(std::cout);
    llvm::Function* DeclFunction = Function::Create(ImplFunction->getFunctionType(), ImplFunction->getLinkage(), "_Z3fo111oPiS_", relaseMod1);
    llvm::ValueToValueMapTy VMap;
    //VMap[ImplFunction] = DeclFunction;
    Function::arg_iterator DestI = DeclFunction->arg_begin();
    for (Function::const_arg_iterator J = ImplFunction->arg_begin(); J != ImplFunction->arg_end();
         ++J) {
      DeclFunction->setName(J->getName());
      VMap[J] = DestI++;
    }
    //VMap[&*ImplFunction->arg_begin()] = &*DeclFunction->arg_begin();
    SmallVector<ReturnInst*, 8> Returns;
    CloneFunctionInto(DeclFunction, ImplFunction, VMap, llvm::CloneFunctionChangeType::DifferentModule, Returns);
    //relaseMod1->dump();
    relaseMod1->print(llvm::errs(), nullptr);
    return 0;
}
Другие вопросы по тегам