This shows you the differences between two versions of the page.
cpl:labs:llvm-pass [2015/11/23 11:12] laura.vasilescu |
cpl:labs:llvm-pass [2015/12/08 00:32] (current) irina.presa [Integrarea unui pas în LLVM] |
||
---|---|---|---|
Line 5: | Line 5: | ||
Există numeroase pass-uri deja implementate în versiunea oficială LLVM. Acestea primesc ca input cod ''LLVM IR'' și oferă ca output fie ''LLVM IR'' (în cazul în care este un pass de transformare), fie un text cu diverse statistici (în cazul în care este un pass de analiză). | Există numeroase pass-uri deja implementate în versiunea oficială LLVM. Acestea primesc ca input cod ''LLVM IR'' și oferă ca output fie ''LLVM IR'' (în cazul în care este un pass de transformare), fie un text cu diverse statistici (în cazul în care este un pass de analiză). | ||
- | ===== Rularea unui Pass ===== | + | ===== Crearea unui Pass ===== |
''LLVM Passes'' pot fi rulate cu ajutorul tool-ului ''opt''. | ''LLVM Passes'' pot fi rulate cu ajutorul tool-ului ''opt''. | ||
Line 69: | Line 69: | ||
</code> | </code> | ||
+ | ==== Hello World ==== | ||
- | ===== Crearea unui Pass ===== | + | Vom rula pass-ul default hello pe un cod simplu. |
+ | |||
+ | Codul sursă al pass-ului Hello din LLVM se găsește în directorul ''$LLVM_SRC/lib/Transforms/Hello''. Vizualizați codul sursă și makefile-ul. Pentru detalii suplimentare consultați [[http://llvm.org/docs/WritingAnLLVMPass.html|pagina de manual]]. | ||
+ | |||
+ | După cum ați observat anterior, acesta nu este găsit by default de către tool-ul ''opt''. Va trebui să îi specificăm calea către biblioteca dinamică compilată. | ||
+ | |||
+ | <code bash> | ||
+ | student@cpl-vm ~/llvm-3.6.2 $ opt -load llvm-3.6.2/install/lib/LLVMHello.so --help | ||
+ | OVERVIEW: llvm .bc -> .bc modular optimizer and analysis printer | ||
+ | |||
+ | USAGE: opt [options] <input bitcode file> | ||
+ | |||
+ | [...] | ||
+ | -hello - Hello World Pass | ||
+ | -hello2 - Hello World Pass (with getAnalysisUsage implemented) | ||
+ | [...] | ||
+ | </code> | ||
+ | |||
+ | Fie următorul cod sursă C: | ||
+ | <code C ex.c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int compute(int x) | ||
+ | { | ||
+ | return 10 + 4 * x; | ||
+ | } | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | int x = 10 * 12; | ||
+ | |||
+ | printf("Printing something: %d\n", compute(x)); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Vom genera fișierul ''.bc'' corespunzător: | ||
+ | <code bash> | ||
+ | student@cpl-vm ~ $ clang -emit-llvm ex.c -c -o ex.bc | ||
+ | </code> | ||
+ | |||
+ | Vom rula pass-ul ''Hello'' peste bitcode-ul obținut: | ||
+ | <code bash> | ||
+ | student@cpl-vm ~ $ opt -load llvm-3.6.2/install/lib/LLVMHello.so --hello < ex.bc | ||
+ | WARNING: You're attempting to print out a bitcode file. | ||
+ | This is inadvisable as it may cause display problems. If | ||
+ | you REALLY want to taste LLVM bitcode first-hand, you | ||
+ | can force output with the `-f' option. | ||
+ | |||
+ | Hello: compute | ||
+ | Hello: main | ||
+ | </code> | ||
+ | |||
+ | ==== Integrarea unui pas în LLVM ==== | ||
+ | |||
+ | Pentru a nu mai fi nevoiți să specificăm biblioteca dinamică la runtime, aceasta trebuie să fie integrată în codul utilitarelor ''opt'' și ''bugpoint''. Pentru a realiza acest lucru, trebuie să modificăm [[http://llvm.org/docs/WritingAnLLVMPass.html#quickstart|exemplul]] dat în **sursele** de LLVM astfel: | ||
+ | * ''lib/Transforms/Hello/Makefile'' | ||
+ | * se şterge: **LOADABLE_MODULE = 1** | ||
+ | * și se adaugă: **BUILD_ARCHIVE = 1** | ||
+ | * ''tools/opt/CMakeLists.txt'' | ||
+ | * se adaugă noul pass în lista | ||
+ | * **set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Analysis CodeGen Hello)** | ||
+ | * la fel și pentru ''tools/bugpoint/CMakeLists.txt'' | ||
+ | * se crează fişierul ''include/llvm/Transforms/Hello.h'' cu conţinutul | ||
+ | * <code c> | ||
+ | #ifndef LLVM_TRANSFORMS_HELLO_H | ||
+ | #define LLVM_TRANSFORMS_HELLO_H | ||
+ | namespace llvm { | ||
+ | class FunctionPass; | ||
+ | FunctionPass *createHelloPass(); | ||
+ | } | ||
+ | #endif | ||
+ | </code> | ||
+ | * se creeaza fișierul ''lib/Transforms/Hello/LLVMBuild.txt'' după formatul din [[http://llvm.org/docs/CommandGuide/llvm-build.html|sistemul de build]] llvm. | ||
+ | * ex: <code bash> | ||
+ | [component_0] | ||
+ | type = Library | ||
+ | name = Hello | ||
+ | parent = Transforms | ||
+ | library_name = hello | ||
+ | required_libraries = Analysis Support | ||
+ | </code> | ||
+ | * se updatează și fișierul LLVMBuild.txt din directorul părinte pentru a include sub-directorul ''Hello''. | ||
+ | * ''lib/Transforms/Hello/CMakeLists.txt'' | ||
+ | * se şterge **add_llvm_loadable_module( LLVMHello Hello.cpp )** | ||
+ | * și se adaugă | ||
+ | * **add_llvm_library( LLVMHello Hello.cpp )** | ||
+ | * ''lib/Transforms/Hello/Hello.cpp'' | ||
+ | * se include | ||
+ | * **llvm/Transforms/Hello.h** | ||
+ | * se adaugă | ||
+ | *<code c> | ||
+ | FunctionPass* llvm::createHelloPass() | ||
+ | { | ||
+ | return new Hello(); | ||
+ | } | ||
+ | </code> | ||
+ | * ''include/llvm/LinkAllPasses.h'' | ||
+ | * se include **llvm/Transforms/Hello.h** | ||
+ | * și se adaugă | ||
+ | *<code c> | ||
+ | (void) llvm::createHelloPass(); | ||
+ | </code> | ||
+ | * se creeaza un director nou în care vor fi compilate sursele. De exemplu dacă sursele se află în directorul **llvm-3.3.src** și am creat pe același nivel directorul **llvm**, executăm din **interiorul directorului nou creat** comanda | ||
+ | *<code bash> | ||
+ | cmake -G "Unix Makefiles" ../llvm-3.3.src | ||
+ | </code> | ||
+ | * urmată de comanda <code bash> make </code> |