2312llvm,读写位码

如何读写LLVM位码

首先,看看一些高级LLVM术语:
1,LLVM对用户代码的主要抽象模块.它是一个包含用户编写所有函数,全局变量和指令的类.
2,Bitcode文件是LLVM模块的序化,以便以后可在不同程序中重建它.
3,LLVM使用MemoryBuffer对象来处理文件,stdin数组等数据.

示例中,使用LLVMCAPI.这是LLVM核心C++头文件之上的更稳定的抽象.如果有想同多个版本的LLVM工作的代码,CAPI非常有用,它比LLVMC++头文件稳定得多.
顺便,我在工作中广泛使用LLVM,几乎每周都会有一些LLVMC++头文件更改会破坏代码.而CAPI没有破坏代码.
首先,假设你已拉取了LLVM,构建并安装了它.一些简单的步骤可完成:

git clone https://git.llvm.org/git/llvm.git <llvm dir>
cd <llvm dir>
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=install ..
cmake --build . --target install

完成上述操作后,你就在<llvmdir>/build/install中安装了一个LLVM!
因此,对小可执行文件,使用了CMake.CMake迄今为止是与LLVM整合的最简单方法,因为它也是LLVM使用的构建系统.

project(llvm_bc_parsing_example)
cmake_minimum_required(VERSION 3.4.3)
//允许用户指定`LLVM`在系统上安装位置的选项
set(LLVM_INSTALL_DIR "" CACHE STRING "An LLVM install directory.")
if("${LLVM_INSTALL_DIR}" STREQUAL "")
message(FATAL_ERROR "LLVM_INSTALL_DIR not set! Set it to the location of an LLVM install.")
endif()
//修复路径以仅使用`Linux`约定
string(REPLACE "\\" "/" LLVM_INSTALL_DIR ${
   LLVM_INSTALL_DIR})
//告诉`CMake`,`LLVM`的模块在哪
list(APPEND CMAKE_MODULE_PATH ${
   LLVM_INSTALL_DIR}/lib/cmake/llvm)
//包括`LLVM`
include(LLVMConfig)
add_executable(llvm_bc_parsing_example main.c)
target_include_directories(llvm_bc_parsing_example PUBLIC ${
   LLVM_INCLUDE_DIRS})
target_link_libraries(llvm_bc_parsing_example PUBLIC LLVMBitReader LLVMBitWriter)

现在已安装好CMake,可用现有的LLVM安装目录,现在可处理实际C代码了!
因此,要使用LLVMCAPI,基本上总是需要个头文件:

#include <llvm-c/Core.h>

可执行文件需要两个额外头文件,即位码读取器和写入器:

#include <llvm-c/BitReader.h>
#include <llvm-c/BitWriter.h>

现在创建main函数.在此假设总是正好接受2个命令行参数,第一个是输入文件,第二个是输出文件.LLVM有一个系统,如果提供了叫"-"的文件,即从stdin读写stdout,所以我决定也支持它:

if (3 != argc) {
   
    fprintf(stderr, "Invalid command line!\n");
    return 1;
}
const char *const inputFilename = argv[1];
const char *const outputFilename = argv[2];

因此,首先解析输入文件.从stdin或文件名创建一个LLVM内存缓冲对象:

LLVMMemoryBufferRef memoryBuffer;
//检查是否要从`stdin`读取输入文件
if (('-' == inputFilename[0]) && ('\0' == inputFilename[1])) {
   
    char *message;
    if (0 != LLVMCreateMemoryBufferWithSTDIN(&memoryBuffer, &message)) {
   
        fprintf(stderr, "%s\n", message);
        free(message);
        return 1;
    }
} else {
   
    char *message;
    if (0 != LLVMCreateMemoryBufferWithContentsOfFile( inputFilename, &memoryBuffer, &message)) {
   
        fprintf(stderr, "%s\n", message);
        free(message);
        return 1;
    }
}

因此,此代码后,可用memoryBuffer读取位码文件LLVM模块中.因此,创建模块!

//现在使用内存缓冲创建的模块
LLVMModuleRef module;
if (0 != LLVMParseBitcode2(memoryBuffer, &module)) {
   
    fprintf(stderr, "Invalid bitcode detected!\n");
    LLVMDisposeMemoryBuffer(memoryBuffer);
    return 1;
}
//现在使用内存缓冲完成,因此释放掉它
LLVMDisposeMemoryBuffer(memoryBuffer);

一旦有了模块,就不需要内存缓冲,因此可立即释放内存.就这样!取LLVM位码文件,并反序化为LLVM模块.
因此,假设已完成了LLVM模块的所有操作,并想再次写回位码文件.
读取方法一样,查找特殊文件名"-"并相应处理:

//检查是否要把输出文件写入`stdout`
if (('-' == outputFilename[0]) && ('\0' == outputFilename[1])) {
   
    if (0 != LLVMWriteBitcodeToFD(module, STDOUT_FILENO, 0, 0)) {
   
        fprintf(stderr, "Failed to write bitcode to stdout!\n");
        LLVMDisposeModule(module);
        return 1;
    }
} else {
   
    if (0 != LLVMWriteBitcodeToFile(module, outputFilename)) {
   
        fprintf(stderr, "Failed to write bitcode to file!\n");
        LLVMDisposeModule(module);
        return 1;
    }
}

最后,清理垃圾,所以删除模块:

LLVMDisposeModule(module);

就这样!现在,可解析并写LLVM位码文件.完整的示例在此

相关推荐

  1. 2312llvm,

    2023-12-17 17:18:03       43 阅读
  2. 2312llvm,02前端

    2023-12-17 17:18:03       38 阅读
  3. 2312d,原始

    2023-12-17 17:18:03       41 阅读
  4. 2312llvm,01基本介绍

    2023-12-17 17:18:03       38 阅读
  5. 2312llvm,04后端上

    2023-12-17 17:18:03       39 阅读
  6. 2312llvm,05后端下

    2023-12-17 17:18:03       39 阅读
  7. 2312llvm,编译X86的clang与llvm

    2023-12-17 17:18:03       42 阅读
  8. Qtini文件,出现中文乱问题

    2023-12-17 17:18:03       39 阅读
  9. 分享-golang的BMP文件

    2023-12-17 17:18:03       36 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-17 17:18:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-17 17:18:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-17 17:18:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-17 17:18:03       18 阅读

热门阅读

  1. Using Implicit Rules

    2023-12-17 17:18:03       34 阅读
  2. WTN6040F-8S语音芯片:投篮游戏机新时代引领者

    2023-12-17 17:18:03       41 阅读
  3. macos苹果电脑开启tftp server上传fortigate60e固件成功

    2023-12-17 17:18:03       32 阅读
  4. 使用Yellowbrick绘制获取最佳聚类K值的示例

    2023-12-17 17:18:03       39 阅读
  5. 【vue filters 过滤器】vue页面 全局使用

    2023-12-17 17:18:03       38 阅读
  6. RK3568-PWM

    2023-12-17 17:18:03       37 阅读
  7. Optee在嵌入式系统中是否支持多线程机制

    2023-12-17 17:18:03       41 阅读
  8. Word Excel模版引擎

    2023-12-17 17:18:03       51 阅读
  9. 设计模式——原型模式代码示例

    2023-12-17 17:18:03       36 阅读
  10. 通过接口引用对象

    2023-12-17 17:18:03       35 阅读