LLVM 13.1 new Pass插件形式 [for win]

LLVM 13.1 new Pass插件形式 [for win]

4大关键点:

  1. LLVM 13.1版本(当前最新版)
  2. windows平台上的pass demo
  3. new pass形式(非legacy)
  4. clang 动态插件形式(pass插件与llvm本体编译分离)

背景:
当前外部资料均为老版本LLVM + legacy模式的pass,和当前llvm版本脱节,新模式下没找到资料就自己研究了下,具体新旧LLVM版本对pass的编写有啥影响,具体原因是啥,怎么做能兼容旧版本见我的上一篇文章(设计新旧异同分析的原理与思路)

操作步骤
(后续所有步骤若目录不一致需自行改动目录结构,不赘述)

  1. 建立:D:\Code\llvm-project文件夹,放入名为clang的源码文件夹,和名为llvm的源码文件夹,再在此目录新建一个MyCustom文件夹用以存放我们的动态插件工程(版本LLVM 13.1)
  2. 按照我的上一篇文章介绍的步骤1~3构建好x64release版本的clang&llvm(新旧pass对llvm和clang的构建并无区别),编译较慢且CPU占用高请找空闲时间完成
  3. 切换至D:\Code\llvm-project\llvm\build\Release\bin目录键入.\clang.exe --version命令确保输出如下形式
clang version 13.0.1
Target: x86_64-pc-windows-msvc
...
  1. 新建D:\Code\llvm-project\MyCustom\src文件夹,在其中新建文件MyPass.cpp并写入
#include <llvm/IR/PassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/Pass.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Passes/PassPlugin.h>


using namespace llvm;

// test for my custom pass
class MyCustomPass : public PassInfoMixin<MyCustomPass> {
public:
    PreservedAnalyses run(Module& M, ModuleAnalysisManager& AM)
    {
        for (auto& f : M) {
            errs() << "MyCustomPass: " << f.getName() << "\n";
        }
        return PreservedAnalyses::all();
    }
};

// 在clang里根据配置创建自定义pass,called by PassManagerBuilder::populateModulePassManager
extern "C"  __declspec(dllexport) void __stdcall clangAddCustomPass(ModulePassManager & MPM)
{
    MPM.addPass(MyCustomPass());
}
  1. 在D:\Code\llvm-project\MyCustom目录下新建文件CMakeLists.txt,并写入
cmake_minimum_required(VERSION 3.4)

project(custompass)

# 设置编译模式
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")        #/MT
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")                #/MTd

# 添加源码目录
aux_source_directory(./src  src_1)
set(srcs ${src_1})

# 生成动态链接库,那么在Windows下就是dll,最终会生成custompass.dll
add_library(custompass SHARED ${srcs})

set(LLVM_PROJECT_DIR "" CACHE STRING
	"You must input the correct llvm-project dir")
if( LLVM_PROJECT_DIR STREQUAL "" )
	MESSAGE(FATAL_ERROR "LLVM_PROJECT_DIR is empty")
else()
	MESSAGE("LLVM_PROJECT_DIR=${LLVM_PROJECT_DIR}")
endif()

# 添加头文件,需要编译后的以及源码头文件
include_directories("${LLVM_PROJECT_DIR}/llvm/build/include")
include_directories("${LLVM_PROJECT_DIR}/llvm/include")

# 添加编译后的lib
set(mylibdir "${LLVM_PROJECT_DIR}/llvm/build/Release/lib")
set(VTKLIBS LLVMCore LLVMSupport LLVMBinaryFormat LLVMRemarks LLVMBitstreamReader)
foreach(libname ${VTKLIBS})
        SET(FOUND_LIB "FOUND_LIB-NOTFOUND")
        find_library(FOUND_LIB NAMES ${libname} HINTS ${mylibdir} NO_DEFAULT_PATH)
                IF (FOUND_LIB)
                        message("found lib: ${FOUND_LIB}")
                        LIST(APPEND mylibs ${FOUND_LIB})
                ELSE()
                        MESSAGE("not lib found: ${libname}")
                ENDIF ()
endforeach(libname)
#message(${mylibs})

#message(${CPPUNIT_LIBRARY})
target_link_libraries(custompass PUBLIC ${mylibs})
  1. cmake选中D:\Code\llvm-project\MyCustom工程,配置LLVM_PROJECT_DIR字段为D:\Code\llvm-project,并确保成功生成sln工程文件
  2. 编译工程文件得到custompass.dll输出文件,将其拷贝到D:\Code\llvm-project\llvm\build\Release\bin目录下
  3. 打开llvm工程,依次打开Object Libraries\obj.clangCodeGen\Source Files\BackendUtil.cpp文件
  4. 在EmitAssemblyHelper::EmitAssemblyWithNewPassManager函数内的if (!CodeGenOpts.DisableLLVMPasses)判断体末尾加上下方代码已使其固定加载custompass.dll的clangAddCustomPass导出函数(记得引入#include "windows.h")
#if _WINDOWS
    using myPassType = void(__stdcall *)(ModulePassManager & MPM);
    auto customHandle = ::LoadLibraryA("custompass.dll");
    if (!customHandle) {
      errs() << "custompass.dll not found\n";
    } else {
      auto pfn =
          (myPassType)::GetProcAddress(customHandle, "clangAddCustomPass");
      if (pfn != NULL) {
        pfn(MPM);
      } else {
        errs() << "clangAddCustomPass not found\n";
      }
    }
#endif // _WINDOWS
  1. 增量编译LLVM工程(修改不多编译较快)

测试
12. D:\Code\llvm-project\llvm\build\Release\bin下新建文件test.cpp,并写入

#include <stdio.h>

int add(int a,int b)
{
	return a+b;
}

int min(int a,int b)
{
	return a-b;
}

void show()
{
	printf("show\n");
}

int main(int argc, char* argv[]){
	add(1,2);
	min(5,3);
	show();
	return 0;	
}
  1. 输入命令.\clang.exe test.cpp -o test.exe成功得到输出,后续仅需修改MyCustom工程并将编译后的插件放入clang目录即可,同时该工程支持加入多个PASS,先将pass流程泡通搞清楚PASS流程逻辑&llvm的语法组件…一些代码混淆,数据加密等功能后续发文
MyCustomPass: ?add@@YAHHH@Z
MyCustomPass: ?min@@YAHHH@Z
MyCustomPass: ?show@@YAXXZ
MyCustomPass: printf
MyCustomPass: main
MyCustomPass: llvm.va_start
MyCustomPass: _vfprintf_l
MyCustomPass: __acrt_iob_func
MyCustomPass: llvm.va_end
MyCustomPass: __stdio_common_vfprintf
MyCustomPass: __local_stdio_printf_options
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值