Я наткнулся на что-то очень своеобразное — я пишу модуль LLVM Pass. Я перебираю все функции модуля, а затем все циклы каждой функции без объявления и сохраняю указатели на циклы в std::vector
, Вот источник:
virtual bool runOnModule(Module& Mod){
std::vector<Loop*> loops;
// first gather all loop info
for(Module::iterator f = Mod.begin(), fend = Mod.end(); f != fend; ++f){
if (!(*f).isDeclaration()){
LoopInfo& LI = getAnalysis<LoopInfo>(*f);
for(LoopInfo::iterator l = LI.begin(), lend = LI.end(); l != lend; ++l){
loops.push_back(*l);
}
}
}
for (auto& l: loops) errs () << *l << " ";
}
Теперь, если я запускаю это, я получаю ошибку времени выполнения — он не может печатать циклы, так или иначе, я делаю разыменование нулевого указателя или sth. Есть идеи?
Вы должны убедиться, что LoopInfo
проход на самом деле работает до вашего прохода. Вот полный пример — станалоне из opt
:
class AnalyzeLoops : public FunctionPass {
public:
AnalyzeLoops()
: FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LoopInfo>();
}
virtual bool runOnFunction(Function &F) {
LoopInfo &LI = getAnalysis<LoopInfo>();
for (LoopInfo::iterator L = LI.begin(), LE = LI.end(); L != LE; ++L) {
(*L)->dump();
}
return false;
}
static char ID;
};
Кроме того, при создании пропусков выполните:
PassManager PM;
PM.add(new LoopInfo());
PM.add(new AnalyzeLoops());
PM.run(*Mod);
Я подозреваю, что сделать opt
на самом деле запустить LoopInfo
до вашего прохода, вы должны пройти -loops
тоже.
Также обратите внимание, что я определяю getAnalysisUsage
— это заставит LLVM жаловаться, если LoopInfo
не бежал до этого прохода, что делает проблему более очевидной.
Обратите внимание, что LoopInfo
конкретно FunctionPass
и в качестве анализа его следует использовать из другого FunctionPass
, LoopInfo
структура данных на самом деле не выживает между различными функциями, и так как она владеет своими данными (те, Loop*
объекты) они также будут уничтожены.
Одна вещь, которую вы могли бы сделать, если вам действительно нужно ModulePass
просто вызвать LoopInfo
вручную, а не как анализ. Когда вы перебираете функции в модуле, для каждой функции создайте новый LoopInfo
возражать и использовать его runOnFunction
метод. Хотя даже в этом случае вы должны убедиться, что LoopInfo
которому принадлежит данный Loop*
выживает, если вы хотите использовать последний.
Прежде всего LoopInfo должен запускаться только один раз перед циклом for.
Во-вторых, LoopInfo :: iterator просто включает в себя циклы верхнего уровня функции. чтобы посетить все циклы, вам также нужно перебрать подциклы каждого цикла. это может быть реализовано либо как рекурсивная функция, либо с помощью WorkList, например:
virtual bool runOnFunction(Function &F) {
LoopInfo *loopinfo;
loopinfo = &getAnalysis<LoopInfo>();
std::vector<Loop*> allLoops;
for (LoopInfo::iterator Li = loopinfo->begin(), Le = loopinfo->end();
Li != Le; Li++) {
Loop *L = *Li;
allLoops.push_back(L);
dfsOnLoops(L, loopinfo, allLoops);
}
}
void dfsOnLoops(Loop *L, LoopInfo *loopinfo, std::vector<Loop*> LoopS) {
std::vector<Loop *> subloops = L->getSubLoops();
if (subloops.size()) {
// recursive on subloops
for (std::vector<Loop *>::iterator Li = subloops.begin();Li != subloops.end(); Li++){
LoopS.push_back(*Li);
dfsOnLoops(*Li, loopinfo, LoopS);
}
}
}
`
Ни один из ответов не помог, но мне удалось решить проблему самостоятельно. По сути, каждый проход llvm может определять метод releaseMemory (), подробнее Вот. В классе LoopInfo реализован этот метод, и, таким образом, информация анализа будет потеряна каждый раз, когда мы выходим из области видимости при вызове getAnalysis. Я просто удалил метод releaseMemory () в Loopinfo.h, и память больше не освобождалась. Обратите внимание, что это вызвало большие изменения в кодовой базе, и даже opt пришлось перестраивать, так что делать это в общем-то, вероятно, плохая идея, и это определенно не будет легко восприниматься как изменение в llvm (я полагаю, не уверен).
Я думаю, что лучший способ решить эту проблему — это явно создавать объекты LoopInfo и сохранять их. Вот код для LLVM 3.5
using LoopInfoType=llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>;
std::vector<llvm::Loop*> loopVec;
std::vector<LoopInfoType*> loopInfoVec;
for(llvm::Module::iterator F = M.begin(); F!= M.end(); F++){
//skip declrations
if(F->isDeclaration()){
continue;
}//TODO that scope problem
llvm::DominatorTree DT = llvm::DominatorTree();
DT.recalculate(*F);
LoopInfoType *loopInfo = new LoopInfoType();
loopInfo->releaseMemory();
loopInfo->Analyze(DT);
loopInfoVec.push_back(loopInfo);
for(llvm::LoopInfo::iterator lit = loopInfo->begin(); lit != loopInfo->end(); lit++){
Loop * L = * lit;
loopVec.push_back(L);
//L->dump();
}
}//for all functions
cin.get();
for(auto loop : loopVec){
std::cout << "loop\n";
loop->dump();
for(llvm::Loop::block_iterator bit = loop->block_begin(); bit != loop->block_end(); bit++){
llvm::BasicBlock * B = * bit;
B->dump();
std::cout << "\n\n";
}
}