06 llvm IR测试创建struct和Array

发布时间 2023-08-09 19:58:08作者: 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;

/*
llvm提供两种struct,identified struct和literal struct,对应接口分别为llvm::StructType::Create()和llvm::StructType::get()
identified struct:
对应使用struct关键定义的类型
*/
int main() {
  LLVMContext c;
  Module *m = new Module("test module", c);
  IRBuilder<> builder(c);

  StructType* structAddr = StructType::create(c, "TestStruct");
  structAddr->setBody({builder.getInt32Ty(), builder.getInt32Ty(), builder.getInt32Ty(), builder.getInt32Ty()});
  std::vector<Constant *> structInit = {builder.getInt32(1), builder.getInt32(8), builder.getInt32(8), builder.getInt32(10)};
  m->getOrInsertGlobal("test_struct_var", structAddr);
  GlobalVariable *gv = m->getNamedGlobal("test_struct_var");
  // gv->setLinkage(GlobalValue::PrivateLinkage); // 链接类型
  // If true then there is a definition within the same linkage unit and that definition cannot be runtime preempted
  gv->setDSOLocal(true);
  gv->setInitializer(ConstantStruct::get(structAddr, structInit));
  gv->setAlignment(MaybeAlign(4));
  gv->setSection("test_section"); // 指定在elf目标文件的test_section中

  /*
  IRBuilder.h :
    /// Fetch the type representing a pointer to an integer value.
    IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
  */
  std::vector<Constant *> ptrArrInit = {gv, gv};
  // DataLayout dl(m);
  // ArrayType* AddressTableType = ArrayType::get(builder.getIntPtrTy(dl), 2);
  Type *voidType = Type::getVoidTy(c);
  PointerType *voidPointerType = PointerType::get(voidType, 0); // 创建void *
  PointerType *ptr_type = PointerType::get(gv->getType(), 0); // 获取指向该变量的指针type
  ArrayType* AddressTableType = ArrayType::get(voidPointerType, 2);//Type::getInt8PtrTy(c), 2);
  Constant* AddressTableInit = ConstantArray::get(AddressTableType, ptrArrInit);
  Constant* AddressTable = m->getOrInsertGlobal("test_struct_init", AddressTableType);
  dyn_cast<GlobalVariable>(AddressTable)->setInitializer(AddressTableInit);


  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", m);
  // 低版本无getArg()函数
  Value *arg0 = func->getArg(0);
  arg0->setName("a");
  func->getArg(1)->setName("c");

  // 1 给函数创建主block
  BasicBlock *bEntry = BasicBlock::Create(c, "entry_block", func);



  ConstantInt *vConst5 = builder.getInt32(5);
  builder.CreateRet(vConst5);

  verifyFunction(*func);

  FunctionType *pseudo_func_type = FunctionType::get(
      builder.getInt64Ty(),
      {builder.getInt64Ty(), builder.getInt64Ty()},
      false);
  Function::Create(
      pseudo_func_type,
      GlobalValue::ExternalLinkage,
      "llvm.bpf.pseudo",
      m);

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

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

%TestStruct = type { i32, i32, i32, i32 }

@test_struct_var = dso_local global %TestStruct { i32 1, i32 8, i32 8, i32 10 }, section "test_section", align 4
@test_struct_init = global [2 x void*] [void* @test_struct_var, void* @test_struct_var]

define i32 @test_function(i32 %a, i32 %c) {
entry_block:
}

; Function Attrs: nounwind
declare i64 @llvm.bpf.pseudo(i64, i64) #0

attributes #0 = { nounwind }


*/