Ohjelmointi

Mikä on LLVM? Voima Swiftin, Rustin, Clangin ja muun takana

Uudet kielet ja parannukset olemassa oleviin kieliin ovat levinneet kaikkialle kehittyneeseen maisemaan. Mozillan Rust, Applen Swift, Jetbrainsin Kotlin ja monet muut kielet tarjoavat kehittäjille uudenlaisia ​​vaihtoehtoja nopeuteen, turvallisuuteen, mukavuuteen, siirrettävyyteen ja tehoon.

Miksi nyt? Yksi iso syy on uudet työkalut kielten rakentamiseen - erityisesti kääntäjät. Ja tärkein heistä on LLVM, avoimen lähdekoodin projekti, jonka Swift-kielen luoja Chris Lattner kehitti alun perin tutkimusprojektina Illinoisin yliopistossa.

LLVM helpottaa paitsi uusien kielten luomista myös olemassa olevien kielten kehittämistä. Se tarjoaa työkaluja kielten luomisen monien epäkiitollisimpien osien automatisointiin: kääntäjän luominen, tuotun koodin siirtäminen useille alustoille ja arkkitehtuureille, arkkitehtuurikohtaisten optimointien, kuten vektorisoinnin, luominen ja koodin kirjoittaminen yleisten kielen metaforojen, kuten poikkeuksia. Sen liberaali lisensointi tarkoittaa, että sitä voidaan käyttää vapaasti uudelleen ohjelmistokomponenttina tai ottaa käyttöön palveluna.

LLVM: ää käyttävien kielten luettelolla on monia tuttuja nimiä. Applen Swift-kieli käyttää kääntäjän viitekehyksenä LLVM: ää ja Rust käyttää LLVM: ää työkaluketjunsa keskeisenä osana. Monilla kääntäjillä on myös LLVM-painos, kuten Clang, C / C ++ -kääntäjä (tämä nimi on "C-lang"), joka itsessään on läheisessä yhteydessä LLVM: ään. Mono, .NET-toteutus, on mahdollisuus kääntää natiivikoodiksi LLVM-takapäätä käyttämällä. Ja Kotlin, nimellisesti JVM-kieli, kehittää Kotlin Native -nimisen kielen version, joka käyttää LLVM: ää konekielen koodaamiseen.

LLVM määritelty

Ytimessään LLVM on kirjasto kone-natiivikoodin luomiseen ohjelmallisesti. Kehittäjä käyttää sovellusliittymää luodakseen ohjeet muodossa nimeltä väliesitystai IR. LLVM voi sitten kääntää infrapunayksikön erilliseksi binaariksi tai suorittaa JIT (just-in-time) -kokoelman koodille suoritettavaksi toisen ohjelman yhteydessä, kuten kielen tulkin tai ajonaikana.

LLVM: n sovellusliittymät tarjoavat alkukantoja monien ohjelmointikielissä esiintyvien yleisten rakenteiden ja mallien kehittämiseen. Esimerkiksi melkein jokaisella kielellä on funktion ja globaalin muuttujan käsite, ja monilla on korutiineja ja C-funktiorajapintoja. LLVM: llä on toiminnot ja globaalit muuttujat vakioelementteinä IR: ssä, ja sillä on metaforoja korutiittien luomiseen ja C-kirjastojen kanssa vuorovaikutukseen.

Sen sijaan, että viettäisit aikaa ja energiaa kyseisten pyörien keksimisessä, voit vain käyttää LLVM: n toteutuksia ja keskittyä kielesi osiin, jotka tarvitsevat huomiota.

Lue lisää Go, Kotlin, Python ja Rust

Mennä:

  • Napauta Googlen Go-kielen tehoa
  • Parhaat Go-kielen IDE: t ja toimittajat

Kotlin:

  • Mikä on Kotlin? Java-vaihtoehto selitetty
  • Kotlin-kehykset: Tutkimus JVM-kehitystyökaluista

Python:

  • Mikä on Python? Kaikki mitä sinun tarvitsee tietää
  • Opetusohjelma: Kuinka aloittaa Python
  • 6 välttämätöntä kirjastoa jokaiselle Python-kehittäjälle

Ruoste:

  • Mikä on ruoste? Tapa tehdä turvallinen, nopea ja helppo ohjelmistokehitys
  • Opi aloittamaan Rust

LLVM: Suunniteltu siirrettävyyttä varten

LLVM: n ymmärtäminen saattaa auttaa analysoimaan C-ohjelmointikieliä: C: tä kuvataan joskus kannettavana, korkean tason kokoonpanokielenä, koska sillä on rakenteita, jotka voivat liittyä läheisesti järjestelmän laitteistoon, ja se on siirretty lähes jokainen järjestelmäarkkitehtuuri. Mutta C on hyödyllinen kannettavana kokoonpanokielenä vain pisteeseen saakka; sitä ei ole suunniteltu tiettyä tarkoitusta varten.

Sitä vastoin LLVM: n IR on alusta alkaen suunniteltu kannettavaksi kokoonpanoksi. Yksi tapa saavuttaa tämä siirrettävyys on tarjoamalla primitiivejä riippumatta tietystä konearkkitehtuurista. Esimerkiksi kokonaislukutyypit eivät rajoitu taustalla olevan laitteiston enimmäisbittileveyteen (kuten 32 tai 64 bittiä). Voit luoda primitiivisiä kokonaislukutyyppejä käyttämällä niin monta bittiä kuin tarvitaan, kuten 128-bittinen kokonaisluku. Sinun ei myöskään tarvitse huolehtia tuotoksen muokkaamisesta vastaamaan tietyn prosessorin käskyjoukkoa. LLVM huolehtii siitä myös sinulle.

LLVM: n arkkitehtuurineutraali muotoilu helpottaa kaikenlaisten laitteiden tukemista sekä nykyisessä että tulevaisuudessa. Esimerkiksi IBM on äskettäin lähettänyt koodin tukemaan z / OS: ää, Linux on Power (mukaan lukien tuki IBM: n MASS-vektorikirjastolle) ja AIX-arkkitehtuureja LLVM: n C-, C ++ - ja Fortran-projekteille.

Jos haluat nähdä live-esimerkkejä LLVM IR: stä, siirry ELLCC Project -sivustolle ja kokeile live-esittelyä, joka muuntaa C-koodin LLVM IR: ksi suoraan selaimessa.

Kuinka ohjelmointikielet käyttävät LLVM: ää

LLVM: n yleisimpiä käyttötapoja on kielen ennenaikainen (AOT) kääntäjä. Esimerkiksi Clang-projekti etukäteen kokoaa C: n ja C ++: n alkuperäisiin binääreihin. Mutta LLVM tekee mahdolliseksi myös muut asiat.

Ajankohtainen kääntäminen LLVM: n kanssa

Joissakin tilanteissa koodi on luotava lennossa ajon aikana sen sijaan, että se olisi koottu etukäteen. Esimerkiksi Julian kieli, JIT, kokoaa koodinsa, koska sen on toimittava nopeasti ja oltava vuorovaikutuksessa käyttäjän kanssa REPL (read-eval-print loop) tai vuorovaikutteisen kehotteen kautta.

Numba, matematiikan kiihdytyspaketti Pythonille, JIT kokoaa valitut Python-toiminnot konekoodiksi. Se voi myös koota Numba-koristelun koodin etuajassa, mutta (kuten Julia) Python tarjoaa nopean kehityksen olemalla tulkittu kieli. JIT-kokoelman käyttäminen tällaisen koodin tuottamiseen täydentää Pythonin interaktiivista työnkulua paremmin kuin etukäteen laadittu kokoelma.

Toiset kokeilevat uusia tapoja käyttää LLVM: ää JIT: nä, kuten kokoamalla PostgreSQL-kyselyitä, mikä parantaa suorituskykyä jopa viisinkertaiseksi.

Automaattinen koodin optimointi LLVM: llä

LLVM ei vain koota infrapunaa alkuperäiseen konekoodiin. Voit myös ohjata sen ohjelmallisesti optimoimaan koodin erittäin tarkasti linkitysprosessin läpi. Optimoinnit voivat olla varsin aggressiivisia, mukaan lukien toimintojen upottaminen, kuolleen koodin (mukaan lukien käyttämättömät tyyppikohtaiset ilmoitukset ja funktion argumentit) poistaminen ja silmukoiden purkaminen.

Jälleen kerran voima on siinä, ettei sinun tarvitse toteuttaa tätä kaikkea itse. LLVM voi käsitellä niitä puolestasi tai voit ohjata sen kytkemään ne pois tarvittaessa. Jos esimerkiksi haluat pienempiä binäärejä jonkin suorituskyvyn kustannuksella, saatat kääntäjän käyttöliittymän käskemään LLVM: ää poistamaan silmukan purkamisen käytöstä.

Toimialakohtaiset kielet LLVM: n avulla

LLVM: ää on käytetty kääntäjien tuottamiseen monille yleiskielille, mutta se on hyödyllinen myös sellaisten kielten tuottamiseen, jotka ovat erittäin vertikaalisia tai yksinomaan ongelma-alueille. Joillakin tavoin LLVM loistaa kirkkaimmin, koska se poistaa paljon roskaa tällaisen kielen luomisessa ja saa sen toimimaan hyvin.

Esimerkiksi Emscripten-projekti vie LLVM IR-koodin ja muuntaa sen JavaScriptiksi, mikä teoriassa sallii minkä tahansa kielen, jolla on LLVM-takapää, viedä koodia, jota voidaan käyttää selaimessa. Pitkän aikavälin suunnitelmana on saada LLVM-pohjaiset takapinnat, jotka voivat tuottaa WebAssemblyn, mutta Emscripten on hyvä esimerkki siitä, kuinka joustava LLVM voi olla.

Toinen tapa käyttää LLVM: ää on lisätä toimialakohtaiset laajennukset olemassa olevaan kieleen. Nvidia käytti LLVM: ää Nvidia CUDA Compilerin luomiseen, jonka avulla kielet voivat lisätä natiivitukea CUDA: lle, joka kääntyy osana luomaasi alkuperäistä koodia (nopeammin) sen sijaan, että sitä kutsutaan sen mukana toimitetun kirjaston kautta (hitaammin).

LLVM: n menestys toimialakohtaisten kielten kanssa on herättänyt uusia hankkeita LLVM: ssä niiden aiheuttamien ongelmien ratkaisemiseksi. Suurin ongelma on, kuinka joitain DSL: iä on vaikea kääntää LLVM IR: ksi ilman paljon kovaa työtä käyttöliittymässä. Yksi ratkaisu töissä on monitasoinen keskitason edustus eli MLIR-projekti.

MLIR tarjoaa käteviä tapoja edustaa monimutkaisia ​​tietorakenteita ja operaatioita, jotka voidaan sitten kääntää automaattisesti LLVM IR: ksi. Esimerkiksi TensorFlow-koneoppimiskehyksessä monet sen monimutkaisista tietovirta-kaavio-operaatioista voidaan tehokkaasti koota natiivikoodiksi MLIR: n avulla.

Työskentely LLVM: n kanssa useilla kielillä

Tyypillinen tapa työskennellä LLVM: n kanssa on koodi kielellä, jonka kanssa olet tyytyväinen (ja se tukee tietysti LLVM: n kirjastoja).

Kaksi yleistä kielivalintaa ovat C ja C ++. Monet LLVM-kehittäjät käyttävät yhtä näistä kahdesta useista hyvistä syistä:

  • Itse LLVM on kirjoitettu C ++: lla.
  • LLVM: n sovellusliittymät ovat saatavana C- ja C ++ - inkarnaatioina.
  • Paljon kielenkehitystä tapahtuu yleensä C / C ++: n perustana

Silti nämä kaksi kieltä eivät ole ainoat valinnat. Monet kielet voivat soittaa luonnollisesti C-kirjastoihin, joten teoreettisesti on mahdollista suorittaa LLVM-kehitys millä tahansa tällaisella kielellä. Mutta se auttaa omistamaan todellisen kirjaston kielellä, joka käärii tyylikkäästi LLVM: n sovellusliittymät. Onneksi monilla kielillä ja kielen suoritusajoilla on tällaisia ​​kirjastoja, mukaan lukien C # /. NET / Mono, Rust, Haskell, OCAML, Node.js, Go ja Python.

Yksi varoitus on, että jotkut kielen sitomisista LLVM: ään voivat olla vähemmän täydellisiä kuin toiset. Esimerkiksi Pythonissa on monia vaihtoehtoja, mutta jokainen vaihtelee täydellisyydeltään ja hyödyllisyydeltään:

  • Numban luovan tiimin kehittämä llvmlite on noussut nykyiseksi kilpailijaksi LLVM: n kanssa Pythonissa. Se toteuttaa vain osan LLVM: n toiminnoista Numba-projektin tarpeiden sanelemana. Mutta tämä osajoukko tarjoaa valtaosan siitä, mitä LLVM-käyttäjät tarvitsevat. (llvmlite on yleensä paras valinta työskennellessäsi LLVM: n kanssa Pythonissa.)
  • LLVM-projekti ylläpitää omaa joukkoaan sidoksia LLVM: n C-sovellusliittymään, mutta niitä ei tällä hetkellä ylläpidetä.
  • llvmpy, ensimmäinen suosittu LLVM: n Python-sidos, loppui ylläpidosta vuonna 2015. Huono kaikille ohjelmistoprojekteille, mutta huonompi työskennellessään LLVM: n kanssa, kun otetaan huomioon LLVM: n jokaisessa versiossa tapahtuvien muutosten määrä.
  • llvmcpy pyrkii päivittämään C-kirjaston Python-sidokset ajan tasalle, pitämään ne ajan tasalla automatisoidusti ja saattamaan ne saataville käyttämällä Pythonin alkuperäisiä idiomeja. llvmcpy on vielä alkuvaiheessa, mutta voi jo tehdä alkeellista työtä LLVM-sovellusliittymien kanssa.

Jos olet utelias käyttämään LLVM-kirjastoja kielen rakentamiseen, LLVM: n omilla sisällöntuottajilla on joko C ++ - tai OCAML-opas, joka opastaa luomaan yksinkertaisen kielen nimeltä Kaleidoskooppi. Se on sittemmin siirretty muille kielille:

  • Haskell:Suora portti alkuperäisestä opetusohjelmasta.
  • Python: Yksi tällainen portti seuraa opetusohjelmaa tarkasti, kun taas toinen on kunnianhimoisempi uudelleenkirjoittaminen interaktiivisella komentorivillä. Molemmat käyttävät llvmlite-sidoksia LLVM: ään.
  • RuostejaNopea: Tuntui väistämättömältä, että saimme opetusohjelman portit kahdelle kielelle, jotka LLVM auttoi luomaan.

Lopuksi opetusohjelma on saatavilla myösihmisen Kieli (kielet. Se on käännetty kiinaksi alkuperäisillä C ++ - ja Python-versioilla.

Mitä LLVM ei tee

Kaiken, mitä LLVM tarjoaa, on hyödyllistä tietää myös, mitä se ei tee.

Esimerkiksi LLVM ei jäsennä kielen kielioppia. Monet työkalut tekevät jo työn, kuten lex / yacc, flex / bison, Lark ja ANTLR. Jäsennys on joka tapauksessa tarkoitus irrottaa kokoelmasta, joten ei ole yllättävää, että LLVM ei yritä puuttua tähän.

LLVM ei myöskään käsittele suoraan tietyn kielen ympärillä olevaa suurempaa ohjelmistokulttuuria. Kääntäjän binäärien asentaminen, pakettien hallinta asennuksessa ja työkaluketjun päivittäminen - sinun on tehtävä se itse.

Ja lopuksi, ja mikä tärkeintä, on vielä olemassa yhteisiä osia kielistä, joille LLVM ei tarjoa alkukantoja. Monilla kielillä on jonkinlainen roskien keräämä muistinhallinta joko päämuistina muistin hallinnassa tai lisänä strategioihin, kuten RAII (jota C ++ ja Rust käyttävät). LLVM ei anna sinulle roskien keräysmekanismia, mutta se tarjoaa työkaluja roskien keruun toteuttamiseen sallimalla koodin merkitsemisen metatiedoilla, mikä helpottaa roskien keräilijöiden kirjoittamista.

Mikään näistä ei kuitenkaan sulje pois mahdollisuutta, että LLVM saattaisi lopulta lisätä natiivimekanismeja roskien keräyksen toteuttamiseen. LLVM kehittyy nopeasti, ja se julkaistaan ​​noin puolen vuoden välein. Ja kehitysnopeus todennäköisesti kiihtyy vain sen ansiosta, että monet nykyiset kielet ovat asettaneet LLVM: n kehitysprosessinsa ytimeen.

$config[zx-auto] not found$config[zx-overlay] not found