我接触llvm的主要目的是写pass,但llvm ir以及ir对应的api让我很头疼。为了快速熟悉这套api,我需要一种快速编写、快速测试的方法,最后了解到llvm jit的存在。
但是在网上找了一些教材后,发现都不能顺利的跑起来,就连llvm源码中提供的example我也没能顺利的跑起来,一度让我怀疑自己是不是该放弃。在垂死挣扎之后,终于让我跑通了。
下面用一个简单例子来演示怎么使用llvm api新建module以及function,并且用jit去执行函数。
我们的目的是生成下面两个函数,并且调用foo,最后能打出执行结果11。
我把整个代码分成两部分,一部分是使用llvm ir指令生成上面函数,第二部分是使用llvm jit去执行上面函数。
下面是第一部分代码,
下面是第二部分代码
最后使用clang++进行编译生成可执行文件
下面是执行的效果,可以看到生成的中间代码以及运行的结果。通过这种方式,感觉可以很方便的学习llvm ir指令以及对应的api。
代码仓库地址
int
add1(
int
x) {
return
x
+
1
;
}
int
foo() {
return
add1(
10
);
}
int
add1(
int
x) {
return
x
+
1
;
}
int
foo() {
return
add1(
10
);
}
int
initModule(LLVMContext &Context, Module
*
M, Function
*
FooF) {
/
/
Create the add1 function entry
and
insert this entry into module M. The
/
/
function will have a
return
type
of
"int"
and
take an argument of
"int"
.
Function
*
Add1F
=
cast<Function>(M
-
>getOrInsertFunction(
"add1"
,
Type
::getInt32Ty(Context),
Type
::getInt32Ty(Context)));
/
/
Add a basic block to the function. As before, it automatically inserts
/
/
because of the last argument.
BasicBlock
*
BB
=
BasicBlock::Create(Context,
"EntryBlock"
, Add1F);
/
/
Create a basic block builder with default parameters. The builder will
/
/
automatically append instructions to the basic block `BB'.
IRBuilder<> builder(BB);
/
/
Get pointers to the constant `
1
'.
Value
*
One
=
builder.getInt32(
1
);
/
/
Get pointers to the integer argument of the add1 function...
assert
(Add1F
-
>arg_begin() !
=
Add1F
-
>arg_end());
/
/
Make sure there's an arg
Argument
*
ArgX
=
&
*
Add1F
-
>arg_begin();
/
/
Get the arg
ArgX
-
>setName(
"AnArg"
);
/
/
Give it a nice symbolic name
for
fun.
/
/
Create the add instruction, inserting it into the end of BB.
Value
*
Add
=
builder.CreateAdd(One, ArgX);
/
/
Create the
return
instruction
and
add it to the basic block
builder.CreateRet(Add);
/
/
Now, function add1
is
ready.
/
/
Now we
're going to create function `foo'
, which returns an
int
and
takes no
/
/
arguments.
/
/
Add a basic block to the FooF function.
BB
=
BasicBlock::Create(Context,
"EntryBlock"
, FooF);
/
/
Tell the basic block builder to attach itself to the new basic block
builder.SetInsertPoint(BB);
/
/
Get pointer to the constant `
10
'.
Value
*
Ten
=
builder.getInt32(
10
);
/
/
Pass Ten to the call to Add1F
CallInst
*
Add1CallRes
=
builder.CreateCall(Add1F, Ten);
Add1CallRes
-
>setTailCall(true);
/
/
Create the
return
instruction
and
add it to the basic block.
builder.CreateRet(Add1CallRes);
}
int
initModule(LLVMContext &Context, Module
*
M, Function
*
FooF) {
/
/
Create the add1 function entry
and
insert this entry into module M. The
/
/
function will have a
return
type
of
"int"
and
take an argument of
"int"
.
Function
*
Add1F
=
cast<Function>(M
-
>getOrInsertFunction(
"add1"
,
Type
::getInt32Ty(Context),
Type
::getInt32Ty(Context)));
/
/
Add a basic block to the function. As before, it automatically inserts
/
/
because of the last argument.
BasicBlock
*
BB
=
BasicBlock::Create(Context,
"EntryBlock"
, Add1F);
/
/
Create a basic block builder with default parameters. The builder will
/
/
automatically append instructions to the basic block `BB'.
IRBuilder<> builder(BB);
/
/
Get pointers to the constant `
1
'.
Value
*
One
=
builder.getInt32(
1
);
/
/
Get pointers to the integer argument of the add1 function...
assert
(Add1F
-
>arg_begin() !
=
Add1F
-
>arg_end());
/
/
Make sure there's an arg
Argument
*
ArgX
=
&
*
Add1F
-
>arg_begin();
/
/
Get the arg
ArgX
-
>setName(
"AnArg"
);
/
/
Give it a nice symbolic name
for
fun.
/
/
Create the add instruction, inserting it into the end of BB.
Value
*
Add
=
builder.CreateAdd(One, ArgX);
/
/
Create the
return
instruction
and
add it to the basic block
builder.CreateRet(Add);
/
/
Now, function add1
is
ready.
/
/
Now we
're going to create function `foo'
, which returns an
int
and
takes no
/
/
arguments.
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)