LLVM

LLVM
Tip de compilator
Dezvoltator Vikram Adwe [d] și Chris Lattner [d]
Scris in C++ [3] , C [4] și limbaj de asamblare [4]
Sistem de operare multiplatformă
Prima editie 24 octombrie 2003 [1]
ultima versiune
Licență Licența deschisă a Universității din Illinois [d] [5]șilicența Apache 2.0[6]
Site-ul web llvm.org
 Fișiere media la Wikimedia Commons

LLVM (fosta Low Level Virtual Machine [7] ) este un proiect de infrastructură software pentru crearea de compilatoare și utilități aferente . Este format dintr-un set de compilatoare din limbaje de nivel înalt (așa-numitele „frontend”), un sistem de optimizare, interpretare și compilare în codul mașinii. Infrastructura se bazează pe un sistem de codare a instrucțiunilor de mașină, independent de platformă, asemănător RISC ( LLVM IR bytecode ), care este un asamblator de nivel înalt cu care funcționează diferite transformări.

Scris în C++, oferă optimizări în etapele de compilare, legare și execuție. Inițial, compilatoarele pentru limbajele C și C++ au fost implementate în proiect folosind front-end-ul Clang , ulterior au apărut front-end-uri pentru multe limbi, inclusiv: ActionScript , Ada , C# [8] , Common Lisp , Crystal , CUDA , D , Delphi , Dylan, Fortran , Limbaj de programare G grafic, Halide , Haskell , Java (bytecode), JavaScript , Julia , Kotlin , Lua , Objective-C , OpenGL Shading Language , Ruby , Rust , Scala , Swift , Xojo .

LLVM poate produce cod nativ pentru o varietate de arhitecturi, inclusiv ARM , x86 , x86-64 , PowerPC , MIPS , SPARC , RISC-V și multe altele (inclusiv GPU -uri de la Nvidia și AMD ).

Unele proiecte au propriile lor compilatoare LLVM (de exemplu, versiunea LLVM a GCC), altele folosesc cadrul LLVM [9] , cum ar fi Glasgow Haskell Compiler .

Dezvoltarea a început în 2000 la Universitatea din Illinois . La mijlocul anilor 2010, LLVM a devenit larg răspândit în industrie: a fost folosit, printre altele, de Adobe , Apple și Google . În special, subsistemul OpenGL din Mac OS X 10.5 se bazează pe LLVM, iar iPhone SDK utilizează preprocesorul GCC (frontend) cu un backend LLVM. Apple și Google sunt unul dintre principalii sponsori ai proiectului, iar unul dintre principalii dezvoltatori, Chris Lattner, a lucrat la Apple timp de 11 ani (din 2017 - la Tesla Motors [10] , din 2020 - în dezvoltator de procesoare și microcontrolere bazate pe arhitectura RISC-V SiFive [11] ).

Caracteristici

LLVM se bazează pe o reprezentare intermediară de cod ( Reprezentare intermediară, IR ), care poate fi transformată în timpul compilării, conectării și execuției. Din această reprezentare, codul mașină optimizat este generat pentru o serie de platforme, atât static, cât și dinamic ( compilare JIT ). LLVM 9.0.0 acceptă generarea de cod static pentru x86 , x86-64 , ARM , PowerPC , SPARC , MIPS , RISC-V , Qualcomm Hexagon , NVPTX, SystemZ, Xcore. Compilarea JIT (generarea codului de mașină în timpul execuției) este acceptată pentru arhitecturile x86, x86_64, PowerPC, MIPS, SystemZ și parțial ARM [12] .

LLVM este scris în C++ și a fost portat pe majoritatea sistemelor de tip Unix și Windows . Sistemul are o structură modulară, modulele sale individuale pot fi construite în diverse sisteme software, poate fi extins cu algoritmi de transformare suplimentari și generatoare de cod pentru noi platforme hardware.

LLVM include un wrapper API pentru OCaml .

Platforme

LLVM acceptă următoarele platforme:

Sistem de operare Arhitectură Compilator
linux x86 / AMD64 GCC , Clang
FreeBSD x86 / AMD64 GCC , Clang
OpenBSD x86 / AMD64 GCC , Clang
Mac OS X PowerPC GCC
Mac OS X x86 / AMD64 GCC , Clang
Solaris UltraSPARC GCC
Cygwin / Win32 x86 GCC 3.4.X, Binutils 2.15
MinGW / Win32 x86 GCC 3.4.X, Binutils 2.15

LLVM are suport parțial pentru următoarele platforme:

Sistem de operare Arhitectură Compilator
AIX PowerPC GCC
linux PowerPC GCC
Amiga OS m68k , PowerPC GCC
Windows x86 MSVC

Tipuri de date

Tipuri simple

Numerele întregi de bitness arbitrar am bit adâncime
  • i1 - valoare booleană - 0 sau 1
  • i32 - întreg pe 32 de biți
  • i17
  • i256
  • Generarea codului nativ pentru tipurile de biți foarte mari nu este acceptată. Dar pentru reprezentarea intermediară nu există restricții.
  • Numerele sunt considerate a fi reprezentate în complement a doi. Nu există nicio distincție între numerele întregi semnate și nesemnate la nivel de tip: acolo unde contează, acestea sunt gestionate de instrucțiuni diferite.
Numere în virgulă mobilă float , double , tipuri specifice platformei (de ex. x86_fp80 )
valoare goală gol

Tipuri derivate

Indicatori tip de* i32* - indicator către un întreg pe 32 de biți
Matrice [număr de elemente x tip]
  • [10 x i32]
  • [8 x dublu]
structurilor { i32, i32, dublu }
Un vector este un tip special pentru simplificarea operațiunilor SIMD .

Vectorul este format din 2 n valori de tip primitiv - întreg sau virgulă mobilă.

<număr de elemente x tip> < 4 x float > - vector XMM
Funcții
  • i32 (i32, i32)
  • float ({ float, float }, { float, float })

Sistemul de tipuri acceptă suprapunerea/imbricarea, adică puteți utiliza matrice multidimensionale, matrice de structuri, pointeri către structuri și funcții etc.

Operațiuni

Majoritatea instrucțiunilor din LLVM iau două argumente (operand) și returnează o valoare (codul cu trei adrese). Valorile sunt definite printr-un identificator text. Valorile locale sunt prefixate %cu , iar valorile globale sunt prefixate cu @. Valorile locale se mai numesc și registre, iar LLVM se mai numește și o mașină virtuală cu un număr infinit de registre. Exemplu:

%sum = adăugați i32 %n, 5 %diff = sub dublu %a, %b %z = adăugați <4 x float> %v1, %v2 ; adăugarea elementară %cond = icmp eq %x, %y ; Comparație între numere întregi. Rezultatul este de tip i1. %success = apel i32 @puts(i8* %str)

Tipul operanzilor este întotdeauna specificat explicit și determină fără ambiguitate tipul rezultatului. Operanzii instrucțiunilor aritmetice trebuie să fie de același tip, dar instrucțiunile în sine sunt „supraîncărcate” pentru orice tip numeric și vector.

LLVM acceptă un set complet de operații aritmetice, operații logice pe biți și operații de deplasare, precum și instrucțiuni speciale pentru lucrul cu vectori.

LLVM IR este puternic tipizat, deci există operații de turnare care sunt codificate explicit cu instrucțiuni speciale. Un set de 9 instrucțiuni acoperă toate variantele posibile între diferite tipuri numerice: întreg și virgulă mobilă, cu semn și fără semn, lungime diferită de biți etc. În plus, există instrucțiuni pentru conversia între numere întregi și pointeri, precum și o instrucțiune universală pentru tip turnare bitcast(responsabilul pentru corectitudinea unor astfel de transformări revine programatorului).

Memorie

Pe lângă valorile înregistrate, LLVM are și gestionarea memoriei. Valorile din memorie sunt adresate prin pointeri tastate . Puteți accesa memoria utilizând două instrucțiuni: loadși store. De exemplu:

%x = încărcare i32* %x.ptr ; încărcați valoarea tipului i32 la pointerul %x.ptr %tmp = adaugă i32 %x, 5 ; adauga 5 stocați i32 %tmp, i32* %x.ptr ; și pune înapoi

Instrucțiunea malloceste tradusă într-un apel al funcției de sistem cu același nume și alocă memorie pe heap , returnând o valoare - un pointer de un anumit tip. Vine cu instructiuni free.

%struct.ptr = malloc { dublu, dublu } %string = malloc i8, i32 %lungime %array = malloc [16 x i32] gratuit i8* %string

Instrucțiunea allocaalocă memorie pe stivă.

%x.ptr = alloca double ; %x.ptr este de tip double* %array = alloca float, i32 8 ; %array este de tip float*, nu [8 x float]!

Memoria alocată allocaeste eliberată automat când funcția se iese utilizând instrucțiunile retsau unwind.

Operații cu pointeri

Pentru a calcula adresele elementelor de matrice, structuri etc. cu tastarea corectă, se folosește instrucțiunea getelementptr.

%array = alloca i32, i32 %size %ptr = getelementptr i32* %array, i32 %index ; valoarea de tip i32*

getelementptrcalculează doar adresa, dar nu accesează memoria. Instrucțiunea acceptă un număr arbitrar de indici și poate dereferința structuri ale oricărei imbricare.

Există, de asemenea, instrucțiuni extractvalueși insertvalue. Ele diferă de getelementptrfaptul că nu iau un pointer către un tip de date agregate (matrice sau structură), ci valoarea acestui tip în sine. extractvaluereturnează valoarea corespunzătoare a subelementului, dar insertvaluegenerează o nouă valoare de tip agregat.

%n = extrage valoare { i32, [4 x i8*] } %s, 0 %tmp = adăugați i32 %n, 1 %s.1 = inserare valoare { i32, [4 x i8*] } %s, i32 %tmp, 0

Note

  1. Lattner K. Versiunea LLVM 1.0 este în sfârșit disponibilă!
  2. LLVM 15.0.4 Lansat - 2022.
  3. Proiectul llvm Open Source pe Open Hub: Pagina de limbi - 2006.
  4. 1 2 Proiectul llvm Open Source pe Open Hub:  Pagina de limbi
  5. Licență  _
  6. http://releases.llvm.org/9.0.0/LICENSE.TXT - 2019.
  7. LLVMdev: Numele LLVM Arhivat 3 noiembrie 2016 la Wayback Machine , Chris Lattner (Apple), 21-12-2011 „„LLVM” nu mai este oficial un acronim. Acronimul pe care l-a extins cândva era confuz și nepotrivit aproape din prima zi.”
  8. LLILC . Preluat la 14 aprilie 2015. Arhivat din original la 19 mai 2019.
  9. Proiecte construite cu LLVM  . llvm. Preluat la 24 mai 2018. Arhivat din original la 24 mai 2018.
  10. Bun venit Chris Lattner | Tesla . Preluat la 11 ianuarie 2017. Arhivat din original la 11 ianuarie 2017.
  11. Fondatorul LLVM se alătură SiFive . Preluat la 28 ianuarie 2020. Arhivat din original la 28 ianuarie 2020.
  12. The LLVM Target-Independent Code Generator Arhivat la 1 mai 2021 la secțiunea Wayback Machine Target Feature Matrix 

Literatură

Link -uri