c++ - 如何使用 BuildMI() 在 LLVM 的 MachineFunctionPass 中正确插入机器指令?

标签 c++ linux llvm riscv

我在这个博客之后写了我的 MachineFunctionPass:https://www.kharghoshal.xyz/blog/writing-machinefunctionpass

然后将其移植到 RISCV 目标。效果很好。 我还为每条指令添加迭代以检查 Call 指令。它仍然有效,直到我尝试编写指令。

这是我的 MachineFunctionPass:

#include "RISCV.h"
#include "RISCVInstrInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"

using namespace llvm;

#define RISCV_MACHINEINSTR_PRINTER_PASS_NAME                                   \
  "Dummy RISCV machineinstr printer pass"

namespace {

class RISCVMachineInstrPrinter : public MachineFunctionPass {
public:
  static char ID;

  RISCVMachineInstrPrinter() : MachineFunctionPass(ID) {
    initializeRISCVMachineInstrPrinterPass(*PassRegistry::getPassRegistry());
  }

  bool runOnMachineFunction(MachineFunction &MF) override;

  StringRef getPassName() const override {
    return RISCV_MACHINEINSTR_PRINTER_PASS_NAME;
  }
};

char RISCVMachineInstrPrinter::ID = 0;

bool RISCVMachineInstrPrinter::runOnMachineFunction(MachineFunction &MF) {

  for (auto &MBB : MF) {
    
    for (auto &MI : MBB) {

      if (MI.isCall()) {
        outs() << "Found Call\n";

        outs() << MI.getOpcode() << "\n";

        RISCVInstrInfo *XII; // target instruction info
        DebugLoc DL;
        MachineBasicBlock::iterator MBBI = BuildMI(MBB, MI ,DL, XII->get(RISCV::SW), RISCV::X1)
            .addReg(RISCV::X31)
            .addImm(0);
        return true;
      }
    }
  }

  return false;
}

} // end of anonymous namespace

INITIALIZE_PASS(RISCVMachineInstrPrinter, "RISCV-machineinstr-printer",
                RISCV_MACHINEINSTR_PRINTER_PASS_NAME,
                true, // is CFG only?
                true  // is analysis?
)

namespace llvm {

FunctionPass *createRISCVMachineInstrPrinterPass() {
  return new RISCVMachineInstrPrinter();
}

} // namespace llvm

当我尝试使用编译代码时

clang hi.c -o hi -march=rv32g --target=riscv32

输出是一条我不理解的错误消息:

Found Call
202
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.  Program arguments: /home/ibndias/riscv32/bin/clang-12 -cc1 -triple riscv32-- -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hi.c -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -nostdsysteminc -target-feature +m -target-feature +a -target-feature +f -target-feature +d -target-feature +relax -target-feature -save-restore -target-abi ilp32d -msmall-data-limit 8 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /home/ibndias/riscv32/lib/clang/12.0.0 -isysroot /home/ibndias/riscv32/riscv32-unknown-elf -internal-isystem /home/ibndias/riscv32/riscv32-unknown-elf/include -fdebug-compilation-dir /home/ibndias/Documents/Projects -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fcolor-diagnostics -faddrsig -o /tmp/hi-047c57.o -x c hi.c 
1.  <eof> parser at end of file
2.  Code generation
3.  Running pass 'Function Pass Manager' on module 'hi.c'.
4.  Running pass 'Dummy RISCV machineinstr printer pass' on function '@main'
 #0 0x000055c4c194489e llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/home/ibndias/riscv32/bin/clang-12+0x185589e)
 #1 0x000055c4c1942734 llvm::sys::RunSignalHandlers() (/home/ibndias/riscv32/bin/clang-12+0x1853734)
 #2 0x000055c4c1942878 SignalHandler(int) (/home/ibndias/riscv32/bin/clang-12+0x1853878)
 #3 0x00007f3f492a23c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0)
 #4 0x000055c4c0b72ae2 (anonymous namespace)::RISCVMachineInstrPrinter::runOnMachineFunction(llvm::MachineFunction&) (/home/ibndias/riscv32/bin/clang-12+0xa83ae2)
 #5 0x000055c4c0e8901c llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/home/ibndias/riscv32/bin/clang-12+0xd9a01c)
 #6 0x000055c4c12ca770 llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/ibndias/riscv32/bin/clang-12+0x11db770)
 #7 0x000055c4c12cbd79 llvm::FPPassManager::runOnModule(llvm::Module&) (/home/ibndias/riscv32/bin/clang-12+0x11dcd79)
 #8 0x000055c4c12c9980 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/ibndias/riscv32/bin/clang-12+0x11da980)
 #9 0x000055c4c1be7b26 (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (/home/ibndias/riscv32/bin/clang-12+0x1af8b26)
#10 0x000055c4c1be94ce clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::DataLayout const&, llvm::Module*, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (/home/ibndias/riscv32/bin/clang-12+0x1afa4ce)
#11 0x000055c4c2863fd1 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/ibndias/riscv32/bin/clang-12+0x2774fd1)
#12 0x000055c4c360db39 clang::ParseAST(clang::Sema&, bool, bool) (/home/ibndias/riscv32/bin/clang-12+0x351eb39)
#13 0x000055c4c21fb239 clang::FrontendAction::Execute() (/home/ibndias/riscv32/bin/clang-12+0x210c239)
#14 0x000055c4c21af54b clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/ibndias/riscv32/bin/clang-12+0x20c054b)
#15 0x000055c4c22cd800 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/ibndias/riscv32/bin/clang-12+0x21de800)
#16 0x000055c4c0b1ca57 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/ibndias/riscv32/bin/clang-12+0xa2da57)
#17 0x000055c4c0b1a60b ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) (/home/ibndias/riscv32/bin/clang-12+0xa2b60b)
#18 0x000055c4c0ab1cde main (/home/ibndias/riscv32/bin/clang-12+0x9c2cde)
#19 0x00007f3f48d530b3 __libc_start_main /build/glibc-YYA7BZ/glibc-2.31/csu/../csu/libc-start.c:342:3
#20 0x000055c4c0b1a19e _start (/home/ibndias/riscv32/bin/clang-12+0xa2b19e)
clang-12: error: unable to execute command: Segmentation fault (core dumped)
clang-12: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 12.0.0 (https://github.com/llvm/llvm-project.git 99ad956fdaee5398fdcf46fa49cb433cf52dc461)
Target: riscv32--
Thread model: posix
InstalledDir: /home/ibndias/riscv32/bin
clang-12: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-12: note: diagnostic msg: /tmp/hi-5c6fca.c
clang-12: note: diagnostic msg: /tmp/hi-5c6fca.sh
clang-12: note: diagnostic msg: 

********************

这是我的代码:

#include<stdio.h>

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

int main()
{
        int a, b, c;

        a = 0x10;
        b = 0x20;

        c = foo(a,b);
        return c;
}

这是插入指令的正确方法吗?

  for (auto &MBB : MF) {

    for (auto &MI : MBB) {

      if (MI.isCall()) {
        outs() << "Found Call\n";

        outs() << MI.getOpcode() << "\n";

        RISCVInstrInfo *XII; // target instruction info
        DebugLoc DL;
        MachineBasicBlock::iterator MBBI = BuildMI(MBB, MI ,DL, XII->get(RISCV::SW), RISCV::X1)
            .addReg(RISCV::X31)
            .addImm(0);
        return true;
      }
    }
  }

最佳答案

您正在使用 MBBI 在 buildMI 尚未初始化时为其提供位置。
我的理解是,您想在调用之前添加一条指令,因此您应该使用 MI 而不是 MBBI 作为第二个参数。
目标指令信息(XII)也未初始化。
您可以在这里查看:
https://llvm.org/docs/CodeGenerator.html#id23

关于c++ - 如何使用 BuildMI() 在 LLVM 的 MachineFunctionPass 中正确插入机器指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63629692/

相关文章:

c++ - 成员函数的 const 修饰符如何影响重载决议?

gcc - 为什么gcc "start"函数(在main之前)中有无意义的asm代码?

floating-point - LLVM为什么不通过优化浮点指令?

x86 - 如何使用 LLVM 在某些指令后插入调用?

c++ - C/C++多进程访问同一个变量的方法

linux - perf stat中循环注释的含义是什么

c++ - 有条件地为变量分配一个类

c++ - C++中动态数组是如何实现的?

C++ multimap 操作

python - 直到文件末尾才能让 Python 读取