I have two RISCV custom compiler passes, pass A and pass B. Pass A adds some custom instructions that I want to detect in pass B. As such, pass B should depend on pass A. In B::getAnalysisUsage
I am doing AU.addRequired<A>()
so pass A should run before pass B (is that right?).
However, the compiler crashes at PMDataManager::~PMDataManager
when I do this. I presume an invalid pointer is freed, but how is this possible? Maybe I need to add something to pass A so that it can be required by pass B?
I can use addRequired
for built-in passes just fine, it’s just the custom pass A that doesn’t work. Pass A does not depend on anything, so I don’t think there is a dependency cycle going on. If you need any more information please let me know.
Crash below (using llvm 16.0.2):
1. <eof> parser at end of file
#0 0x0000000001dfcae7 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/workspaces/intermittent-risc-v/llvm/llvm-16.0.2/install/bin/clang+0x1dfcae7)
#1 0x0000000001dfaa8e llvm::sys::RunSignalHandlers() (/workspaces/intermittent-risc-v/llvm/llvm-16.0.2/install/bin/clang+0x1dfaa8e)
#2 0x0000000001d7fd4f CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#3 0x00007ff9cd4a6520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#4 0x00000000017ff172 llvm::PMDataManager::~PMDataManager() (/workspaces/intermittent-risc-v/llvm/llvm-16.0.2/install/bin/clang+0x17ff172)
clang-16: error: clang frontend command failed with exit code 139 (use -v to see invocation)
Source code for A:
char A::ID = 0;
A::A() : MachineFunctionPass(ID) {}
void A::getAnalysisUsage(AnalysisUsage &AU) const
{
AU.setPreservesCFG();
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
bool A::runOnMachineFunction(MachineFunction &MF) {
// Pass A inserts instructions.
}
FunctionPass *llvm::createAPass() {
return new A();
}
INITIALIZE_PASS(A, DEBUG_TYPE, PASS_NAME, false, false)
Source code for B:
char B::ID = 0;
INITIALIZE_PASS_BEGIN(B, DEBUG_TYPE, PASS_NAME,
false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_DEPENDENCY(A)
INITIALIZE_PASS_END(B, DEBUG_TYPE,
PASS_NAME, false, false)
B::B() : MachineFunctionPass(ID) {}
void B::getAnalysisUsage(AnalysisUsage &AU) const
{
AU.setPreservesCFG();
AU.addRequired<A>();
AU.addPreserved<A>();
AU.addRequired<LiveIntervals>();
MachineFunctionPass::getAnalysisUsage(AU);
}
bool B::runOnMachineFunction(MachineFunction &MF) {
// Pass B detects instructions inserted by pass A.
}
FunctionPass *llvm::createBPass() {
return new B();
}
RISCVTargetMachine.cpp
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
auto *PR = PassRegistry::getPassRegistry();
...
initializeAPass(*PR);
initializeBPass(*PR);
}
void RISCVPassConfig::addPreEmitPass() {
addPass(createAPass());
...
}
void RISCVPassConfig::addPreRegAlloc() {
...
addPass(createBPass());
}