LLVM хранит Loop * в std :: vector

Я наткнулся на что-то очень своеобразное — я пишу модуль 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. Есть идеи?

3

Решение

Вы должны убедиться, что 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* выживает, если вы хотите использовать последний.

1

Другие решения

Прежде всего 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);
}
}
}
`
1

Ни один из ответов не помог, но мне удалось решить проблему самостоятельно. По сути, каждый проход llvm может определять метод releaseMemory (), подробнее Вот. В классе LoopInfo реализован этот метод, и, таким образом, информация анализа будет потеряна каждый раз, когда мы выходим из области видимости при вызове getAnalysis. Я просто удалил метод releaseMemory () в Loopinfo.h, и память больше не освобождалась. Обратите внимание, что это вызвало большие изменения в кодовой базе, и даже opt пришлось перестраивать, так что делать это в общем-то, вероятно, плохая идея, и это определенно не будет легко восприниматься как изменение в llvm (я полагаю, не уверен).

1

Я думаю, что лучший способ решить эту проблему — это явно создавать объекты 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";
}
}
0
По вопросам рекламы [email protected]