c++ - 如何在 LLVM 过程中破坏然后分解函数?

标签 c++ llvm compiler-optimization

我有一个用于重命名函数的 LLVM pass。给定一些源文件 file.cc,我生成如下 LLVM 位码:

clang -c -o foo.bc -emit-llvm foo.cc

我想通过 foo.bc 运行 LLVM 并重命名所有全局变量、函数和别名,以便我可以将转换后的位码输出到新文件 file_renamed.bc,然后将 file.bcfile_renamed.bc 链接到一个文件 file_linked.bc

我遇到的一个问题是,只需执行 F.setName(F.getName() + "_renamed"),就会在 ma​​ngled 名称后添加后缀由 F.getName() 返回。

另一个问题:我下面有一个函数 demangle(const std::string &Name) 成功地 demangles Name,但是我在重新整理那个名字时遇到了麻烦.

如果有更好的方法来重命名 LLVM 位码中的标识符,或者链接相同位码的两个实例但仍然能够唯一标识每个版本中的函数和全局变量,请随时在您的答案中提出建议。

这是我的 LLVM pass。请注意,我使用的是 LLVM 3.4(它是我正在处理的项目的依赖项。)

标题

#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cxxabi.h>
#include <memory>

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/Mangler.h"

代码

using namespace llvm;

namespace {

  struct FunctionRename : public ModulePass {
    static char ID; // Pass identification

    FunctionRename() : ModulePass(ID) {}

    bool runOnModule(Module &M) override {

      // Rename all globals and references to them
      for (auto it = M.global_begin(); it != M.global_end(); ++it)
      {...}

      // Rename all aliases and references to them
      for (auto it = M.alias_begin(); it != M.alias_end(); ++it)
      {...}

      // Rename all functions and references to them
      for (auto &F : M)
      {
        StringRef Name = F.getName();
        if (F.isDeclaration())
          continue;

        std::string demangled_name = demangle(Name.str());
        std::string new_name = rename(demangled_name);
        F.setName(mangle(new_name, &F));
        F.setLinkage(GlobalValue::WeakAnyLinkage);
      }
      return true;
    }

    std::string demangle(const std::string &Name)
    {
      int status;
      char* demangled_name = NULL;
      char* cstr_name = new char[Name.length() + 1];
      strcpy(cstr_name, Name.c_str());
      demangled_name = __cxxabiv1::__cxa_demangle(cstr_name, NULL, NULL, &status);
      if (status != 0)
      {
        errs() << "Demangling operation failed:\n";
        switch (status)
        {...}
        exit(-1);
      }
      std::string s(demangled_name);
      return s;
    }

    std::string rename(std::string &Name)
    {
      std::string search_str = std::string("(");
      std::string suffix_str = std::string("_renamed");
      size_t i = Name.find_first_of(search_str);
      if (i == std::string::npos)
        Name.append(suffix_str);
      else
        Name.insert(i, suffix_str);
      return Name;
    }

    /* PROBLEMATIC FUNCTION */
    std::string mangle(const std::string &Name, const GlobalValue *GV)
    {
      SmallString<256> MangledName(StringRef(Name));

      Mangler m;
      m.getNameWithPrefix((SmallVectorImpl<char>&) MangledName, GV, false, true);
      Twine T;
      StringRef S = T.toStringRef((SmallVectorImpl<char>&) MangledName);
      return S.str();
    }
  };
}

// Register Pass
char FunctionRename::ID = 0;
static RegisterPass<FunctionRename> X("functionrename", "Function Rename Pass");

最佳答案

你不能简单地从字符串中破坏 C++ 标识符。你需要有适当的 C++ AST。事实上,我根本不明白你为什么需要那个 mangle/demangle 东西。由于您在 LLVM IR 级别工作,因此您根本不应该为语言细节(如原始未损坏的名称)而烦恼。

关于c++ - 如何在 LLVM 过程中破坏然后分解函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45349997/

相关文章:

clang - 使用 LLVM LibFuzzer 时, 'edge' 中的值 'fsantize-coverage=edge' 无效

c++ - 速度和动量 - 我无法走远

LLVM指令变量名称和参数

C++17 复制省略和对象销毁

llvm - 检查函数 A 是否正在调用函数 B 的最快方法

gcc - 达夫的设备还有用吗?

c++ - 循环遍历两个不同长度的 vector 时的优化

c - Malloc 改变单独函数中未初始化变量的行为?

c++ - C++中的数据继承

c++ - 使用 CUDA 进行循环卷积