当前位置:网站首页>LLVM系列第九章:控制流语句if-else
LLVM系列第九章:控制流语句if-else
2022-08-02 14:07:00 【飞翼剑仆】
系列文章目录
LLVM系列第一章:编译LLVM源码
LLVM系列第二章:模块Module
LLVM系列第三章:函数Function
LLVM系列第四章:逻辑代码块Block
LLVM系列第五章:全局变量Global Variable
LLVM系列第六章:函数返回值Return
LLVM系列第七章:函数参数Function Arguments
LLVM系列第八章:算术运算语句Arithmetic Statement
LLVM系列第九章:控制流语句if-else
LLVM系列第十章:控制流语句if-else-phi
LLVM系列第十一章:写一个Hello World
LLVM系列第十二章:写一个简单的词法分析器Lexer
LLVM系列第十三章:写一个简单的语法分析器Parser
LLVM系列第十四章:写一个简单的语义分析器Semantic Analyzer
LLVM系列第十五章:写一个简单的中间代码生成器IR Generator
LLVM系列第十六章:写一个简单的编译器
LLVM系列第十七章:for循环
LLVM系列第十八章:写一个简单的IR处理流程Pass
LLVM系列第十九章:写一个简单的Module Pass
LLVM系列第二十章:写一个简单的Function Pass
LLVM系列第二十一章:写一个简单的Loop Pass
LLVM系列第二十二章:写一个简单的编译时函数调用统计器(Pass)
LLVM系列第二十三章:写一个简单的运行时函数调用统计器(Pass)
LLVM系列第二十四章:用Xcode编译调试LLVM源码
LLVM系列第二十五章:简单统计一下LLVM源码行数
前言
在此记录下用LLVM创建if-else控制流语句的过程,以备查阅。
开发环境的配置请参考第一章 《LLVM系列第一章:编译LLVM源码》。
我们知道,一个if-else语句包含了一个条件判断以及两个逻辑分支。最终会运行哪个分支的代码,取决于条件判断的结果为真还是假。而“条件”则一般是一个比较表达式。
本章,我们就来创建简单的if-else控制流语句。
一、Hello if-else
为简单起见,我就来为以下这个简单的C函数生成IR代码(示例):
// Test.c
int Test(int a)
{
int b;
if (a > 33)
{
b = 66;
}
else
{
b = 77;
}
return b;
}
这里有个可变变量b,当然它也是一个局部变量,我们可以在栈上创建一个可变变量。LLVM IR提供了一个指令,可以让我们在栈上申明变量,即 alloca 指令。它使用起来也很简单(示例):
%variable.address = alloca i32
LLVM也提供了相应的C++ API用于在栈上申明变量:
AllocaInst * llvm::IRBuilderBase::CreateAlloca(Type * Ty, Value * ArraySize = nullptr, const Twine & Name = "")
注意用alloca 指令申明的变量,其实得到是变量的地址。如果要访问它,我们需要用store和load指令。store指令可以把变量值写入该地址(示例):
store i32 66, i32* %variable.address, align 4
而load指令则可以把变量值从该地址的读取出来(示例):
%actual.value = load i32, i32* %variable.address, align 4
以下就是我们调用LLVM C++ API来生成IR的代码(示例):
// HelloIfElse.cpp
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include <vector>
using namespace llvm;
int main(int argc, char* argv[])
{
LLVMContext context;
IRBuilder<> builder(context);
// Create a module
Module* module = new Module("Test.c", context);
// Add a function
std::vector<Type*> parameters(1, builder.getInt32Ty());
FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), parameters, false);
Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "Test", module);
// Add an argument to the function
Value* arg = function->getArg(0);
arg->setName("a");
// Add some basic blocks to the function
BasicBlock* entryBlock = BasicBlock::Create(context, "entry", function);
BasicBlock* thenBlock = BasicBlock::Create(context, "if.then", function);
BasicBlock* elseBlock = BasicBlock::Create(context, "if.else", function);
BasicBlock* returnBlock = BasicBlock::Create(context, "if.end", function);
// Fill the "entry" block (1):
// int b;
builder.SetInsertPoint(entryBlock);
Value* bPtr = builder.CreateAlloca(builder.getInt32Ty(), nullptr, "b.address");
// Fill the "entry" block (2):
// if (a > 33)
ConstantInt* value33 = builder.getInt32(33);
Value* condition = builder.CreateICmpSGT(arg, value33, "compare.result");
builder.CreateCondBr(condition, thenBlock, elseBlock);
// Fill the "if.then" block:
// b = 66;
builder.SetInsertPoint(thenBlock);
ConstantInt* value66 = builder.getInt32(66);
builder.CreateStore(value66, bPtr);
builder.CreateBr(returnBlock);
// Fill the "if.else" block:
// b = 77;
builder.SetInsertPoint(elseBlock);
ConstantInt* value77 = builder.getInt32(77);
builder.CreateStore(value77, bPtr);
builder.CreateBr(returnBlock);
// Fill the "if.end" block:
// return b;
builder.SetInsertPoint(returnBlock);
Value* returnValue = builder.CreateLoad(bPtr, "return.value");
builder.CreateRet(returnValue);
// Print the IR
verifyFunction(*function);
module->print(outs(), nullptr);
return 0;
}
二、编译
用clang++进行编译(示例):
# Set up C++ standard library and header path
export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
# Compile
clang++ -w -o HelloIfElse `llvm-config --cxxflags --ldflags --system-libs --libs core` HelloIfElse.cpp
以上命令会生成一个名为HelloIfElse的可执行程序。
三、运行
运行HelloIfElse(示例):
./HelloIfElse
输出结果如下(示例):
; ModuleID = 'Test.c'
source_filename = "Test.c"
define i32 @Test(i32 %a) {
entry:
%b.address = alloca i32, align 4
%compare.result = icmp sgt i32 %a, 33
br i1 %compare.result, label %if.then, label %if.else
if.then: ; preds = %entry
store i32 66, i32* %b.address, align 4
br label %if.end
if.else: ; preds = %entry
store i32 77, i32* %b.address, align 4
br label %if.end
if.end: ; preds = %if.else, %if.then
%return.value = load i32, i32* %b.address, align 4
ret i32 %return.value
}
四、总结
我们用LLVM提供的C++ API,创建了简单的if-else控制流语句,并打印出了它的IR代码。完整源码示例请参看:
https://github.com/wuzhanglin/llvm-IR-examples
边栏推荐
猜你喜欢
随机推荐
profiler network乱码
LLVM系列第二十三章:写一个简单的运行时函数调用统计器(Pass)
Eslint规则大全
2. Basic use RecyclerView
ABP,kendo后台接口,新增,查询
AAPT: error: duplicate value for resource ‘attr/xxx‘ with config ‘‘, file failed to compile.
宝塔搭建PHP自适应懒人网址导航源码实测
UIWindow的makeKeyAndVisible不调用rootviewController 的viewDidLoad的问题
What?It's 2020, you still can't adapt the screen?
华为防火墙IPS
自定义UDF函数
YOLOv7 uses cloud GPU to train its own dataset
PostgreSQL 性能谜题
MySQL知识总结 (九) 用户与用户权限管理
Cannot figure out how to save this field into database. You can consider adding a type converter for
NDK入门篇:C语言基础
芝诺悖论的理解
浏览器报错数字代表的大概意思
MapReduce流程
RN开发时遇到的问题



![[VCU] Detailed S19 file (S-record)](/img/00/ccff024d919398230f9b876c60acf6.png)





