如何在 LLVM 的 MachineFunctionPass 中正确使用 BuildMI() 插入机器指令?
How to insert machine instruction using BuildMI() correctly inside a MachineFunctionPass in LLVM?
我在这个博客之后写了我的 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
我在这个博客之后写了我的 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