среда, 23 мая 2018 г.

Собираем свой собственный пасс компилятора под Windows как часть проекта LLVM

К сожалению под Windows отсутствует механизм динамического связывания, хотя и есть DLL, но LLVM не может зарегистрировать пользовательский пасс, оформленный как DLL, поэтому свои пассы придется собирать как часть проекта LLVM. В данной заметке я приведу небольшую инструкцию, которой очень не хватает на официальном сайте проекта.

1. Нужно скопировать каталог с исходными кодами своих пассов (буду называть его LLVMExperimentPasses) в lib/Transforms (здесь и далее пути даны относительно корня каталога с исходными кодами LLVM, предполагается, что вы уже его зачекаутили, например с GitHub-зеркала).

2. Добавить команду add_subdirectory(LLVMExperimentPasses) в файл lib/Transforms/CMakeLists.txt.

3. Для каждого созданного пасса добавить функцию с сигнатурой initialize${ИМЯ ПАССА}Pass(PassRegistry &); в заголовочный файл include/llvm/InitializePasses.h. Также следует добавить туда функцию с сигнатурой void initializeLLVMExperimentPasses(PassRegistry &);. Для пасса FunctionArgumentCount следует добавить в заголовочный файл такие строки:

// my experiment passes
void initializeLLVMExperimentPasses(PassRegistry &);
void initializeFunctionArgumentCountPass(PassRegistry &);
} // end namespace llvm
(функция обязательно должна быть определена внутри пространства имен llvm).

4. Добавить библиотеку LLVMExperimentPasses в список LLVM_LINK_COMPONENTS в файле tools/opt/CMakeLists.txt:

set(LLVM_LINK_COMPONENTS
    ${LLVM_TARGETS_TO_BUILD}
    AggressiveInstCombine
    ...
    ExperimentPasses
)
Важно: Библиотека перечисляется как ExperimentPasses, а не LLVMExperimentPasses.

5. Зарегистрировать пассы в исходном коде утилиты opt, добавив вызов функции initializeLLVMExperimentPasses в функцию main данной утилиты (в файле tools/opt/opt.cpp):

// Initialize passes
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
...
initializeLLVMExperimentPasses(Registry);
// For codegen passes, only passes that do IR to IR transformation are
// supported.
6. Пересобрать LLVM (здесь YOUR_LLVM_BUILDTREE - каталог, в котором вы собираете вашу копию LLVM) и установить новые библиотеки и утилиты:

cd YOUR_LLVM_BUILDTREE

cmake -DCMAKE_CXX_COMPILER=YOUR_FAVOURITE_COMPILER -DCMAKE_C_COMPILER=YOUR_FAVOURITE_COMPILER -DCMAKE_LINKER=YOUR_FAVOURITE_LINKER .. -G"Ninja"

cmake --build .

cmake --build . --target install
Все, пассы готовы к использованию. Например, пасс FunctionArgumentCount из моего примера будет зарегистрирован под именем fnargcnt и может быть вызван с помощью утилиты opt:

opt.exe -fnargcnt < sum.bc > sum-out.bc

Понравилось сообщение - подпишитесь на блог