2015-01-27 4 views
4

당신이 나에게 예를 줄 수 LLVM 내 IR 코드의 함수 호출을 추가하는 방법 LLVM 내 패스로 내 IR 코드를 함수

foo(x); 

의 간단한 호출을 추가하는 방법?

답변

10

간단한 방법은 LLVM C++ API 코드출력 옵션ELLCC을 사용하는 것입니다 배우는 것이다.

두 가지 핵심 노트 :

  1. foo의 정의를 사용할 수 있는지 확인합니다; 그렇지 않으면 먼저 정의해야합니다. 일반적으로 getOrInsertFunction을 사용하여 프로토 타입을 가져온 다음 IRBuilder을 사용하여 해당 기능에 본문을 삽입해야합니다.

  2. CallInst을 만들려면 쉬운 방법은 CallInst*IRBuilder::CreateCall(Value*, ArrayRef<Value*>, const Twine &)입니다.

여기는 llvm3.4에 대해 전에 쓴 세그먼트입니다. 도움이되기를 바랍니다.

#include "llvm/Analysis/Verifier.h" 
#include "llvm/IR/DerivedTypes.h" 
#include "llvm/IR/LLVMContext.h" 
#include "llvm/IR/Module.h" 
#include "llvm/IR/TypeBuilder.h" 
#include "llvm/IR/IRBuilder.h" 

using namespace llvm; 

Constant* geti8StrVal(Module& M, char const* str, Twine const& name) { 
    LLVMContext& ctx = getGlobalContext(); 
    Constant* strConstant = ConstantDataArray::getString(ctx, str); 
    GlobalVariable* GVStr = 
     new GlobalVariable(M, strConstant->getType(), true, 
         GlobalValue::InternalLinkage, strConstant, name); 
    Constant* zero = Constant::getNullValue(IntegerType::getInt32Ty(ctx)); 
    Constant* indices[] = {zero, zero}; 
    Constant* strVal = ConstantExpr::getGetElementPtr(GVStr, indices, true); 
    return strVal; 
} 

static Function *printf_prototype(LLVMContext &ctx, Module *mod) { 

    FunctionType *printf_type = 
     TypeBuilder<int(char *, ...), false>::get(getGlobalContext()); 

    Function *func = cast<Function>(mod->getOrInsertFunction(
     "printf", printf_type, 
     AttributeSet().addAttribute(mod->getContext(), 1U, Attribute::NoAlias))); 

    return func; 
} 

static Function *main_prototype(LLVMContext &ctx, Module *mod) { 

    FunctionType *foo_type = 
     TypeBuilder<int(int, char **), false>::get(getGlobalContext()); 
    Function *func = cast<Function>(mod->getOrInsertFunction("main", foo_type)); 
    /// func->setLinkage(GlobalValue::PrivateLinkage); 

    return func; 
} 

int main(int argc, char **argv) { 

    InitializeNativeTarget(); 

    LLVMContext &ctx = getGlobalContext(); 
    Module *module = new Module("example", ctx); 
    /// auto module = std::make_unique<Module>("example", ctx); 
    IRBuilder<> builder(ctx); 
    module->setDataLayout(
     "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" 
     "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" 
     "a0:0:64-s0:64:64-f80:128:128"); 
    module->setTargetTriple("x86_64-unknown-linux-gnu"); 

    // 
    // extern void printf(const char *fmt, ...); 
    // 
    Function *printf_func = printf_prototype(ctx, module); 

    // 
    // int foo(void) 
    // { 
    Function *main_fn = main_prototype(ctx, module); 
    BasicBlock *block = BasicBlock::Create(ctx, "", main_fn, 0); 
    builder.SetInsertPoint(block); 

    // 
    // int32_t temp = 15 + ... 
    // 
    Constant *left = ConstantInt::get(ctx, APInt(32, 15)); 

    AllocaInst *allocaInst = 
     builder.CreateAlloca(TypeBuilder<int, false>::get(getGlobalContext())); 
    SmallVector<Value *, 4> addsVect; 
    for (Argument &arg : main_fn->getArgumentList()) { 
    addsVect.push_back(&arg); 
    } 
    builder.CreateStore(addsVect[0], allocaInst); 
    LoadInst *loadInst = builder.CreateLoad(allocaInst); 

    Value *add = builder.CreateAdd(left, loadInst); 
    /// add->getType()->dump(); 
    /// errs() << "\n"; 

    // 
    // printf("%d\n", temp); 
    // 

    Constant *nullValue = Constant::getNullValue(add->getType()); 
    /// 
    builder.CreateICmpEQ(add, nullValue); 
    builder.CreateICmpNE(add, nullValue); 
    /// 
    Value *cmpResult = builder.CreateICmpUGT(add, nullValue); 
    builder.CreateICmpUGE(add, nullValue); 
    builder.CreateICmpULT(add, nullValue); 
    builder.CreateICmpULE(add, nullValue); 
    /// 
    builder.CreateICmpSGT(add, nullValue); 
    builder.CreateICmpSGE(add, nullValue); 
    builder.CreateICmpSLT(add, nullValue); 
    builder.CreateICmpSLE(add, nullValue); 
    /// 

    BasicBlock *br_true = BasicBlock::Create(ctx, "br_true", main_fn, 0); 
    BasicBlock *br_false = BasicBlock::Create(ctx, "br_false", main_fn, 0); 

    builder.CreateCondBr(cmpResult, br_true, br_false); 

    builder.SetInsertPoint(br_false); 
    builder.CreateCall2(printf_func, utils::geti8StrVal(*module, "%d\n"), add); 

    SmallVector<Value *, 4> assertArgs; 
    assertArgs.push_back(utils::geti8StrVal(*module, "__assert_fail")); 
    assertArgs.push_back(utils::geti8StrVal(*module, __FILE__)); 
    /// assertArgs.push_back(
    ///  ConstantInt::get(TypeBuilder<int, false>::get(ctx), __LINE__, false)); 
    assertArgs.push_back(add); 
    assertArgs.push_back(utils::geti8StrVal(*module, __FUNCTION__)); 
    Function *assertFunc = utils::getFn_assert(*module); 
    /// errs() << *assertFunc; 
    builder.CreateCall(assertFunc, assertArgs); 

    /// builder.CreateBr(br_true); 

    ConstantInt *zero = ConstantInt::get(IntegerType::getInt32Ty(ctx), 0); 
    builder.CreateRet(zero); 

    // 
    // return 0; 
    // } 
    // 
    builder.SetInsertPoint(br_true); 
    builder.CreateRet(zero); 
}