Ukuphuhlisa umqokeleli ngumsebenzi onzima kakhulu. Kodwa, ngethamsanqa, ngophuhliso lweeprojekthi ezifana ne-LLVM, isisombululo sale ngxaki senziwe lula kakhulu, esivumela ukuba nomdwelisi omnye ukuba enze ulwimi olutsha olusondeleyo ekusebenzeni kwi-C. Ukusebenza ne-LLVM kuyinkimbinkimbi yinto yokuba oku inkqubo imelwe sisixa esikhulu sekhowudi, exhotyiswe ngamaxwebhu amancinane . Ukuze uzame ukulungisa le ntsilelo, umbhali wezinto eziphathekayo, inguqulelo esiyipapashayo namhlanje, uya kubonisa imizekelo yekhowudi ebhalwe kwi-Go kwaye ibonise indlela eguqulelwe ngayo kuqala
Umzekelo wokuqala
Umsebenzi wokuqala endiza kuwujonga apha yindlela elula yokongeza amanani:
func myAdd(a, b int) int{
return a + b
}
Lo msebenzi ulula kakhulu, kwaye, mhlawumbi, akukho nto inokuba lula. Iguqulela kule khowudi ilandelayo yeGo SSA:
func myAdd(a int, b int) int:
entry:
t0 = a + b int
return t0
Ngalo mbono, iingcebiso zodidi lwedatha zibekwe ekunene kwaye zinokuhoywa kwiimeko ezininzi.
Lo mzekelo mncinane sele ukuvumela ukuba ubone undoqo wenkalo enye ye-SSA. Okukuthi, xa uguqulela ikhowudi kwifomu ye-SSA, intetho nganye yahlulahlulwe yaya kutsho kwezona ndawo zisisiseko apho iqulunqwe khona. Kwimeko yethu, umyalelo return a + b
, eneneni, imele imisebenzi emibini: ukudibanisa amanani amabini kunye nokubuyisela isiphumo.
Ukongeza, apha ungabona iibhloko ezisisiseko zenkqubo; kule khowudi kukho ibhloko enye kuphela - ibhloko yokungena. Siza kuthetha ngakumbi malunga neebhloko ngezantsi.
Ikhowudi ye-Go SSA iguqulela ngokulula kwi-LLVM IR:
define i64 @myAdd(i64 %a, i64 %b) {
entry:
%0 = add i64 %a, %b
ret i64 %0
}
Into onokuthi uyiqaphele kukuba nangona izakhiwo ezahlukeneyo zesyntactic zisetyenziswa apha, ulwakhiwo lomsebenzi alutshintshanga. Ikhowudi ye-LLVM IR inamandla kancinane kunekhowudi ye-Go SSA, efana ne-C. Apha, kwisibhengezo somsebenzi, okokuqala kukho inkcazo yohlobo lwedatha olubuyiselayo, uhlobo lwengxabano lubonakaliswe phambi kwegama lengxabano. Ukongeza, ukwenza lula ukwahlulahlula kwe-IR, amagama amaqumrhu ehlabathi andulelwa sisimboli @
, kwaye phambi kwamagama asekuhlaleni kukho uphawu %
(umsebenzi ukwathathwa njengequmrhu lehlabathi).
Into enye ekufuneka uyiqaphele malunga nale khowudi kukuba isigqibo sokumelwa kohlobo lweGo int
, enokumelwa njengexabiso le-32-bit okanye i-64-bit, ngokuxhomekeke kumqokeleli kunye nethagethi yokuhlanganiswa, yamkelwe xa i-LLVM ivelisa ikhowudi ye-IR. Esi sesinye sezizathu ezininzi zokuba ikhowudi ye-LLVM IR ayikho, njengoko abantu abaninzi becinga, iqonga elizimeleyo. Ikhowudi enjalo, eyenzelwe iqonga elinye, ayinakuthatyathwa kwaye iqulunqelwe elinye iqonga (ngaphandle kokuba ukulungele ukusombulula le ngxaki.
Enye inqaku elinomdla elifanele liphawulwe kukuba uhlobo i64
Asiyonani elipheleleyo esayiniweyo: ayithathi cala ngokumela uphawu lwenani. Ngokuxhomekeke kumyalelo, inokumela zombini amanani asayiniweyo kunye namanani angabhalwanga. Kwimeko yokumelwa komsebenzi wokongezwa, oku akunamsebenzi, ngoko akukho mahluko ekusebenzeni ngamanani asayiniweyo okanye angasayinwanga. Apha ndingathanda ukuqaphela ukuba kulwimi lwe-C, ukuphuphuma kwenani elipheleleyo elisayiniweyo likhokelela kwindlela yokuziphatha engachazwanga, ngoko i-frontend ye-Clang yongeza iflegi kumsebenzi. nsw
(akukho zisongelo esayiniweyo), exelela i-LLVM ukuba inokucinga ukuba ukongeza akusayi kuphuphuma.
Oku kunokubaluleka kwezinye izilungiso. Umzekelo, ukongeza amaxabiso amabini i16
kwiplatifti ye-32-bit (enerejista ye-32-bit) ifuna, emva kokongezwa, umsebenzi wokwandisa uphawu ukuze uhlale kuluhlu. i16
. Ngenxa yoku, kudla ngokusebenza ngakumbi ukwenza imisebenzi epheleleyo ngokusekwe kubungakanani berejista yomatshini.
Yintoni eyenzekayo ngokulandelayo ngale khowudi ye-IR ayinamdla ukhethekileyo kuthi ngoku. Ikhowudi iphuculwe (kodwa kwimeko yomzekelo olula njengowethu, akukho nto iphuculweyo) kwaye iguqulelwe kwikhowudi yomatshini.
Umzekelo wesibini
Umzekelo olandelayo esiza kujonga kuwo uya kuba nzima ngakumbi. Oko kukuthi, sithetha ngomsebenzi oshwankathela isilayi samanani apheleleyo:
func sum(numbers []int) int {
n := 0
for i := 0; i < len(numbers); i++ {
n += numbers[i]
}
return n
}
Le khowudi iguqulela kule khowudi ilandelayo yeGo SSA:
func sum(numbers []int) int:
entry:
jump for.loop
for.loop:
t0 = phi [entry: 0:int, for.body: t6] #n int
t1 = phi [entry: 0:int, for.body: t7] #i int
t2 = len(numbers) int
t3 = t1 < t2 bool
if t3 goto for.body else for.done
for.body:
t4 = &numbers[t1] *int
t5 = *t4 int
t6 = t0 + t5 int
t7 = t1 + 1:int int
jump for.loop
for.done:
return t0
Apha unokubona ezinye izakhiwo eziqhelekileyo zokumela ikhowudi kwifom ye-SSA. Mhlawumbi eyona nto icacileyo yale khowudi yinto yokuba akukho miyalelo yolawulo lokuqukuqela ecwangcisiweyo. Ukulawula ukuhamba kwezibalo, kukho ukutsiba okunemiqathango kunye nokungenamiqathango, kwaye, ukuba siqwalasela lo myalelo njengomyalelo wokulawula ukuhamba, umyalelo wokubuyisela.
Enyanisweni, apha unokunikela ingqalelo kwinto yokuba inkqubo ayihlulwanga ibe ziibhloko usebenzisa iibrayisi ezigobileyo (njengakwintsapho yeelwimi C). Yahlulwe ngeeleyibhile, ikhumbuza iilwimi zendibano, kwaye inikezelwe ngendlela yeebhloko ezisisiseko. Kwi-SSA, iibhloko ezisisiseko zichazwa njengolandelelwano oludityanisiweyo lwekhowudi eqala ngeleyibhile kwaye iphele ngemiyalelo esisiseko yokugqibezela ibhloko, efana β return
ΠΈ jump
.
Enye ingcaciso enomdla yale khowudi imelwe ngumyalelo phi
. Imiyalelo ayiqhelekanga kwaye inokuthatha ixesha ukuyiqonda. khumbula, ukuba myAdd
eboniswe ngasentla, kodwa ayilungelanga imisebenzi entsonkothileyo njengomsebenzi oxoxwe kweli candelo sum
. Ngokukodwa, iinguqu zitshintsha ngexesha lokwenziwa kwe-loop i
ΠΈ n
.
I-SSA idlula umda wokwabela amaxabiso aguquguqukayo kube kanye usebenzisa into ebizwa ngokuba ngumyalelo phi
(igama layo lithatyathwe kwialfabhethi yesiGrike). Inyani kukuba ukuze ukumelwa kwekhowudi ye-SSA kuveliswe kwiilwimi ezinje ngeC, kuya kufuneka ubhenele kumaqhinga athile. Isiphumo sokubiza lo myalelo lixabiso langoku loguqulo (i
okanye n
), kwaye uluhlu lweebhloko ezisisiseko zisetyenziswa njenge parameters zayo. Ngokomzekelo, qwalasela lo myalelo:
t0 = phi [entry: 0:int, for.body: t6] #n
Intsingiselo yalo ilandelayo: ukuba ibhloko yangaphambili esisiseko yayiyibhloko entry
(igalelo), ngoko t0
yinto engatshintshiyo 0
, kwaye ukuba ibhloko esisiseko yangaphambili yayi for.body
, ngoko kufuneka uthathe ixabiso t6
ukusuka kule block. Konke oku kunokubonakala kungaqondakali, kodwa lo matshini yeyona nto yenza ukuba i-SSA isebenze. Ngokwembono yomntu, konke oku kwenza ukuba ikhowudi ibe nzima ukuyiqonda, kodwa into yokuba ixabiso ngalinye linikezelwe kube kanye kuphela kwenza ukuba uninzi lwazo lube lula kakhulu.
Qaphela ukuba ubhala eyakho i compiler, awuzukufuneka ujongane nolu hlobo lwezinto. Nditsho noClang akavelisi yonke le miyalelo phi
, isebenzisa isixhobo alloca
(ifana nokusebenza ngeenguqu eziqhelekileyo zendawo). Emva koko, xa uqhuba i-LLVM yokuphumelela ipasi ebizwa alloca
iguqulelwe kwifomu ye-SSA. I-TinyGo, nangona kunjalo, ifumana igalelo kwi-Go SSA, ethi, ngokulula, sele iguqulelwe kwifom ye-SSA.
Olunye uhlaziyo lweqhekeza lekhowudi ephakathi phantsi kwengqwalasela kukuba ukufikelela kwizinto eziqhekezayo ngesalathiso kubonakaliswe ngendlela yokusebenza kokubala idilesi kunye nokusebenza kokurhoxisa isalathisi esisiphumo. Apha ungabona ukongezwa ngokuthe ngqo kwezigxininisi kwikhowudi ye-IR (umzekelo - 1:int
). Kumzekelo kunye nomsebenzi myAdd
oku akuzange kusetyenziswe. Ngoku sele sizifumene ezo mpawu endleleni, makhe sijonge ukuba le khowudi iba yintoni xa iguqulelwa kwifom ye-LLVM IR:
define i64 @sum(i64* %ptr, i64 %len, i64 %cap) {
entry:
br label %for.loop
for.loop: ; preds = %for.body, %entry
%0 = phi i64 [ 0, %entry ], [ %5, %deref.next ]
%1 = phi i64 [ 0, %entry ], [ %6, %deref.next ]
%2 = icmp slt i64 %1, %len
br i1 %2, label %for.body, label %for.done
for.body: ; preds = %for.loop
%3 = getelementptr i64, i64* %ptr, i64 %1
%4 = load i64, i64* %3
%5 = add i64 %0, %4
%6 = add i64 %1, 1
br label %for.loop
for.done: ; preds = %for.loop
ret i64 %0
}
Apha, njengangaphambili, sinokubona isakhiwo esifanayo, esibandakanya ezinye izakhiwo ze-syntactic. Umzekelo, kwiifowuni phi
amaxabiso kunye neelebhile zitshintshiwe. Nangona kunjalo, kukho into apha efanelwe ingqalelo ekhethekileyo.
Ukuqala, apha unokubona utyikityo lomsebenzi owahluke ngokupheleleyo. I-LLVM ayixhasi izilayi, kwaye ngenxa yoko, njenge-optimization, i-TinyGo compiler evelise le khowudi ephakathi yahlula inkcazo yesi sakhiwo sedatha kwiinxalenye. Inokumela izinto ezintathu zesilayi (ptr
, len
ΠΈ cap
) njengesakhiwo (isakhiwo), kodwa ukubamela njengamaqumrhu amathathu ahlukeneyo kuvumela ulungiselelo oluthile. Abanye abaqulunqi banokumela isilayi ngezinye iindlela, ngokuxhomekeke kwiindibano zokubiza imisebenzi yeqonga ekujoliswe kulo.
Enye into enomdla kule khowudi kukusetyenziswa komyalelo getelementptr
(idla ngokufinyezwa njenge-GEP).
Lo myalelo usebenza ngezalathisi kwaye usetyenziselwa ukufumana isalathi sento yesilayi. Umzekelo, masiyithelekise nale khowudi ilandelayo ebhalwe ku-C:
int* sliceptr(int *ptr, int index) {
return &ptr[index];
}
Okanye ngokuhambelana noku kulandelayo:
int* sliceptr(int *ptr, int index) {
return ptr + index;
}
Eyona nto ibalulekileyo apha kukuba imiyalelo getelementptr
ayiwenzi imisebenzi yokurhoxisa. Ibala nje isalathisi esitsha ngokusekwe kwesi sikhoyo. Inokuthathwa njengemiyalelo mul
ΠΈ add
kwinqanaba le-hardware. Unokufunda ngakumbi malunga nemiyalelo ye-GEP
Enye into enomdla kule khowudi ephakathi kukusetyenziswa komyalelo icmp
. Lo ngumyalelo wenjongo jikelele osetyenziswayo ukuphumeza uthelekiso olupheleleyo. Isiphumo sokuphumeza lo myalelo sihlala sixabiso lohlobo i1
- ixabiso elisengqiqweni. Kule meko, uthelekiso lwenziwa kusetyenziswa igama elingundoqo slt
(isayinwe ngaphantsi kwe), njengoko sithelekisa amanani amabini amelwe ngaphambili luhlobo int
. Ukuba besithelekisa amanani amabini angasayinwanga, besiya kusebenzisa icmp
, kwaye igama elingundoqo elisetyenziswe kuthelekiso liya kuba ult
. Ukuthelekisa amanani amanqaku adadayo, kusetyenziswa omnye umyalelo, fcmp
, esebenza ngendlela efanayo.
Iziphumo
Ndiyakholelwa ukuba kulo mbandela ndigubungele ezona mpawu zibalulekileyo ze-LLVM IR. Ewe, kukho okuninzi ngakumbi apha. Ngokukodwa, ukumelwa okuphakathi kwekhowudi kunokuquka izichasiselo ezininzi ezivumela ukugqithiswa kokulungelelaniswa ukuba kuthathelwe ingqalelo iimpawu ezithile zekhowudi ezaziwa ngumqambi ongenakuchazwa ngenye indlela kwi-IR. Umzekelo, le flegi inbounds
Imiyalelo ye-GEP, okanye iiflegi nsw
ΠΈ nuw
, enokongezwa kwimiyalelo add
. Kukwanjalo nakwigama elingundoqo private
, ebonisa isilungisi ukuba umsebenzi esiwuphawulayo awusayi kubhekiselwa ngaphandle kweyunithi yoqulunqo lwangoku. Oku kuvumela uninzi lwezinto ezinomdla zokusebenzisa iinkqubo ezihambelanayo ezifana nokuphelisa iimpikiswano ezingasetyenziswanga.
Unokufunda ngakumbi malunga ne-LLVM kwi
Bafundi abathandekayo! Ngaba usebenzisa i-LLVM?
umthombo: www.habr.com