Для разработки собственного Pass я хочу написать модульные тесты — у меня есть много «чистых» вспомогательных методов, поэтому они кажутся идеальными кандидатами для модульного тестирования. Но некоторые из них требуют в качестве аргумента экземпляр llvm :: LoopInfo.
В моем (Function-) Pass я просто использую
void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.addRequired<llvm::LoopInfoWrapperPass>();
}
...
llvm::LoopInfo &loopInfo = getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
чтобы получить этот информационный объект.
В моем модульном тесте я сейчас разбираю llvm::Function
void foo()
(что я хочу запустить свой анализ) с диска, как это:
llvm::SMDiagnostic Err;
llvm::LLVMContext Context;
std::unique_ptr<llvm::Module> module(parseIRFile(my_bc_filename, Err, Context));
llvm::Function* foo = module.operator*().getFunction("foo");
чтобы завершить тест, мне нужно заполнить следующую заглушку:
llvm::LoopInfo& = /*run LoopInfoWrapperPass on foo and return LoopInfo element */;
Мои первые попытки были основаны на использовании PassManager<Function>
(в заголовке «llvm / IR / PassManager.h»), AnalysisManager<Function>
и класс LoopInfoWrapperPass
, но я не смог найти ни одного примера использования в Интернете для LLVM 4.0 — и более старые примеры, казалось, использовали предыдущую версию PassManager, и я не видел, как использовать LegacyPassManager
, Я пытался заглянуть в источники PassManager
но не смог понять смысл typedefs и аргументов шаблона (и они усиливают мою иррациональную неприязнь к C ++ как к языку).
Как мне заполнить эту заглушку? Как мне назвать этот проход анализа (и получить LoopInfo) в моем простом коде C ++?
PS: мне нужно использовать больше проходов, кроме LoopInfoWrapperPass, но я предполагаю, что путь должен быть перенесен на любой проход анализа.
PPS: я использую googletest в качестве фреймворка для юнит-тестирования, с конфигурацией сборки CMake, которая делает юнит-тестирование своей собственной целью, и я строю свой Pass-of-of-tree против двоичных библиотек LLVM 4.0.1, если таковые имеются это как-то актуально.
Я не уверен, как вы структурировали свои юнит-тесты, но хорошая идея — просмотреть дерево исходных текстов LLVM.
Один пример можно найти в CFGTest.cpp
Вот.
Вам нужно создать PassManager
и сам трубопровод. Из моего небольшого опыта в этом, он хорошо работает для небольших тестов, но если вам нужно что-то большее или передавать / выводить данные, это действительно ограничивает, так как LoopInfo
данные имеют только значение внутри конвейера (иначе runOn()
методы и друзья).
В противном случае вы можете выбрать (не каламбур) более простой, ИМХО, метод для создания набора требуемого анализа самостоятельно (только в случае доминант в случае LoopInfo
) без использования инфраструктуры менеджера пропусков. Пример этого можно увидеть Вот.
Надеюсь это поможет.
Других решений пока нет …