第160集:生成 LLVM IR(一)
LLVM IR生成的基本概念
生成 LLVM IR 是编译器前端的重要任务,它将抽象语法树(AST)转换为 LLVM IR,为后续的优化和代码生成做准备。LLVM 提供了丰富的 API 来帮助开发者生成 LLVM IR,这些 API 可以通过 C++、C、Python 等语言使用。本集将介绍如何使用 LLVM 的 API 生成 LLVM IR,包括模块与函数的创建、类型系统的使用和指令生成的方法。
LLVM IR生成的步骤
- 创建模块:模块是 LLVM IR 的顶层容器,对应于一个编译单元
- 创建函数:在模块中定义函数
- 创建基本块:在函数中创建基本块
- 生成指令:在基本块中生成指令
- 设置函数返回值:为函数设置返回值
- 验证模块:验证生成的 LLVM IR 是否有效
- 输出模块:将生成的 LLVM IR 输出为汇编形式或二进制形式
模块与函数
创建模块
模块是 LLVM IR 的顶层容器,它包含函数、全局变量、常量等。创建模块是生成 LLVM IR 的第一步。
C++ API 示例
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
using namespace llvm;
int main() {
// 创建 LLVM 上下文
LLVMContext Context;
// 创建模块
Module *M = new Module("example.ll", Context);
// 设置目标三元组
M->setTargetTriple("x86_64-pc-linux-gnu");
// 后续操作...
return 0;
}Python API 示例
from llvm import ir
# 创建模块
module = ir.Module(name="example.ll")
# 设置目标三元组
module.triple = "x86_64-pc-linux-gnu"
# 后续操作...创建函数
函数是 LLVM IR 中的可执行代码块,它包含参数、返回类型和函数体。创建函数需要指定函数类型、函数名和链接类型。
C++ API 示例
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
// 创建函数类型:int (int, int)
FunctionType *FuncType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context), Type::getInt32Ty(Context)},
false);
// 创建函数
Function *Func = Function::Create(FuncType,
Function::ExternalLinkage,
"add",
M);
// 设置函数参数名
Function::arg_iterator Args = Func->arg_begin();
Args->setName("a");
Args++;
Args->setName("b");Python API 示例
from llvm import ir
# 创建函数类型:int (int, int)
func_type = ir.FunctionType(ir.IntType(32), [ir.IntType(32), ir.IntType(32)], False)
# 创建函数
func = ir.Function(module, func_type, name="add")
# 设置函数参数名
func.args[0].name = "a"
func.args[1].name = "b"创建基本块
基本块是函数中的一个连续的指令序列,只有一个入口点和一个出口点。创建基本块是生成函数体的第一步。
C++ API 示例
#include "llvm/IR/BasicBlock.h"
// 创建基本块
BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Func);Python API 示例
from llvm import ir
# 创建基本块
entry_bb = ir.BasicBlock(func, name="entry")类型系统
LLVM IR 是类型安全的,每个值都有明确的类型。LLVM 提供了丰富的类型系统,包括基本类型、指针类型、数组类型、结构体类型和函数类型等。
基本类型
基本类型包括整数类型、浮点类型和空类型。
C++ API 示例
#include "llvm/IR/Type.h"
// 整数类型
Type *Int1Ty = Type::getInt1Ty(Context); // 布尔值
Type *Int8Ty = Type::getInt8Ty(Context); // 字节
Type *Int16Ty = Type::getInt16Ty(Context); // 短整型
Type *Int32Ty = Type::getInt32Ty(Context); // 整型
Type *Int64Ty = Type::getInt64Ty(Context); // 长整型
// 浮点类型
Type *FloatTy = Type::getFloatTy(Context); // 单精度浮点
Type *DoubleTy = Type::getDoubleTy(Context); // 双精度浮点
// 空类型
Type *VoidTy = Type::getVoidTy(Context); // 空类型Python API 示例
from llvm import ir
# 整数类型
int1_ty = ir.IntType(1) # 布尔值
int8_ty = ir.IntType(8) # 字节
int16_ty = ir.IntType(16) # 短整型
int32_ty = ir.IntType(32) # 整型
int64_ty = ir.IntType(64) # 长整型
# 浮点类型
float_ty = ir.FloatType() # 单精度浮点
double_ty = ir.DoubleType() # 双精度浮点
# 空类型
void_ty = ir.VoidType() # 空类型指针类型
指针类型表示指向其他类型的指针。
C++ API 示例
// 指针类型
Type *Int32PtrTy = Type::getInt32PtrTy(Context); // 指向整型的指针
Type *FloatPtrTy = Type::getFloatPtrTy(Context); // 指向单精度浮点的指针Python API 示例
from llvm import ir
# 指针类型
int32_ptr_ty = ir.PointerType(ir.IntType(32)) # 指向整型的指针
float_ptr_ty = ir.PointerType(ir.FloatType()) # 指向单精度浮点的指针数组类型
数组类型表示固定大小的数组。
C++ API 示例
// 数组类型
Type *ArrayTy = ArrayType::get(Type::getInt32Ty(Context), 10); // 10个整型的数组Python API 示例
from llvm import ir
# 数组类型
array_ty = ir.ArrayType(ir.IntType(32), 10) # 10个整型的数组结构体类型
结构体类型表示包含多个成员的复合类型。
C++ API 示例
// 结构体类型
StructType *StructTy = StructType::create(Context, "Point");
std::vector<Type *> Members;
Members.push_back(Type::getInt32Ty(Context)); // x 坐标
Members.push_back(Type::getInt32Ty(Context)); // y 坐标
StructTy->setBody(Members);Python API 示例
from llvm import ir
# 结构体类型
struct_ty = ir.StructType([ir.IntType(32), ir.IntType(32)], name="Point") # 包含两个整型成员的结构体函数类型
函数类型表示函数的参数类型和返回类型。
C++ API 示例
// 函数类型:int (int, int)
FunctionType *FuncType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context), Type::getInt32Ty(Context)},
false);
// 函数类型:void ()
FunctionType *VoidFuncType = FunctionType::get(Type::getVoidTy(Context), false);Python API 示例
from llvm import ir
# 函数类型:int (int, int)
func_type = ir.FunctionType(ir.IntType(32), [ir.IntType(32), ir.IntType(32)], False)
# 函数类型:void ()
void_func_type = ir.FunctionType(ir.VoidType(), False)指令生成
基本指令生成
指令是 LLVM IR 的基本执行单位,生成指令是生成 LLVM IR 的核心任务。LLVM 提供了丰富的 API 来生成各种类型的指令。
C++ API 示例:生成加法指令
#include "llvm/IR/IRBuilder.h"
// 创建 IR 构建器
IRBuilder<> Builder(EntryBB);
// 获取函数参数
Function::arg_iterator Args = Func->arg_begin();
Value *A = Args++;
Value *B = Args;
// 生成加法指令
Value *Sum = Builder.CreateAdd(A, B, "sum");Python API 示例:生成加法指令
from llvm import ir
# 创建 IR 构建器
builder = ir.IRBuilder(entry_bb)
# 获取函数参数
a = func.args[0]
b = func.args[1]
# 生成加法指令
sum_val = builder.add(a, b, name="sum")控制流指令生成
控制流指令用于控制程序的执行流程,如条件分支、无条件跳转等。
C++ API 示例:生成条件分支指令
// 创建基本块
BasicBlock *IfTrueBB = BasicBlock::Create(Context, "if_true", Func);
BasicBlock *IfFalseBB = BasicBlock::Create(Context, "if_false", Func);
BasicBlock *EndBB = BasicBlock::Create(Context, "end", Func);
// 生成比较指令
Value *Cmp = Builder.CreateICmpSGT(A, B, "cmp");
// 生成条件分支指令
Builder.CreateCondBr(Cmp, IfTrueBB, IfFalseBB);
// 填充 if_true 基本块
Builder.SetInsertPoint(IfTrueBB);
Builder.CreateBr(EndBB);
// 填充 if_false 基本块
Builder.SetInsertPoint(IfFalseBB);
Builder.CreateBr(EndBB);
// 填充 end 基本块
Builder.SetInsertPoint(EndBB);Python API 示例:生成条件分支指令
from llvm import ir
# 创建基本块
if_true_bb = ir.BasicBlock(func, name="if_true")
if_false_bb = ir.BasicBlock(func, name="if_false")
end_bb = ir.BasicBlock(func, name="end")
# 生成比较指令
cmp_val = builder.icmp_sgt(a, b, name="cmp")
# 生成条件分支指令
builder.cbranch(cmp_val, if_true_bb, if_false_bb)
# 填充 if_true 基本块
builder.position_at_end(if_true_bb)
builder.branch(end_bb)
# 填充 if_false 基本块
builder.position_at_end(if_false_bb)
builder.branch(end_bb)
# 填充 end 基本块
builder.position_at_end(end_bb)内存指令生成
内存指令用于访问内存,如加载、存储、分配内存等。
C++ API 示例:生成内存指令
// 生成 alloca 指令
Value *Ptr = Builder.CreateAlloca(Type::getInt32Ty(Context), nullptr, "ptr");
// 生成 store 指令
Builder.CreateStore(A, Ptr);
// 生成 load 指令
Value *LoadedVal = Builder.CreateLoad(Type::getInt32Ty(Context), Ptr, "loaded_val");Python API 示例:生成内存指令
from llvm import ir
# 生成 alloca 指令
ptr = builder.alloca(ir.IntType(32), name="ptr")
# 生成 store 指令
builder.store(a, ptr)
# 生成 load 指令
loaded_val = builder.load(ptr, name="loaded_val")函数调用指令生成
函数调用指令用于调用函数。
C++ API 示例:生成函数调用指令
// 创建函数类型:int (int, int)
FunctionType *FuncType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context), Type::getInt32Ty(Context)},
false);
// 声明外部函数
Function *Callee = Function::Create(FuncType,
Function::ExternalLinkage,
"foo",
M);
// 生成函数调用指令
Value *CallArgs[] = {A, B};
Value *Call = Builder.CreateCall(Callee, CallArgs, "call_foo");Python API 示例:生成函数调用指令
from llvm import ir
# 创建函数类型:int (int, int)
callee_type = ir.FunctionType(ir.IntType(32), [ir.IntType(32), ir.IntType(32)], False)
# 声明外部函数
callee = ir.Function(module, callee_type, name="foo")
# 生成函数调用指令
call = builder.call(callee, [a, b], name="call_foo")代码示例
示例1:生成简单的加法函数
C++ API 示例
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
int main() {
// 创建 LLVM 上下文
LLVMContext Context;
// 创建模块
Module *M = new Module("add.ll", Context);
// 设置目标三元组
M->setTargetTriple("x86_64-pc-linux-gnu");
// 创建函数类型:int (int, int)
FunctionType *FuncType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context), Type::getInt32Ty(Context)},
false);
// 创建函数
Function *AddFunc = Function::Create(FuncType,
Function::ExternalLinkage,
"add",
M);
// 设置函数参数名
Function::arg_iterator Args = AddFunc->arg_begin();
Args->setName("a");
Args++;
Args->setName("b");
// 创建基本块
BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", AddFunc);
// 创建 IR 构建器
IRBuilder<> Builder(EntryBB);
// 获取函数参数
Args = AddFunc->arg_begin();
Value *A = Args++;
Value *B = Args;
// 生成加法指令
Value *Sum = Builder.CreateAdd(A, B, "sum");
// 生成返回指令
Builder.CreateRet(Sum);
// 验证模块
if (verifyModule(*M, &errs())) {
errs() << "模块验证失败!\n";
return 1;
}
// 输出模块
M->print(errs(), nullptr);
// 清理资源
delete M;
return 0;
}Python API 示例
from llvm import ir
# 创建模块
module = ir.Module(name="add.ll")
# 设置目标三元组
module.triple = "x86_64-pc-linux-gnu"
# 创建函数类型:int (int, int)
func_type = ir.FunctionType(ir.IntType(32), [ir.IntType(32), ir.IntType(32)], False)
# 创建函数
func = ir.Function(module, func_type, name="add")
# 设置函数参数名
func.args[0].name = "a"
func.args[1].name = "b"
# 创建基本块
entry_bb = ir.BasicBlock(func, name="entry")
# 创建 IR 构建器
builder = ir.IRBuilder(entry_bb)
# 获取函数参数
a = func.args[0]
b = func.args[1]
# 生成加法指令
sum_val = builder.add(a, b, name="sum")
# 生成返回指令
builder.ret(sum_val)
# 输出模块
print(module)示例2:生成条件语句
C++ API 示例
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
int main() {
// 创建 LLVM 上下文
LLVMContext Context;
// 创建模块
Module *M = new Module("max.ll", Context);
// 设置目标三元组
M->setTargetTriple("x86_64-pc-linux-gnu");
// 创建函数类型:int (int, int)
FunctionType *FuncType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context), Type::getInt32Ty(Context)},
false);
// 创建函数
Function *MaxFunc = Function::Create(FuncType,
Function::ExternalLinkage,
"max",
M);
// 设置函数参数名
Function::arg_iterator Args = MaxFunc->arg_begin();
Args->setName("a");
Args++;
Args->setName("b");
// 创建基本块
BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", MaxFunc);
BasicBlock *IfTrueBB = BasicBlock::Create(Context, "if_true", MaxFunc);
BasicBlock *IfFalseBB = BasicBlock::Create(Context, "if_false", MaxFunc);
BasicBlock *EndBB = BasicBlock::Create(Context, "end", MaxFunc);
// 创建 IR 构建器
IRBuilder<> Builder(EntryBB);
// 获取函数参数
Args = MaxFunc->arg_begin();
Value *A = Args++;
Value *B = Args;
// 生成比较指令
Value *Cmp = Builder.CreateICmpSGT(A, B, "cmp");
// 生成条件分支指令
Builder.CreateCondBr(Cmp, IfTrueBB, IfFalseBB);
// 填充 if_true 基本块
Builder.SetInsertPoint(IfTrueBB);
Builder.CreateBr(EndBB);
// 填充 if_false 基本块
Builder.SetInsertPoint(IfFalseBB);
Builder.CreateBr(EndBB);
// 填充 end 基本块
Builder.SetInsertPoint(EndBB);
// 生成 PHI 指令
PHINode *Phi = Builder.CreatePHI(Type::getInt32Ty(Context), 2, "max_val");
Phi->addIncoming(A, IfTrueBB);
Phi->addIncoming(B, IfFalseBB);
// 生成返回指令
Builder.CreateRet(Phi);
// 验证模块
if (verifyModule(*M, &errs())) {
errs() << "模块验证失败!\n";
return 1;
}
// 输出模块
M->print(errs(), nullptr);
// 清理资源
delete M;
return 0;
}Python API 示例
from llvm import ir
# 创建模块
module = ir.Module(name="max.ll")
# 设置目标三元组
module.triple = "x86_64-pc-linux-gnu"
# 创建函数类型:int (int, int)
func_type = ir.FunctionType(ir.IntType(32), [ir.IntType(32), ir.IntType(32)], False)
# 创建函数
func = ir.Function(module, func_type, name="max")
# 设置函数参数名
func.args[0].name = "a"
func.args[1].name = "b"
# 创建基本块
entry_bb = ir.BasicBlock(func, name="entry")
if_true_bb = ir.BasicBlock(func, name="if_true")
if_false_bb = ir.BasicBlock(func, name="if_false")
end_bb = ir.BasicBlock(func, name="end")
# 创建 IR 构建器
builder = ir.IRBuilder(entry_bb)
# 获取函数参数
a = func.args[0]
b = func.args[1]
# 生成比较指令
cmp_val = builder.icmp_sgt(a, b, name="cmp")
# 生成条件分支指令
builder.cbranch(cmp_val, if_true_bb, if_false_bb)
# 填充 if_true 基本块
builder.position_at_end(if_true_bb)
builder.branch(end_bb)
# 填充 if_false 基本块
builder.position_at_end(if_false_bb)
builder.branch(end_bb)
# 填充 end 基本块
builder.position_at_end(end_bb)
# 生成 PHI 指令
phi = builder.phi(ir.IntType(32), name="max_val")
phi.add_incoming(a, if_true_bb)
phi.add_incoming(b, if_false_bb)
# 生成返回指令
builder.ret(phi)
# 输出模块
print(module)示例3:生成循环语句
C++ API 示例
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
int main() {
// 创建 LLVM 上下文
LLVMContext Context;
// 创建模块
Module *M = new Module("sum.ll", Context);
// 设置目标三元组
M->setTargetTriple("x86_64-pc-linux-gnu");
// 创建函数类型:int (int)
FunctionType *FuncType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context)},
false);
// 创建函数
Function *SumFunc = Function::Create(FuncType,
Function::ExternalLinkage,
"sum",
M);
// 设置函数参数名
Function::arg_iterator Args = SumFunc->arg_begin();
Args->setName("n");
// 创建基本块
BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", SumFunc);
BasicBlock *LoopCondBB = BasicBlock::Create(Context, "loop_cond", SumFunc);
BasicBlock *LoopBodyBB = BasicBlock::Create(Context, "loop_body", SumFunc);
BasicBlock *LoopEndBB = BasicBlock::Create(Context, "loop_end", SumFunc);
// 创建 IR 构建器
IRBuilder<> Builder(EntryBB);
// 获取函数参数
Value *N = SumFunc->arg_begin();
// 生成 alloca 指令
Value *S = Builder.CreateAlloca(Type::getInt32Ty(Context), nullptr, "s");
Value *I = Builder.CreateAlloca(Type::getInt32Ty(Context), nullptr, "i");
// 生成存储指令
Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(Context), 0), S);
Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(Context), 0), I);
// 跳转到循环条件基本块
Builder.CreateBr(LoopCondBB);
// 填充循环条件基本块
Builder.SetInsertPoint(LoopCondBB);
Value *LoadedI = Builder.CreateLoad(Type::getInt32Ty(Context), I, "loaded_i");
Value *Cmp = Builder.CreateICmpSLT(LoadedI, N, "cmp");
Builder.CreateCondBr(Cmp, LoopBodyBB, LoopEndBB);
// 填充循环体基本块
Builder.SetInsertPoint(LoopBodyBB);
Value *LoadedS = Builder.CreateLoad(Type::getInt32Ty(Context), S, "loaded_s");
Value *LoadedI2 = Builder.CreateLoad(Type::getInt32Ty(Context), I, "loaded_i2");
Value *Add = Builder.CreateAdd(LoadedS, LoadedI2, "add");
Builder.CreateStore(Add, S);
Value *LoadedI3 = Builder.CreateLoad(Type::getInt32Ty(Context), I, "loaded_i3");
Value *Inc = Builder.CreateAdd(LoadedI3, ConstantInt::get(Type::getInt32Ty(Context), 1), "inc");
Builder.CreateStore(Inc, I);
Builder.CreateBr(LoopCondBB);
// 填充循环结束基本块
Builder.SetInsertPoint(LoopEndBB);
Value *FinalS = Builder.CreateLoad(Type::getInt32Ty(Context), S, "final_s");
Builder.CreateRet(FinalS);
// 验证模块
if (verifyModule(*M, &errs())) {
errs() << "模块验证失败!\n";
return 1;
}
// 输出模块
M->print(errs(), nullptr);
// 清理资源
delete M;
return 0;
}Python API 示例
from llvm import ir
# 创建模块
module = ir.Module(name="sum.ll")
# 设置目标三元组
module.triple = "x86_64-pc-linux-gnu"
# 创建函数类型:int (int)
func_type = ir.FunctionType(ir.IntType(32), [ir.IntType(32)], False)
# 创建函数
func = ir.Function(module, func_type, name="sum")
# 设置函数参数名
func.args[0].name = "n"
# 创建基本块
entry_bb = ir.BasicBlock(func, name="entry")
loop_cond_bb = ir.BasicBlock(func, name="loop_cond")
loop_body_bb = ir.BasicBlock(func, name="loop_body")
loop_end_bb = ir.BasicBlock(func, name="loop_end")
# 创建 IR 构建器
builder = ir.IRBuilder(entry_bb)
# 获取函数参数
n = func.args[0]
# 生成 alloca 指令
s = builder.alloca(ir.IntType(32), name="s")
i = builder.alloca(ir.IntType(32), name="i")
# 生成存储指令
builder.store(ir.Constant(ir.IntType(32), 0), s)
builder.store(ir.Constant(ir.IntType(32), 0), i)
# 跳转到循环条件基本块
builder.branch(loop_cond_bb)
# 填充循环条件基本块
builder.position_at_end(loop_cond_bb)
loaded_i = builder.load(i, name="loaded_i")
cmp_val = builder.icmp_slt(loaded_i, n, name="cmp")
builder.cbranch(cmp_val, loop_body_bb, loop_end_bb)
# 填充循环体基本块
builder.position_at_end(loop_body_bb)
loaded_s = builder.load(s, name="loaded_s")
loaded_i2 = builder.load(i, name="loaded_i2")
add_val = builder.add(loaded_s, loaded_i2, name="add")
builder.store(add_val, s)
loaded_i3 = builder.load(i, name="loaded_i3")
inc_val = builder.add(loaded_i3, ir.Constant(ir.IntType(32), 1), name="inc")
builder.store(inc_val, i)
builder.branch(loop_cond_bb)
# 填充循环结束基本块
builder.position_at_end(loop_end_bb)
final_s = builder.load(s, name="final_s")
builder.ret(final_s)
# 输出模块
print(module)验证与输出
验证模块
验证模块是确保生成的 LLVM IR 有效的重要步骤。LLVM 提供了验证模块的 API,可以检测出无效的 LLVM IR。
C++ API 示例
#include "llvm/IR/Verifier.h"
#include "llvm/Support/raw_ostream.h"
// 验证模块
if (verifyModule(*M, &errs())) {
errs() << "模块验证失败!\n";
return 1;
}输出模块
输出模块可以将生成的 LLVM IR 输出为汇编形式或二进制形式。
C++ API 示例:输出为汇编形式
#include "llvm/Support/raw_ostream.h"
// 输出模块
M->print(errs(), nullptr);C++ API 示例:输出为二进制形式
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Support/FileUtilities.h"
// 输出为二进制形式
std::error_code EC;
raw_fd_ostream OS("output.bc", EC);
if (!EC) {
WriteBitcodeToFile(*M, OS);
OS.flush();
}实用案例分析
案例:生成函数调用
问题:生成一个函数,该函数调用另一个函数并返回结果。
分析:
- 创建模块
- 声明外部函数
- 创建调用函数
- 在调用函数中生成函数调用指令
- 返回调用结果
C++ API 实现:
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
int main() {
// 创建 LLVM 上下文
LLVMContext Context;
// 创建模块
Module *M = new Module("call.ll", Context);
// 设置目标三元组
M->setTargetTriple("x86_64-pc-linux-gnu");
// 创建函数类型:int (int, int)
FunctionType *FooType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context), Type::getInt32Ty(Context)},
false);
// 声明外部函数 foo
Function *FooFunc = Function::Create(FooType,
Function::ExternalLinkage,
"foo",
M);
// 创建函数类型:int (int, int)
FunctionType *BarType = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context), Type::getInt32Ty(Context)},
false);
// 创建函数 bar
Function *BarFunc = Function::Create(BarType,
Function::ExternalLinkage,
"bar",
M);
// 设置函数参数名
Function::arg_iterator Args = BarFunc->arg_begin();
Args->setName("a");
Args++;
Args->setName("b");
// 创建基本块
BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", BarFunc);
// 创建 IR 构建器
IRBuilder<> Builder(EntryBB);
// 获取函数参数
Value *A = BarFunc->arg_begin();
Value *B = (++BarFunc->arg_begin());
// 生成函数调用指令
Value *CallArgs[] = {A, B};
Value *Call = Builder.CreateCall(FooFunc, CallArgs, "call_foo");
// 生成返回指令
Builder.CreateRet(Call);
// 验证模块
if (verifyModule(*M, &errs())) {
errs() << "模块验证失败!\n";
return 1;
}
// 输出模块
M->print(errs(), nullptr);
// 清理资源
delete M;
return 0;
}小结
本集我们学习了如何生成 LLVM IR,包括:
- LLVM IR生成的基本概念:生成步骤和基本流程
- 模块与函数:创建模块和函数的方法
- 类型系统:基本类型、指针类型、数组类型、结构体类型和函数类型的使用
- 指令生成:基本指令、控制流指令、内存指令和函数调用指令的生成方法
- 代码示例:生成简单的加法函数、条件语句和循环语句的示例
- 验证与输出:验证模块的有效性和输出模块的方法
- 实用案例分析:生成函数调用的案例
通过本集的学习,你应该能够理解如何使用 LLVM 的 API 生成 LLVM IR,以及 LLVM IR 生成在编译器中的重要作用。LLVM 提供了丰富的 API 来帮助开发者生成 LLVM IR,这些 API 设计合理,使用方便,可以大大简化编译器前端的开发工作。在实际开发中,你可以根据具体的需求选择合适的 API 来生成 LLVM IR,为后续的优化和代码生成做准备。
思考与练习
编写一个程序,生成一个函数,该函数计算两个整数的乘积。
编写一个程序,生成一个函数,该函数计算一个整数的阶乘。
编写一个程序,生成一个函数,该函数计算一个数组的和。
编写一个程序,生成一个函数,该函数实现选择排序算法。
讨论 LLVM IR 生成与抽象语法树(AST)的关系,以及如何将 AST 转换为 LLVM IR。