The LLVM Compiler Architecture - Dipartimento di Matematica e
Transcript
The LLVM Compiler Architecture - Dipartimento di Matematica e
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
The LLVM Compiler Architecture
Matteo Cicuttin
Nicola Gigante
Università di Udine
Dip. di Ingegneria Elettrica, Gestionale e Meccanica
Dip. di Matematica e Informatica
30 aprile 2013
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
Agenda
Parte prima (Matteo):
Introduzione ai compilatori
Presentazione di Clang/LLVM
Parte seconda (Nicola):
Il linguaggio di LLVM
Internals di LLVM
LLVM - Architettura interna
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Compilers 101
I compilatori sono forse i software più complessi che girano sui
calcolatori (se la giocano con i sistemi operativi). Skills richieste al
compiler hacker:
Architetture hardware
Sistemi operativi
Linguaggi formali
Algoritmi e strutture dati
Semantica
Ricerca operativa (?)
Progettazione software
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
Obiettivi di un compilatore
Due classi di obiettivi, legati ai punti di vista di chi usa il
compilatore:
Essere efficiente
Produrre codice efficiente
Essere user-friendly
e di chi sviluppa il compilatore:
Essere modulare e mantenibile
Essere facilmente espandibile
Essere comprensibile
...oltre a generare codice corretto ovviamente!
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
Obiettivi di un compilatore
I processi di (1) creazione del compilatore
e (2) di compilazione sono estremamente
complessi, quindi:
Centrare gli obiettivi: difficile!
Necessaria strategia: identificare
correttamente i sottoproblemi del
processo di compilazione
Sottoproblemi =⇒ moduli del
compilatore
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
La pipeline
Lexer
Parser
Semantics
IR Gen
Intermediate Representation
IR Opt
Codegen
MC Opt
MC Gen
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
La pipeline
Frontend
Lexer
Parser
Semantics
IR Gen
Intermediate Representation
Backend
IR Opt
Codegen
MC Opt
MC Gen
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
La pipeline
Questo approccio ci permette di tenere sotto controllo la
complessità. Ma non solo!
Host system running the compiler
x86
C
C++
Pascal
C#
Java
Haskell
ARM
IR
PowerPC
SPARC
Complessità del nostro task: O(M + N) invece di O(M ∗ N)!
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Analisi lessicale
Il compito dell’analisi lessicale è quello di tradurre il testo in un
flusso di token. Esempio:
i f a <> b t h e n
a := 3
end ;
TOK_KWD_IF TOK_IDENT TOK_NEQ
TOK_IDENT TOK_KWD_THEN TOK_IDENT
TOK_ASSIGN TOK_NUM TOK_KWD_END
TOK_SEMICOL
Alcuni token avranno delle proprietà:
Identificatori (TOK IDENT): nome
Numeri (TOK NUM): valore
Keywords: regular expressions, scanner, tokenizer, finite state
machine
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Analisi sintattica
Il compito dell’analisi sintattica è quello di verificare che il flusso di
token rispetti la grammatica del linguaggio. Se la rispetta
otteniamo l’albero di sintassi astratta.
IF
n
co
d
true
branch
TOK_KWD_IF TOK_IDENT TOK_NEQ
TOK_IDENT TOK_KWD_THEN TOK_IDENT
TOK_ASSIGN TOK_NUM TOK_KWD_END
TOK_SEMICOL
n
itio
<>
a
f
br alse
an
ch
:=
b
a
3
if expr := IF bool expr THEN block END ’;’ ||
IF bool expr THEN block ELSE block END ’;’
Keywords: recursive descent parser, SLR parser, LALR parser, CYK
algorithm
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Analisi semantica
Questa fase ha come scopo principale il controllo della validità
semantica del programma. In particolare esegue cose tipo:
costruzione della symbol table
type checking: rifiutare
int f ( int x ){...}
f = 5;
definite assignment analysis
...
f: int → int
(int → int) ⇐ (int)
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
IR generation
La rappresentazione intermedia è una rappresentazione astratta del
programma sorgente. Può essere:
L’albero di sintassi astratta
=⇒ Non si usa, didattico e troppo legato al linguaggio
sorgente
Three Address Code
=⇒ Si, ma superato (GENERIC di gcc)
Static Single Assignment
=⇒ LLVM bytecode, GIMPLE (sempre gcc)
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Three Address Code
Nasce per rappresentare codice che dovrà girare su una macchina a
registri. Si contrappone al P-Code o al bytecode JVM (stack
based).
Tre indirizzi ⇐⇒ tre operandi
Simile ad un codice assembler
Consideriamo l’espressione w = x ∗ y + z.
=
w
+
∗
x
t0 = x ∗ y
w = t0 + z
z
y
Sembra interessante, ma...
mul r0, rX, rY
add rW, r0, rZ
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
Static Single Assignment - Idea
...iniziamo a pensare alla dead code elimination:
x =1
x =2
w =x +y
x0 = 1
=⇒
x1 = 2
w0 = x1 + y0
L’idea della rappresentazione SSA semplifica un sacco di
ottimizzazioni!
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Static Single Assignment - φ function
Dobbiamo gestire il control flow che si divide e si ricongiunge!
i f x < y then
a := x
else
a := y ;
end ;
cmp lt x0 y0
brc label true, label false
true:
a0 = x0
br label end;
false:
a1 = y0
br label end;
end:
a2 = φ(a0 , a1 )
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Riferimenti
Alcuni riferimenti:
Compiler Construction - Niklaus Wirth
Compiler Construction - Kenneth Louden
Compilers: principles, techniques and tools - Aho, Lam, Sethi,
Ullman
Modern compiler implementation in $(LANG) - Appel
Pascal Implementation - Pemberton, Daniels
Cap. 10: la P-Machine
Lex & Yacc - Brown, Levine, Mason
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM
LLVM è una collezione di tool per la costruzione di compilatori. I
sotto-progetti sono:
LLVM Core: un set di librerie che comprendono un
ottimizzatore e un code generator per tutte le CPU più
comuni.
Clang, il frontend C/C++
LLDB, il debugger
libc++
dragonegg, per integrare i frontend di GCC con LLVM
Molto altro!
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM Core
LLVM in realtà è una libreria che implementa tutto il backend!
“Compila” il linguaggio intermedio LLVM, che è SSA
Le API a disposizione permettono di costruire un compilatore
in tempi rapidi
La documentazione è chiara ed estesa
Manca qualcosa? Creiamo un plugin!
Vediamo un assaggio del suo uso!
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Uso di LLVM
Esempio (alla lavagna):
V a l u e ∗ BinaryExprAST : : Codegen ( ) {
V a l u e ∗L = LHS−>Codegen ( ) ;
V a l u e ∗R = RHS−>Codegen ( ) ;
i f ( L == 0 | | R == 0 ) r e t u r n 0 ;
s w i t c h (Op) {
c a s e ’+ ’ : r e t u r n B u i l d e r . CreateFAdd ( L , R , ” addtmp ” ) ;
c a s e ’− ’ : r e t u r n B u i l d e r . C r e a t e F S u b ( L , R , ” subtmp ” ) ;
c a s e ’ ∗ ’ : r e t u r n B u i l d e r . C r e a t e F M u l ( L , R , ” multmp ” ) ;
d e f a u l t : r e t u r n ErrorV ( ” i n v a l i d b i na r y operator ” ) ;
}
}
Fonte: http://www.llvm.org/docs/tutorial/index.html
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
Uso con Yacc/Bison (idea)
binExpr: binExpr ’+’ binExpr {
$$ = Builder.CreateFAdd($1, $2, "addtmp");
}
binExpr: binExpr ’-’ binExpr {
$$ = Builder.CreateFSub($1, $2, "subtmp");
}
binExpr: binExpr ’*’ binExpr {
$$ = Builder.CreateFMul($1, $2, "multmp");
}
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
I plugin per LLVM
Vediamo un passo di ottimizzazione banale:
namespace {
c l a s s Hello : public FunctionPass {
public :
v i r t u a l b o o l r u n O n F u n c t i o n ( F u n c t i o n &F ) {
c e r r << ” H e l l o : ” << F . getName ( ) << ” \n” ;
return false ;
}
};
}
F u n c t i o n P a s s ∗ c r e a t e H e l l o P a s s ( ) { r e t u r n new H e l l o ( ) ; }
Questo passo stampa i nomi delle funzioni su cui l’ottimizzatore
sta lavorando.
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Il frontend Clang
Clang è il frontend C/C++/ObjC e compila questi tre linguaggi in
LLVM.
Anche Clang è una libreria (clang è il driver)
Facilmente integrabile in altre applicazioni
Supporto alla compilazione incrementale
Syntax highlighting & checking
Automatic refactoring
Code indexing
Informazione mantenuta attraverso i passi di compilazione
Migliore diagnostica
Source-to-source translation (py2to3 )
GCC-compatibile
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
La diagnostica di Clang
La diagnostica di Clang è estremamente più espressiva di quella di
GCC:
Esempio banale: ve ne accorgerete usandolo!!
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Le performance di Clang
Clang tipicamente è molto più CPU- e Memory-efficient di GCC.
Alcuni numeri (outdated):
Compila Carbon.h 2.5x più velocemente di GCC
Compila Carbon.h utilizzando 1/6 della memoria
distcc-friendly: Preprocessore Clang spende 10x tempo
kernel in meno rispetto a GCC =⇒ distcc 3x più veloce
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
Compilare Clang
Compilare Clang è banale...
s v n co h t t p : / / l l v m . o r g / s v n / l l v m −p r o j e c t / l l v m / t r u n k l l v m
cd l l v m / t o o l s
s v n co h t t p : / / l l v m . o r g / s v n / l l v m −p r o j e c t / c f e / t r u n k c l a n g
cd . . / . .
cd l l v m / p r o j e c t s
s v n co h t t p : / / l l v m . o r g / s v n / l l v m −p r o j e c t / c o m p i l e r −r t / t r u n k \
c o m p i l e r −r t
cd . . / . .
mkdir b u i l d
cd b u i l d
. . / llvm / configure
make −j 1 6
...ora avete la nuova toolchain a disposizione!
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
Domande?
Domande?
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Intermediate Representation
Introduzione
Il LLVM IR è la forma in cui il codice viene rappresentato
all’interno dell’ottimizzatore di LLVM.
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM Intermediate Representation
Introduzione
Come LLVM rappresenta il sorgente:
Set di istruzioni di basso livello, simile ad un assembly RISC
Architettura load/store
Alcuni elementi di livello più alto:
Astrazione dai dettagli delle convenzioni di chiamata
Flessibile supporto alla gestione delle eccezioni
Registri virtualmente infiniti
Type system strutturato ed esplicito
Istruzioni atomiche e istruzioni vettoriali
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Esempio
Codice C:
Corrispondente IR:
int abs(int n) {
if(n < 0)
return -n;
else
return n;
}
define i32 @abs(i32 %n) {
entry:
%1 = icmp slt i32 %n, 0
br i1 %1, label then, label end
then:
%2 = sub nsw i32 0, %n
br label end
end:
%3 = phi i32 [%2 then] [%n entry]
ret i32 %3
}
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Esempio
Codice C:
int abs(int n) {
if(n < 0)
return -n;
else
return n;
}
Corrispondente IR (ottimizzato -O3):
define i32 @abs(i32 %n) {
%1 = icmp slt i32 %n, 0
%2 = sub nsw i32 0, %n
%3 = select i1 %1, i32 %2, i32 %n
ret i32 %3
}
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Registri e accesso alla memoria
LLVM modella una macchina con infiniti registri
Ogni registro ha un tipo ben definito
Ogni istruzione usa e/o definisce uno o più registri
Le istruzioni che definiscono registri sono in formato SSA
L’accesso alla memoria principale è limitato a sole due
istruzioni load e store
Allocazione esplicita di spazio per le variabili locali sullo stack
frame
Aritmetica dei puntatori gestita esplicitamente
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Controllo del flusso
LLVM esplicita il controllo del flusso.
Il corpo di una funzione è un Control Flow Graph composto da
basic block:
Sequenza di istruzioni elementari
Una e una sola istruzione di branching alla fine, quindi almeno
un successore
Almeno un predecessore, tranne il blocco di entrata della
funzione
Quindi ogni basic block è l’unità minima di codice rispetto al
controllo del flusso
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Controllo del flusso (2)
Oltre al control flow graph all’interno di una singola funzione,
dall’IR si risale immediatamente ad altre strutture:
Call graph
Data dependency graph
Altro...
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Controllo del flusso - esempio
Codice di esempio:
define i32 @abs(i32 %n) {
entry:
%1 = icmp slt i32 %n, 0
br i1 %1, label then,
label end
then:
%2 = sub nsw i32 0, %n
br label end
end:
%3 = phi i32 [%2 then]
[%n entry]
ret i32 %3
}
Control Flow Graph:
entry
then
end
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Controllo del flusso - esempio
Codice di esempio:
define i32 @abs(i32 %n) {
entry:
%1 = icmp slt i32 %n, 0
br i1 %1, label then,
label end
then:
%2 = sub nsw i32 0, %n
br label end
end:
%3 = phi i32 [%2 then]
[%n entry]
ret i32 %3
}
Data Dependency Graph:
%n
sub
phi
%2
phi
%3
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Intermediate Representation
Type system
Ogni registro e ogni accesso alla memoria ha un tipo ben
specificato.
Le conversioni di tipo avvengono solo tramite ben specifiche
istruzioni di cast
Tipi base:
Interi: i1, i8, i16, i32, i64
Floating point: float, double
Puntatori (esempio: i32*)
Tipi aggregati:
Array (esempio: [ 42 x i8 ])
Vettori (esempio: <8 x i32>)
Strutture (esempio: { i32, float })
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Intermediate Representation
Type system - esempio
Struttura C:
Tipo nell’IR:
struct S {
int n;
float x;
struct S *a[42];
};
%S = {
i32,
float,
[ 42 x %S* ]
}
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Introduzione
Le parole chiave nelle scelte progettuali di LLVM sono modularità
ed efficienza. È molto difficile far andare d’accordo questi due
aspetti.
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Architettura interna
Introduzione
IR
Passi di analisi
Passi di
ottimizzazione
Si
Passi
invalidati?
No
Target Lowering
Codice macchina
LLVM - Uso delle API
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Passi di ottimizzazione
L’ottimizzatore lavora applicando all’IR una sequenza di “passi” di
ottimizzazione.
I passi si dividono secondo il livello a cui operano: Module
pass, Function pass, CFG pass, Loop pass, ecc...
Ogni passo estrae informazioni dall’IR (Analyzer pass) o
trasforma l’IR secondo qualche criterio (Transform pass).
Un transform pass può invalidare il risultato di passi
precedenti, che possono dover essere rieseguiti
- esempio: la constant propagation va rifatta dopo l’inlining
I passi sono target-independent ma target-aware
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Passi di ottimizzazione
Alcuni comuni passi di ottimizzazione:
Inlining
Combine Redundant Instructions
((Interprocedural) Sparse Conditional) Constant Propagation
Dead Code Elimination
Type Based Alias Analysis
Tail Call Elimination
Loop transformations
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Target backend
La “lowering” del codice IR in codice macchina avviene in più fasi:
Instruction selection
SSA machine code optimization
Instruction scheduling
Register allocation
Late machine code optimization
Machine code emission
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Target backend
La “lowering” del codice IR in codice macchina avviene in più fasi:
Instruction selection
SSA machine code optimization
Instruction scheduling
Register allocation
Late machine code optimization
Machine code emission
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Target backend
La “lowering” del codice IR in codice macchina avviene in più fasi:
Instruction selection
SSA machine code optimization
Instruction scheduling
Register allocation
Late machine code optimization
Machine code emission
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Target backend
La “lowering” del codice IR in codice macchina avviene in più fasi:
Instruction selection
SSA machine code optimization
Instruction scheduling
Register allocation
Late machine code optimization
Machine code emission
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Target backend
La “lowering” del codice IR in codice macchina avviene in più fasi:
Instruction selection
SSA machine code optimization
Instruction scheduling
Register allocation
Late machine code optimization
Machine code emission
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Target backend
La “lowering” del codice IR in codice macchina avviene in più fasi:
Instruction selection
SSA machine code optimization
Instruction scheduling
Register allocation
Late machine code optimization
Machine code emission
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Architettura interna
Just In Time compilation
LLVM supporta l’esecuzione on-the-fly del codice appena generato
(Just In Time compilation).
Indispensabile per l’implementazione di interpreti
Il codice macchina viene emesso direttamente in memoria e
linkato con l’eseguibile host.
L’host ha pieno controllo sul rilocamento dei simboli
È possibile eseguire una compilazione lazy (vengono jittate
solo le funzioni effettivamente eseguite a runtime)
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Uso delle API
Introduzione
LLVM fornisce un’insieme di librerie di classi C++ per la
manipolazione dell’IR e l’esecuzione dell’ottimizzatore e del
backend.
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Uso delle API
Moduli e librerie
Alto numero di piccole librerie diverse, per maggiore modularità:
Moduli principali: libLLVMCore e libLLVMSupport
Moduli di backend: libLLVMCodeGen, libLLVMMC,
libLLVMExecutionEngine
Passi di ottimizzazione extra (IPA, debug, instrumentation,
LTO, etc...)
Moduli di backend specifici (x86, PPC, Mips, etc...)
Accessori vari...
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Uso delle API
Manipolazione dell’IR
La rappresentazione interna dell’IR è Object-Oriented:
La classe Module tiene traccia di tutto l’IR di un modulo
Oggetti di classe Value rappresentano il risultato di una
computazione e formano i Data Dependency Graph
Instruction, Constant, Function etc... sono sottoclassi di
Value
Una sottoclasse di Instruction per ogni istruzione,
raggruppate in oggetti BasicBlock a formare il Control Flow
Graph di ogni Function
La classe Type e sue sottoclassi rappresentano i tipi
IntegerType, StructureType, ArrayType, etc...
Tipi strutturalmente simili sono rappresentati dallo stesso
oggetto (tranne se esplicitamente denominati)
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Uso delle API
Realizzazione di moduli custom
Realizzare moduli (compresi i passi dell’ottimizzatore) per LLVM è
relativamente semplice.
È consigliabile utilizzare il build system interno
Un passo eredita da una sottoclasse di Pass (ModulePass,
FunctionPass, CFGPass, etc...)
Ogni passo indica le analisi di cui ha bisogno, le analisi che
fornisce e le analisi che invalida (call graph, alias analysis
etc...)
Ogni passo si registra nel sistema di plugin di LLVM e diventa
caricabile a runtime su richiesta.
Reference:
http://llvm.org/docs/WritingAnLLVMPass.html
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Architettura interna
LLVM - Uso delle API
LLVM - Uso delle API
Dall’IR al metallo
Sequenza tipica di operazioni per compilare codice con LLVM:
Costruire e comporre l’IR istanziando le opportune classi (la
classe IRBuilder può tornare utile)
Scegliere ed eseguire i passi di ottimizzazione con la classe
PassManager
Emettere il codice macchina con MachineCodeEmitter o
eseguirlo con ExecutionEngine
Preliminari
Fasi
Clang & LLVM
LLVM - IR
LLVM - Uso delle API
Kaleidoscope
Demo
LLVM - Architettura interna
LLVM - Uso delle API