Maomi.Core | 一个好用的模块化和自动服务注册框架

认识Pass层级结构

Pass范围从上到下一共分为5个层级:

模块层级:单个.ll或.bc文件

调用图层级:函数调用的关系。

函数层级:单个函数。

基本块层级:单个代码块。例如C语言中{}括起来的最小代码。

指令层级:单个IR指令。

注意:下面代码最好不要用中文,使用起来非常麻烦,控制台,编译,目标文件的编码不同会造成乱码。

项目目录如下

/MyProject

├── CMakeLists.txt # CMake 配置文件

├── build/ #构建目录

│ └── test.c #测试编译代码

└── mypass1.cpp # pass 项目代码

一,测试代码示例

test.c

#include

void secret_function() {

printf("I am secret\n");

}

int main() {

secret_function();

return 0;

}

二,Pass编写

项目描述:通过解析下面代码的IR,将下面代码中的函数名打印出来。

mypass1.cpp

#include "llvm/IR/PassManager.h"

#include "llvm/Passes/PassBuilder.h"

#include "llvm/Passes/PassPlugin.h"

#include "llvm/Support/raw_ostream.h"

using namespace llvm;

// 这个结构体基本是固定模板

namespace {

struct mypass1 : public PassInfoMixin {

//函数回调,每次遇到函数时调用(这里有重载,存在多种入口方式,可以以模块为入口)

PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {

//这里是主要的逻辑代码,我们主要学习的代码在这

//打印出当前函数的名字

errs() << "Found Function: " << F.getName() << "\n";

//只读时返回:PreservedAnalyses::all()

//存在修改时:PreservedAnalyses::none()

return PreservedAnalyses::all();

}

};

}

//下面基本上是固定的模板,每个pass没什么变化,可以直接复制粘贴,或者背熟。

//直接使用需要修改的是下面的<模块名称,版本号,调用参数,和调用的pass结构体>

extern "C" LLVM_ATTRIBUTE_WEAK::llvm::PassPluginLibraryInfo

llvmGetPassPluginInfo() {

return {

LLVM_PLUGIN_API_VERSION,//版本信息

"mypass1",//模块信息,自定义

"v0.1",//版本号,自定义

\](PassBuilder \&PB) { PB.registerPipelineParsingCallback( \[\](StringRef Name, FunctionPassManager \&FPM, ArrayRef) { if (Name == "mypass1") {//调用参数 FPM.addPass(mypass1());//上面pass结构体 return true; } return false; } ); } }; } 三,Pass的构建 构建LLVM Pass需要写CMakeLists.txt构建声明 1. 配置CMake配置文件 CMakeLists.txt 下面的cmake配置可以直接拿去用,我已经标注好需要修改的位置 #cmake 版本,可通过 cmake --version 判断 cmake_minimum_required(VERSION 4.1.1) #----\>修改 cmake版本号 #项目名字 project(mypass1) #----\>修改 项目名称 #导入项目的 LLVM cmake 配置文件路径(如果根据我之前文章安装这里就相同) set(LLVM_DIR "D:/LLVM/llvm-project/build/lib/cmake/llvm")#----\>修改 llvm cmake配置路径 #寻找 LLVM 的包文件 #REQUIRED 找不到 LLVM 则停止构建 #强制使用 LLVM 安装时生成的配置文件进行定位 find_package(LLVM REQUIRED CONFIG) #将 LLVM 的 CMake 模块路径添加到当前 CMake 搜索路径中,以便后续使用 include(AddLLVM)。 list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") #引入 LLVM 提供的专用 CMake 宏 include(AddLLVM) #将 LLVM 的头文件目录(如 llvm/IR/Function.h)加入编译器的搜索路径 include_directories(${LLVM_INCLUDE_DIRS}) #导入 LLVM 编译时使用的宏定义 add_definitions(${LLVM_DEFINITIONS}) #设置 C++ 标准为 C++17。(这里如果不用17编译会报错) set(CMAKE_CXX_STANDARD 17) #强制要求必须支持 C++17,如果编译器不支持则失败。 set(CMAKE_CXX_STANDARD_REQUIRED ON) #创建一个模块化的库(.dll) add_library(mypass1 MODULE mypass1.cpp) #----\>修改 项目名称,文件名 #windows不用会报错:导出符号 #LLVM Pass 需要暴露一些特定的入口点(如 getAnalysisUsage)给 opt 工具调用。 set_target_properties(mypass1 PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) #----\>修改 项目名称 # 指定该 Pass 需要链接的 LLVM 核心组件。 # LLVMCore: 提供 IR、Function、Module 等核心类。 # LLVMSupport: 提供各种辅助工具类(如 errs() 输出)。 target_link_libraries(mypass1 LLVMCore LLVMSupport) #----\>修改 项目名称,文件名 # 为该目标设置特定的编译器选项。 # /utf-8: 告诉 MSVC 编译器使用 UTF-8 编码处理源代码,防止中文注释引起的乱码或编译错误。 target_compile_options(mypass1 PRIVATE /utf-8)#----\>修改 项目名称,文件名 2.编译并构建Pass 打开visual studio的工作台,我这里是x64 Native Tools Command Prompt for VS 2022\` 进到build目录 #构建项目 #其中-DCMAKE_BUILD_TYPE=RelWithDebInfo不选会报错,由于我之前编译的是带符号的relase版本 cmake -G "Ninja" -DCMAKE_BUILD_TYPE=RelWithDebInfo .. #编译 ninja 最后出现下面提示,即为编译成功 \[2/2\] Linking CXX shared module mypass1.dll 四,使用你第一个Pass 进到build目录 #把.c文件编译为.ll #-O1 使用O1优化(这里我尝试-O0不优化,会导致我的pass无法应用) #-Xclang -disable-llvm-passes 不使用默认的pass优化 clang -S -emit-llvm -O1 -Xclang -disable-llvm-passes test.c -S -o test.ll #使用pass opt -load-pass-plugin=mypass1.dll -passes=mypass1 test.ll -S -o test_opt.ll 输出结果 Found Function: sprintf Found Function: vsprintf Found Function: _snprintf Found Function: _vsnprintf Found Function: secret_function Found Function: printf Found Function: main Found Function: _vsprintf_l Found Function: _vsnprintf_l Found Function: __local_stdio_printf_options Found Function: _vfprintf_l玖陡头芈

相关推荐
rV3u0zV4U4 小时前
存储那么贵,何不白嫖飞书云文件空间
分享
kas9P0mBj4 小时前
Jenkins 学习总结
分享
gr180eoY55 小时前
OPUS编解码器在audio DSP上的移植和应用
分享
GCRK1f25f5 小时前
.NET 新特性概览与相关文章索引
分享
VEKlWXO3U5 小时前
再次革新 .NET 的构建和发布方式(三)
分享
kort02i1s5 小时前
Langchain .. 学习 --- LCEL和Runnable
分享
Kn6V2DH5M5 小时前
Sa-Token v.. 发布 ,正式支持 Spring Boot 、新增 Jackson/Snack 插件适配
分享
iy1aLjJ5X5 小时前
多租户下的ERP系统的仓储管理模块分析设计
分享
pHOL7Zfsw5 小时前
打造沉浸式智能AI问答助手:Vue + UniApp 全端实战(支持 Markdown/公式/多模态交互)
分享