03_llvm_IR测试创建变量

发布时间 2023-08-02 20:04:45作者: UFOFCZ

主要分全局变量、函数参数、局部变量(常量)与返回值

测试全局变量

介绍说明、代码、编译与结果如下:

#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"

using namespace llvm;
/*
全局变量(Global Variable)在一个module内全局可见,以@符号开头,
llvm通过Module::getNamedGlobal()创建,还可配置链接类型、内存对齐等属性,
其中,链接类型是指全局变量在链接时指向同一个全局变量还是不同的全局变量,
不同的全局变量是指名称一样,但内存实例不同,互不影响。
| 链接类型                    | 用途                                        |
| -------------------------- | ------------------------------------------- |
| ExternalLinkage            | 模块外部可见                                 |
| AvailableExternallyLinkage | 只在查询而非代码生成的时候外部可见             |
| LinkOnceAnyLinkage         | 函数在链接(或内连inline)的时候仅保存一份实现 |
| LinkOnceODRLinkage         | 同上,但有些链接属性可以用类似的属性替换       |
| WeakAnyLinkage             | 函数在链接的时候仅保存一份实现(弱链接)       |
| WeakODRLinkage             | 同上,但有些链接属性可以用类似的属性替换       |
| AppendingLinkage           | 这是特殊的链接类型,只适用于全局数组           |
| InternalLinkage            | 链接时若发现有重命名的静态函数,则进行重命名   |
| PrivateLinkage             | 只做内部链接,但不会添加到符号表中            |
| ExternalWeakLinkage        | 外部弱链接                                  |
| CommonLinkage              | 由编译器(链接器)自动选择链接类型            |

llvm官方linkage types:https://llvm.org/docs/LangRef.html#linkage

*/
int main() {
  LLVMContext c;
  Module *m = new Module("test module", 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);
  /*函数在 include/llvm/IR/DerivedTypes.h:102:class FunctionType : public Type {
  /// Create a FunctionType taking no parameters.
  static FunctionType *get(Type *Result, bool isVarArg);
  */
  FunctionType *funcTy = FunctionType::get(voidTy, false);
  Function *func = Function::Create(funcTy, GlobalValue::ExternalLinkage, "test_function IR", m);

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

  verifyFunction(*func);
  m->print(outs(), nullptr);
  return 0;
}
// 编译命令:./output/bin/clang++ -w -o test_gvaria_bin `llvm-config --cxxflags --ldflags --system-libs --libs core` ./04_test_gvaria.cpp

// 运行结果
/*
; ModuleID = 'test module'
source_filename = "test module"

@test_global_var = common global i32, align 4

define void @"test_function IR"() {
entry_block:
}
*/

测试返回值

说明、代码、编译与运行见如下代码注释:

#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;
/*
若函数无返回值可如之前样式直接结束,这里测试通过Constant类返回常量
*/
int main() {
  LLVMContext c;
  Module *m = new Module("test module", 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);
  /*函数在 include/llvm/IR/DerivedTypes.h:102:class FunctionType : public Type {
  /// Create a FunctionType taking no parameters.
  static FunctionType *get(Type *Result, bool isVarArg);
  */
  FunctionType *funcTy = FunctionType::get(voidTy, false);
  Function *func = Function::Create(funcTy, GlobalValue::ExternalLinkage, "test_function IR", m);

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

  // 创建返回值
  ConstantInt *one = builder.getInt32(1);
  builder.CreateRet(one);

  verifyFunction(*func);
  m->print(outs(), nullptr);
  return 0;
}
// 编译命令:./output/bin/clang++ -w -o test_return_bin `llvm-config --cxxflags --ldflags --system-libs --libs core` ./05_test_return.cpp
// 运行结果
/*
; ModuleID = 'test module'
source_filename = "test module"

@test_global_var = common global i32, align 4

define void @"test_function IR"() {
entry_block:
  ret i32 1
}
*/

测试函数参数

说明、代码、编译与运行见如下代码注释:

#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;
/*
若函数无返回值可如之前样式直接结束,这里测试通过Constant类返回常量
*/
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);

  // 创建返回值
  ConstantInt *one = builder.getInt32(1);
  builder.CreateRet(one);

  verifyFunction(*func);
  m->print(outs(), nullptr);
  return 0;
}
// 编译命令:../output/bin/clang++ -w -o test_func_args_bin `llvm-config --cxxflags --ldflags --system-libs --libs core` ./06_test_func_args.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:
  ret i32 1
}

低版本运行结果
; ModuleID = 'test module'
source_filename = "test module"

@test_global_var = common global i32, align 4

define i32 @"test_function IR"(i32, i32) {
entry_block:
  ret i32 1
}
*/