04_llvm_IR测试生成运算指令

发布时间 2023-08-02 20:14:56作者: UFOFCZ

四则运算指令

介绍如下:

#include <vector>
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/GlobalVariable.h"
// #include "llvm/Support/Alignment.h"
#include "llvm/IR/Constants.h"

using namespace llvm;
using namespace std;
/*
代码块(BasicBlock)由一系列指令(Instruction)组成,完成算术与逻辑等运算操作,
如一个加法算术操作,操作符是"+",操作数可来自参数、变量、常量等,统一都由IRBuilder类来创建。
*/
int main() {
  LLVMContext c;
  Module *m = new Module("test module", c);
  IRBuilder<> builder(c);

  // 创建一个全局变量
  m->getOrInsertGlobal("test_global_var", Type::getInt32Ty(c));
  GlobalVariable *gv = m->getNamedGlobal("test_global_var");
  gv->setLinkage(GlobalValue::CommonLinkage); // 链接类型
  /*llvm 13写法
  函数定义变了 ../output/include/llvm/IR/GlobalObject.h函数 void setAlignment(MaybeAlign Align);
  其中 include/llvm/Support/Alignment.h:109:struct MaybeAlign : public llvm::Optional<Align> {
  */
  // gv->setAlignment(MaybeAlign(4));/*llvm 13写法*/

  /*以下是基于低版本llvm 6.0的写法*/
  // llvm-6.0/include/llvm/IR/GlobalObject.h:64函数 void setAlignment(unsigned Align),参数是unsigned int即可
  gv->setAlignment(4);

  // Type *voidTy = Type::getVoidTy(c);// 原来创建void 参数类型
  vector<Type *> paramTys(2, builder.getInt32Ty());
  /*get函数在 include/llvm/IR/DerivedTypes.h:102:class FunctionType : public Type {
  /// This static method is the primary way of constructing a FunctionType.
  static FunctionType *get(Type *Result, ArrayRef<Type*> Params, bool isVarArg);
  */
  FunctionType *funcTy = FunctionType::get(builder.getInt32Ty(), paramTys, false);
  Function *func = Function::Create(funcTy, GlobalValue::ExternalLinkage, "test_function IR", m);
  // 低版本无getArg()函数
  func->getArg(0)->setName("a");
  func->getArg(1)->setName("b");

  // 创建一个block
  BasicBlock *b = BasicBlock::Create(c, "entry_block", func);
  builder.SetInsertPoint(b);

  // arg0 + arg1 * 2,return ret
  Value *arg0 = func->getArg(0);
  Value *arg1 = func->getArg(1);
  ConstantInt *two = builder.getInt32(2);
  Value *tmp = builder.CreateMul(arg1, two, "mul_ans");
  Value *ret = builder.CreateAdd(arg0, tmp, "add_ans");

  // 创建返回值
  builder.CreateRet(ret);

  verifyFunction(*func);
  m->print(outs(), nullptr);
  return 0;
}

// 编译命令 ../clang-16/bin/clang++ -w -o test_return_bin `llvm-config --cxxflags --ldflags --system-libs --libs core` ./07_test_statement.cpp
// 运行结果
/*
; ModuleID = 'test module'
source_filename = "test module"

@test_global_var = common global i32, align 4

define i32 @"test_function IR"(i32 %a, i32 %b) {
entry_block:
  %mul_ans = mul i32 %b, 2
  %add_ans = add i32 %a, %mul_ans
  ret i32 %add_ans
}

*/