当前位置:网站首页>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
边栏推荐
猜你喜欢
随机推荐
数据乱码问题—更改mysql字符编码
数据的表示方法和转换(二进制、八进制、十进制、十六进制)
两个surfaceview的重叠效果类似直播效果中的视频和讲义实践
Handler你真的搞懂了吗?
Redis-01-Nosql概述
执行npm install有错误error
详解RecyclerView系列文章目录
基于ThinkPHP6.0 - 宝塔搭建漫画CMS管理系统源码实测
PostgreSQL 性能谜题
App signature in flutter
C语言初级—水仙花数
mysql
uniCloud 未能获取当前用户信息:30205 | 当前用户为匿名身份
浮点数的运算方法
spark资源调度和任务调度
LLVM系列第二十五章:简单统计一下LLVM源码行数
什么是闭包?闭包的作用?闭包的应用?有什么缺点?
C语言日记 3 常量
YOLOv7 uses cloud GPU to train its own dataset
ConstraintLayout从入门到放弃