自己使用 LLVM Interpreter API 的方法。

 

首先先產生 LLVM 的 function,如下:

 

#define NDEBUG, dbgs() == errs()
#include <stdio.h>
#include<vector>
#include "llvm/LLVMContext.h"
#include "llvm/Support/Threading.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/BasicBlock.h"
#include "llvm/CallingConv.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include <stdlib.h>
#include <pthread.h>
#include "llvm/GlobalVariable.h"
#include "llvm/Support/ThreadLocal.h"
#include<iostream>
#include"llvm/Constants.h"
#include "llvm/CodeGen/MachineCodeInfo.h"
#include "llvm/ADT/SmallVector.h"

using namespace std;
using namespace llvm;
llvm::GlobalVariable* gvar,*gvar2;
ExecutionEngine* EE;
    MachineCodeInfo info[5];

struct myType
{
    int a,b,c[32],d;
};

int main()
{
    struct myType my;
    my.b = 10;
    my.a = 50;
    my.c[1] = 100; my.c[8] = 128;
   // llvm_start_multithreaded();
 //   InitializeNativeTarget();
    IRBuilder<> irbuilder(llvm::getGlobalContext());

    llvm::Module* mod = new llvm::Module("",llvm::getGlobalContext());
    mod->setTargetTriple("x86-unknown-linux-gnu");

  /* SET DATA LAYOUT, THIS IS IMPORTANT */
    mod->setDataLayout("e-p:32:32:32-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-n8:16:32:64-S128");
    //mod->getDataLayout();
//    LLVMLinkInInterpreter();
    //Interpreter inp(mod) ;//llvm::Interpreter(mod);

  /* CREATE AN INTERPRETER */
    EngineBuilder builder(mod);
    builder.setEngineKind(EngineKind::Interpreter);
//    builder.setOptLevel(CodeGenOpt::Default);
    EE = builder.create();


    StructType *sty = StructType::create(mod->getContext(),"Struct.MyType");
    vector<Type*> field;
    Type* tp = IntegerType::get(mod->getContext(),32);
    field.push_back(IntegerType::get(mod->getContext(),32));
    field.push_back(IntegerType::get(mod->getContext(),32));
    field.push_back(ArrayType::get(tp,32));
    field.push_back(tp);
    sty->setBody(field,false);
    PointerType* pty = PointerType::get(sty,0);
    vector<Type*> par;
    par.push_back(pty);


    FunctionType* fty = FunctionType::get(IntegerType::get(mod->getContext(),32),par,false);
    Function* f =  Function::Create(fty,GlobalValue::InternalLinkage,"styF",mod);

    Function::arg_iterator it1 = f->arg_begin();
    Value* fv = it1++;
    fv->setName("p");
    fv->getType();
    BasicBlock* fbb = BasicBlock::Create(mod->getContext(),"",
    f,0);
    irbuilder.SetInsertPoint(fbb);
     LoadInst* ld1 = irbuilder.CreateLoad(fv);
    Value*v1 = irbuilder.CreateExtractValue(ld1,2);
    v1 = irbuilder.CreateExtractValue(v1,8);

       ConstantInt* const_int = llvm::ConstantInt::get(mod->getContext(),
    APInt(32,StringRef("522"),10));
      irbuilder.CreateRet(v1);


    // function : setValue
    vector<Type*>FuncTy1_args;
    FuncTy1_args.push_back(pty);
    FuncTy1_args.push_back(IntegerType::get(mod->getContext(),32));
    FunctionType* setfty = FunctionType::get(irbuilder.getVoidTy(),FuncTy1_args,false);
    Function* sf =  Function::Create(setfty,GlobalValue::InternalLinkage,"setValueF",mod);

    BasicBlock* bb1 = BasicBlock::Create(mod->getContext(),"",sf,0);
    irbuilder.SetInsertPoint(bb1);

    it1 = sf->arg_begin();
    Value* arg1 = it1++; arg1->setName("sty");
    Value* arg2 = it1++; arg2->setName("value");
   AllocaInst* ptr1_23=irbuilder.CreateAlloca(pty); ptr1_23->setAlignment(4);
    StoreInst* s_24 = irbuilder.CreateStore(arg1, ptr1_23); s_24->setAlignment(4);
    LoadInst* ptr1_25 = irbuilder.CreateLoad(ptr1_23); ptr1_25->setAlignment(4);

    Value* ptr1_26 = irbuilder.CreateStructGEP(ptr1_25,2);
    ptr1_26 = irbuilder.CreateStructGEP(ptr1_26,1);
    StoreInst* va = irbuilder.CreateStore(arg2, ptr1_26); va->setAlignment(4);
    irbuilder.CreateRetVoid();

    gvar = new llvm::GlobalVariable(*mod,
    llvm::IntegerType::get(mod->getContext(),32),
    false,
    llvm::GlobalValue::InternalLinkage,
    const_int,
    "",
    0,
    0,
    0);
    gvar->setAlignment(4);
//    gvar->setThreadLocal(true);


    Value* hi = irbuilder.CreateGlobalStringPtr("1234567hi\n");

    // printf
    PointerType* PointerTy_71 = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
    std::vector<Type*> FuncTy_12_args;
    FuncTy_12_args.push_back(PointerTy_71);
    FunctionType* FuncTy_12 = FunctionType::get(IntegerType::get(mod->getContext(),32),
    FuncTy_12_args,true);
    Function* func_printf = Function::Create(FuncTy_12,GlobalValue::ExternalLinkage,
    "printf",mod);
    func_printf->setCallingConv(CallingConv::C);

    PointerType* PointerTy_1 = PointerType::get(IntegerType::get(mod->getContext(),64),0);
    StructType* StructTy_union_pthread_attr_t = mod->getTypeByName("union.pthread_attr_t");
    if (!StructTy_union_pthread_attr_t) {
    StructTy_union_pthread_attr_t = StructType::create(mod->getContext(), "union.pthread_attr_t");
    }
    PointerType* PointerTy_7 = PointerType::get(IntegerType::get(mod->getContext(),8),0);
    vector<Type*>FuncTy8_args;
   FunctionType* FuncTy_8 = FunctionType::get(PointerTy_7,
    FuncTy8_args,
    false);

    if(StructTy_union_pthread_attr_t==NULL)cout<<"FUCK NULL"<<endl;
    PointerType* PointerTy_2 = PointerType::get(StructTy_union_pthread_attr_t,0);
    PointerType* PointerTy_3 = PointerType::get(FuncTy_8,0);
    PointerType* PointerTy_4 = PointerType::get(IntegerType::get(mod->getContext(),8),0);

    vector<Type*> FuncTy_args;
    FuncTy_args.push_back(PointerTy_1);
    FuncTy_args.push_back(PointerTy_2);
    FuncTy_args.push_back(PointerTy_3);
    FuncTy_args.push_back(PointerTy_4);

    FunctionType* FuncTy = FunctionType::get(
    IntegerType::get(mod->getContext(),32),
    FuncTy_args,
    false);

        // function : set value
        ConstantInt* const_int32_4 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1321"), 10));
    Function* setV;
    std::vector<Type*> sv_args;
    sv_args.push_back( PointerType::get(IntegerType::get(mod->getContext(),32),0));
    FunctionType* svTy = FunctionType::get(
    Type::getVoidTy(mod->getContext()),
    sv_args,
    false);

    setV = Function::Create(svTy,GlobalValue::ExternalLinkage,"setValue",mod);

    Function::arg_iterator it = setV->arg_begin();
    Value* int32_v = it++;
    int32_v->setName("v");

    BasicBlock* svbb = BasicBlock::Create(mod->getContext(),"",
    setV,0);

    /*AllocaInst* ptr_6 = new AllocaInst(
    PointerType::get(IntegerType::get(mod->getContext(),32),0),
    "",
    svbb);
    ptr_6->setAlignment(4);
    StoreInst* void_7 = new StoreInst(int32_v,ptr_6,false,svbb);
    void_7->setAlignment(4);
    LoadInst* int32_8 = new LoadInst(ptr_6,"",false,svbb);
    int32_8->setAlignment(4);*/
    StoreInst* void_9 = new StoreInst(const_int32_4,int32_v,false,svbb);
    void_9->setAlignment(4);

    ReturnInst::Create(mod->getContext(),svbb);



    // function: getvalue
    std::vector<Type*> gv_args;
    FunctionType* gvTy = FunctionType::get(IntegerType::get(mod->getContext(),32),
    gv_args,
    false);
         Function* gv = Function::Create(gvTy,
    GlobalValue::ExternalLinkage,
    "getValue",mod);
    gv->setCallingConv(CallingConv::C);

    BasicBlock* gvbb = BasicBlock::Create(
    mod->getContext(),
    "",
    gv,
    0);

    irbuilder.SetInsertPoint(gvbb);
    irbuilder.CreateCall(func_printf,hi);
    //LoadInst* ld = irbuilder.CreateLoad(gvar);

//    irbuilder.CreateRet(ld);
    irbuilder.CreateRet(const_int32_4);

    vector<GenericValue> arg;
    GenericValue rv;
    APInt ap;
    unsigned long long uv;

   /* 確保 INTERPRETER 有被 create */
    if(!EE)cout<<"EE null"<<endl;

 

   /* 呼叫 LLVM::FUNCTION gv , 這個 function 沒有參數 */


    rv = EE->runFunction(gv,arg);
    cout<<rv.IntVal.toString(10,1)<<endl;
//    rv.IntVal.dump();
    mod->dump();

    int p = 128;;

//    printf("Pointer : %x\n",(p));

 

   /* 呼叫另一個 LLVM::FUNCTION setV, 參數一個 , 這個function 的 prototype : void setV(int* ) , 因此傳參數使用 PTOGV function, 其實也可以寫成 

       GenericValue gg ; gg.PointerVal = &p;

   */

    arg.push_back(PTOGV(&p));

    EE->runFunction(setV,arg);
    printf("value: %d\n",p);

//    EE->runJITOnFunction(setV,info);
//    EE->runJITOnFunction(gv,info+1);
//    EE->runJITOnFunction(f,info+2);
//    EE->runJITOnFunction(sf,info+3);


    return 0;
}

 

以下為產生的 LLVM IR

target datalayout = "e-p:32:32:32-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-n8:16:32:64-S128"
target triple = "x86-unknown-linux-gnu"

%Struct.MyType = type { i32, i32, [32 x i32], i32 }

@0 = internal global i32 522, align 4
@1 = private unnamed_addr constant [11 x i8] c"1234567hi\0A\00"

define internal i32 @styF(%Struct.MyType* %p) {
  %1 = load %Struct.MyType* %p
  %2 = extractvalue %Struct.MyType %1, 2
  %3 = extractvalue [32 x i32] %2, 8
  ret i32 %3
}

define internal void @setValueF(%Struct.MyType* %sty, i32 %value) {
  %1 = alloca %Struct.MyType*, align 4
  store %Struct.MyType* %sty, %Struct.MyType** %1, align 4
  %2 = load %Struct.MyType** %1, align 4
  %3 = getelementptr inbounds %Struct.MyType* %2, i32 0, i32 2
  %4 = getelementptr inbounds [32 x i32]* %3, i32 0, i32 1
  store i32 %value, i32* %4, align 4
  ret void
}

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

define void @setValue(i32* %v) {
  store i32 1321, i32* %v, align 4
  ret void
}

define i32 @getValue() {
  %1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @1, i32 0, i32 0))
  ret i32 1321
}

 

執行結果印出

value: 1321

原本值是 128

 

%注意%

LLVM 沒有辦法讓 user 直接開一個 interpreter 的 instance ,而需要用 ExecutionEngine 去創造。

傳參數需要用 GenericValue,裡頭有一個 Union structure ,依造你所需要的 type 給值, 但 int 似乎要另外放, 放在 一個 APInt IntVal 的參數。

將 c int 轉成APint ,APInt(32,c) 及可。

因為Interpreter store, load 時,會查user 所設定的 data layout ,所以一定要設定。

 

 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 lettice0913 的頭像
    lettice0913

    斑的家

    lettice0913 發表在 痞客邦 留言(0) 人氣()