本文主要是介绍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
位码文件.完整的示例
在此
这篇关于2312llvm,读写位码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!