Introduction to compiler design and techniques.
To install:
- Flex:
flex flex-doc
- Bison:
bison bison-doc
- Makefile:
make-doc
- LLVM:
llvm-dev libncurses5-dev
- Git:
git
- Man:
manpages-dev
We provide:
- Ubuntu 16.04 i386 virtual image for VirtualBox and VMware with all needed tools
- Proxy Transparent Wifi Access Point
- Bison manual:
$ info bison
- Flex manual:
$ info flex
- C99 specification draft
- Gnu C Manual
- bc manual:
$ info bc -n "Basic Expressions"
- GCC manuals including internals manual: link
- Tutorials and documentation at GCC Resource Center at IIT Bombay: link
- Stanford CS143 course
- Book: Compilers: Principles, Techniques, and Tools
- Book: Parsing Techniques: A Practical Guide
Un compilateur est un outil qui transforme un code source écrit dans un langage de programmation (le langage source) en un autre langage informatique (le langage cible).
C compilers:
- top: MVCC, GCC (mingw, cygwin), Clang/LLVM
- others: Turbo/Borland, intel compiler, wactom compiler, TCC, PCC
- multi archs: ~ 70 archs including (ARM, x86, ...) : from supercomputers, pc, phones, embed systems, to firmware/bios
- multi langs:
- Principal: C, C++, obj-C, obj-C++, Fortan, Ada, Java, Go
- autres : Pascal, Mercury, Modula-{2,3}, PL/1, D, VHDL
- extensions : OpenMP, OpenACC
- mutli platforms and OSs: tres grand nombre.
TODO: GCC vs BinUtils
TODO: cpp -> cc1/cc1plus -> as -> ld
gcc -E main.c -o main.i
gcc -S main.i -o main.s -masm=intel
gcc -c main.s -o main.o
gcc main.o -o main
TODO:
clang -cc1 main.c -emit-llvm -disable-llvm-passes
- Online LLVM IR Gen
clang -cc1 main.c -ast-print
clang -cc1 main.c -ast-dump
clang -cc1 main.c -ast-view
clang -cc1 main.c -dump-tokens
gcc -O0 -o main main.c -fdump-tree-all -fdump-rtl-all
:main.c.003t.original
: ASTmain.c.004t.gimple
: GIMPLEmain.c.011t.cfg
: CFGmain.c.???r.*
: RTL IR
TODO:
- print Code from generated AST
- add graphviz dot generation from AST
- view IR tree from generated Module
.........................Front-End.................... .....Middle-End.......... .......Back-End.....................
+-------------+ +------------+ +-------------------+ +---------------------------+ +----------------------------------+
| lexer / | | parser | | semantic | | optimizer | | target-dependent optimization |
| scanner | | | | analyzer | ==> | | ===> | |
| (tokens) | | (AST) | | (check errors) | | | | obj code gen |
+-------------+ +------------+ +-------------------+ +---------------------------+ +----------------------------------+
( C ) -> ( tokens ) -> ( AST ) -> ( GENERIC ) =======> ( GIMPLE ) -> ( SSA ) =======> ( RTL ) --> ( ASM ) --> ( obj code )
|....Flex.....| |...Bison....| |...................................LLVM.....................................................................|
- autre IR output:
- Standard Portable Intermediate Representation SPIR/SPIR-V: utilisé en OpenCl, OpenGL et Vulkan
- LLVM Intermediate Representation: utilisé en LLVM
- HSA Intermediate Layer: Utilisé en HSA specification
- version ancienne (4.3.1): contienne 2,029,115 lines in the main source et 1,546,826 lines in libraries. 57,825 fichiers + 52 configuration scripts + 163 Makefiles.
- determiner les sous-chaine (lexemes) et ses classes (sous-chaine: var1, class: identificateur)
- token =
struct token { char *lexem /* sous-chaine */; enum tk_class class; }
- lookahead:
else
: ide
ou keywordelse
==
: assign=
ou bool op==
>>
in c++:cin >> var
vstempl1<templ2<templ3>>
- instruction:
i = 5 + 2 ;
token string (lexeme) | token type |
---|---|
foo | identificateur |
= | assign operator |
5 | number |
-
| plus operator
2 | number ; | end of instruction
- génère AST depuis definitions du grammaire
- erreurs de syntax détecté la
gcc -E file.c
to get pre-processed c code
- détecté les erreurs semantic:
- erreurs de types
- var non déclaré ou initialisé
- ...
- different lexical, syntactic (et la plus tard different semantic) analyser pour chaque lang
- généralement maximiser la vitesse d'exécution et minimiser le taille objet
code generé:
- pre-calculer la valeur d'une équation constante
- éliminer les block mort (condition d'entrer est toujours false
- éliminer function et variable non utilisé
- expressions et fonctions sans side-effect déplacé au dehors des boucles.
y * 8
=>y << 3
y % 32
=>y & 31
for(i = 0; i < 10; i++) printf("%u\n", i*10);
=>for(i = 0; i < 100; i+= 10) printf("%u\n", i);
- algebraic simplifications:
i + 1 - i
=>1
- constant folding:
5 + 3 - 1
=>7
- Loop-invariant code motion:
for(i = 0; i < n i++;) { x= 5 * 2 * n; printf("hi");}
=>x = 10 * n; for(i = 0; i < n i++;) { printf("hi");}
- Common sub-expression elimination:
x= 15 *n +2; y = 2 + 15 *n;
=>x=15*n+2; y = x;
- partie commun pour les plus tard des lang implementer
- optimizations des floats et doubles expressions dangerous because of
precision limitation:
x / 5.0
!=x * 0.2
(x + y) - y != x
double x = 123454.034684121687525678523745234845234874;
double y = 45234845234.874454563246798654679865467659848655489765;
(x + y) - y != y;
X = Y * 0
=>X = 0
if Y is int but if float:NaN * 0 == NaN
- more:
- Wikipedia: Program optimization
- Paul Hsieh' Programming Optimization
- optimizations related to the target architecture:
- register allocation: prefer register over memory for more used variables
- Code scheduling: reorder instructions to execute on different stages of execution
- du presentation intermédiaire (AST ou autre implementation: SSA, IR, RTL) à code assembleur puis à code machine (obj code)
- different implementation pour chaque type processus
- why:
- très utilisés en implementation des lang: Ruby (YARV), PHP (Zend Parser), GCC, Go, Bash, PostgreSQL, MySQL, ...)
- bien utilisés aussi en implementation des fichier configuration et mini-scripts
- écrits en C (et utilisable en C, C++ et peut être Java)
- free et open source (we love open source)
- standardisés
- facile à intégrer avec GCC et LLVM
- très utilisé en materiel d'éducation en USA et Europe
- alternative:
- Ragel: alternative du flex avec plus mieux support du windows, multi output lang, and graph visualization
- Quex: alternative du Flex avec syntax similaire à Flex et plus mieux support à C++ et Unicode
- Lemon: Bison alternative used on SQLite
- JavaCC: pour implémentation en Java, exemple d'utilisation: Apache Derby, Apache Lucene, Vaadin
- ANTLR: en Java aussi, exemple d'utilisation: Groovy, Jython, Hibernate, Twitter search engine, Apache Cassandra
- Irony: pour C# et .net (IronyPython, Script.NET, ....)
- backend-end (et middle-end) à supporter:
- on peut developer notre specific implementation (avec generation direct d'assembleur d'une platform specific ou d'une platform virtuelle)
- sinon, une platform indépendante (avec un code prés d'assembleur, connu
comme byte code ou intermédiaire representation) qui génère lui meme le code
assembleur pour des platform reels et peut être aussi implement le
middle-end (optimization). Cette platform est nommé low level virtuel
machine:
- LLVM: qui génère un code machine optimisé pour des dizaines d'arch (Nvidia et AMD pour leurs GPU, ...)
- CLR: génère un code pour la platform .Net, (un peu specific pour windows et x86)
- JVM: génère un code pour la platform Java, multi platform.
- intro: syntax and file struct:
- %{ CODE C %}
- REGEX DEFS et OPTIONS
- %% patterns et actions qui match et return le type du token %%
- CODE C
- output: yy.lex.c
- rules:
- longest match
- premier rule valid
- RegExp intro: (
*
,+
,?
,[]
,()
,|
,.
,[[:digit:]]
,{N,M}
,\s
,\S
,\w
,\W
,\d
,\D
,^
,$
,[-]
,[^]
) - Flex Global Variables(yytext, yyleng, .........)
- demos:
- ID
[_a-zA-Z][_a-zA-Z0-9]*
- number
[0-9]+
- Decimal
- Hex
- opérateur relationnel (+, -, *, /, %)
- ID
Workshop: implement wc command line
- file syntax et structure:
- %{ CODE C %} %code (top|requires|provide|) ( CODE C )
- définir les token, les types, precedence et autres règles et options
- %% définition du grammaire en syntax comme BNF %%
- CODE C
- Bison Global Variables(yylval, yylloc, .........)
- output:
<app>.tab.c
<app>.tab.h
- BNF intro et syntax:
- ???
- LALR parser intro
- example: syntax du lua et python
- demo:
- simple calc: NUM ( OP NUM ) *
- reduce/reduce & shift/reduce conflicts (exemples et solutions)
Workshop: implementer bc basic, relational et Boolean Expression et precedence
Workshop: implementer p
Workshop: implementer parser for 2 formats (XML, json, ini, YAML, ...)
- Implementation simple en C++
friend cout& operator<<(...)
- pretty affiche de l'arbre
Workshop: implementer des parties de C99:
- control flow: if, for, while, do..while, switch
- functions
- LLVM et Clang intro:
- A l'origine, un remplacement pour le midlle-end (et partie du back-end) du GCC
- a utilise le front-end du GCC
- un front-end (Clang) a remplacé GCC front-end
- architecture modulaire, moderne et intégrable
- en train de developer sont assembleur et linker
- le meilleur choie pour le développement du nouveau lang et compilateurs
- LLVM IR:
- IR sont utilisé pour facilité l'analyse et l'optimisation du code et programs
- chaque instruction a une simple et seul action bien définit (shift, add, move)
- abstraction des registers, et nombre illimité
- C lui meme est une IR pour les plus haut level lang
- ByteCode (dans java et .Net) sont des IR
- type SSA (Static Single Assignment): type safety, low-level operations
- 2 type de variables: global (functs & global vars)
@
et local%
;
pour les commentaires- types: iN (int 1 à 2^23-1 bits), iN*, [i x iN], [i x iN]*
fN (float), vN (vector), SN (stack), void, ...
halt (16bit float), float (32bit), double (64bit)
vector:
<i x iN>
struct: {iN, iN,...} - functs: define TYPE @NAME (args...) { ret .. } declare TYPE @NAME (args...)
- instructions: high lavel assambly
- add, div, or, and, ret, br, ...
- icmp, switch, select, call
- llvm.{memcpy,memmove,memset,sqrt,powi,ctlz,
- pour avoir le code IR, utilise:
clang -S -emit-llvm file.c
- lli & llc
- program Hello World sample en C (utilisé
puts
au lieu deprintf
) et son IR output (clang -S -emit-llvm app.c
)
#include <stdio.h>
int main() {
puts("Hello Wolrd!");
}
- étudier le syntax du IR (app.ll) et le modifier et l' interpreter (lli) et le compiler (llc)
- le réécrire en llvm-c
- le réécrire en llvm cpp
- ajoute LLVM output à notre AST
::Codegen()
- Optimization passes
- intro
- implementation avec LLVM
- ?
- language theory (+ new diff langs: scala, python, ada, lisp/clojure, prolog)
- programming patterns
- OS arch and dev
- system archi