I-LLVM ngokombono we-Go

Ukwakha umhlanganisi kuwumsebenzi onzima kakhulu. Kodwa, ngenhlanhla, ngokuthuthukiswa kwamaphrojekthi afana ne-LLVM, isisombululo sale nkinga senziwe lula kakhulu, okuvumela ngisho nomdidiyeli oyedwa ukuthi akhe ulimi olusha olusondele ekusebenzeni ku-C. Ukusebenza ne-LLVM kuyinkimbinkimbi yiqiniso lokuthi lokhu uhlelo lumelwe inani elikhulu lekhodi, elifakwe imibhalo emincane. Ukuze uzame ukulungisa lokhu kushiyeka, umbhali wendaba, ukuhunyushwa esikushicilela namuhla, uzobonisa izibonelo zekhodi ebhalwe ku-Go futhi abonise ukuthi ahunyushwa kanjani kuqala Hamba SSA, bese ku-LLVM IR usebenzisa isihlanganisi I-TinyGO. Ikhodi ye-Go SSA ne-LLVM IR ihlelwe kancane ukuze isuse izinto ezingahambisani nezincazelo ezinikezwe lapha, ukuze kwenziwe izincazelo ziqondakale kakhudlwana.

I-LLVM ngokombono we-Go

Isibonelo sokuqala

Umsebenzi wokuqala engizowubheka lapha indlela elula yokwengeza izinombolo:

func myAdd(a, b int) int{
    return a + b
}

Lo msebenzi ulula kakhulu, futhi, mhlawumbe, akukho okungaba lula. Ihumusha kukhodi elandelayo ye-Go SSA:

func myAdd(a int, b int) int:
entry:
    t0 = a + b                                                    int
    return t0

Ngalokhu kubuka, izinkomba zohlobo lwedatha zibekwe kwesokudla futhi zingazitshwa ezimweni eziningi.

Lesi sibonelo esincane sesivele sikuvumela ukuthi ubone ingqikithi yesici esisodwa se-SSA. Okungukuthi, lapho uguqula ikhodi ibe yifomu le-SSA, isisho ngasinye sihlukaniswa sibe izingxenye eziyisisekelo lapho sakhiwe khona. Esimweni sethu, umyalo return a + b, empeleni, imele imisebenzi emibili: ukwengeza izinombolo ezimbili nokubuyisela umphumela.

Ngaphezu kwalokho, lapha ungabona amabhlogo ayisisekelo wohlelo; kule khodi kukhona ibhulokhi eyodwa kuphela - ibhulokhi yokungena. Sizokhuluma kabanzi ngamabhulokhi ngezansi.

Ikhodi ye-Go SSA iguqulelwa kalula ku-LLVM IR:

define i64 @myAdd(i64 %a, i64 %b) {
entry:
  %0 = add i64 %a, %b
  ret i64 %0
}

Ongakuqaphela ukuthi nakuba izakhiwo ze-syntactic ezehlukene zisetshenziswa lapha, isakhiwo somsebenzi asishintshile. Ikhodi ye-LLVM IR inamandla kancane kunekhodi ye-Go SSA, efana ne-C. Lapha, kusimemezelo somsebenzi, okokuqala kunencazelo yohlobo lwedatha olubuyiselayo, uhlobo lwe-agumenti lukhonjiswa ngaphambi kwegama lempikiswano. Ngaphezu kwalokho, ukwenza lula ukuncozululwa kwe-IR, amagama ezinhlangano zomhlaba andulelwa uphawu @, futhi ngaphambi kwamagama endawo kukhona uphawu % (umsebenzi nawo uthathwa njengebhizinisi lomhlaba wonke).

Into eyodwa okufanele uyiqaphele ngale khodi ukuthi isinqumo sokumelela uhlobo lwe-Go int, engamelwa njengevelu engu-32-bit noma engu-64-bit, kuye ngohlanganisela kanye nethagethi yokuhlanganiswa, iyamukelwa lapho i-LLVM ikhiqiza ikhodi ye-IR. Lesi ngesinye sezizathu eziningi zokuthi ikhodi ye-LLVM IR ayizimele, njengoba abantu abaningi becabanga, inkundla izimele. Ikhodi enjalo, eyenzelwe inkundla eyodwa, ayikwazi ukumane ithathwe futhi ihlanganiswe kwenye ingxenyekazi (ngaphandle uma ukulungele ukuxazulula le nkinga. ngokuqapha okukhulu).

Elinye iphuzu elithakazelisayo okufanele liphawulwe ukuthi uhlobo i64 ayiyona inombolo esayiniwe: ayithathi hlangothi mayelana nokumela uphawu lwenombolo. Ngokuya ngomyalelo, ingamela izinombolo ezisayiniwe nezingasayiniwe. Endabeni yokumelwa komsebenzi wokwengeza, lokhu akunandaba, ngakho-ke akukho mehluko ekusebenzeni ngezinombolo ezisayiniwe noma ezingasayiniwe. Lapha ngithanda ukuqaphela ukuthi olimini luka-C, ukuchichima kwenombolo ephelele esayiniwe kuholela ekuziphatheni okungachazwanga, ngakho i-frontend ye-Clang yengeza ifulegi ekusebenzeni. nsw (akukho ukugoqa okusayiniwe), okutshela i-LLVM ukuthi ingacabanga ukuthi isengezo asichichichili.

Lokhu kungase kube kubalulekile ekuthuthukisweni okuthile. Isibonelo, ukwengeza amanani amabili i16 endaweni ye-32-bit (enerejista ye-32-bit) idinga, ngemva kokwengeza, umsebenzi wokunweba uphawu ukuze uhlale kububanzi i16. Ngenxa yalokhu, kuvame ukusebenza kahle kakhulu ukwenza imisebenzi ephelele ngokusekelwe kumasayizi erejista yomshini.

Okwenzeka ngokulandelayo ngale khodi ye-IR akusenantshisekelo ethile kithi manje. Ikhodi ithuthukisiwe (kodwa esimweni sesibonelo esilula njengesethu, akukho lutho oluthuthukisiwe) bese iguqulwa ibe ikhodi yomshini.

Isibonelo sesibili

Isibonelo esilandelayo esizobheka kuso sizoba inkimbinkimbi kancane. Okungukuthi, sikhuluma ngomsebenzi ohlanganisa ucezu lwamanani aphelele:

func sum(numbers []int) int {
    n := 0
    for i := 0; i < len(numbers); i++ {
        n += numbers[i]
    }
    return n
}

Le khodi iguqulela kukhodi elandelayo ye-Go 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

Lapha usungabona ezinye izakhiwo ezijwayelekile zokumela ikhodi efomini le-SSA. Mhlawumbe isici esisobala kakhulu sale khodi yiqiniso lokuthi ayikho imiyalo ehlelekile yokulawula ukugeleza. Ukulawula ukugeleza kwezibalo, kukhona ukweqa okunemibandela nokungenamibandela kuphela, futhi, uma sicabangela lo myalo njengomyalo wokulawula ukugeleza, umyalo wokubuyisela.

Eqinisweni, lapha ungakwazi ukunaka iqiniso lokuthi uhlelo aluhlukaniswanga ngamabhulokhi usebenzisa ama-curly braces (njengomndeni wakwaC wezilimi). Ihlukaniswe ngamalebula, okukhumbuza izilimi zokuhlanganisa, futhi yethulwe ngendlela yamabhulokhi ayisisekelo. Ku-SSA, amabhulokhi ayisisekelo achazwa njengokulandelana kwekhodi okuhambisanayo kuqala ngelebula futhi kugcine ngemiyalo eyisisekelo yokuqedela ibhulokhi, njengokuthi − return и jump.

Omunye umniningwane othakazelisayo wale khodi umelwe umyalo phi. Imiyalo ayijwayelekile futhi ingathatha isikhathi ukuyiqonda. khumbula, lokho I-SSA imfushane yokuthi I-Static Single Assignment. Lokhu ukumelwa okumaphakathi kwekhodi esetshenziswa abahlanganisi, lapho okuhlukile ngakunye kwabelwa inani kanye kuphela. Lokhu kuhle kakhulu ekuvezeni imisebenzi elula njengomsebenzi wethu myAddkuboniswe ngenhla, kodwa ayilungele imisebenzi eyinkimbinkimbi njengomsebenzi okuxoxwe ngawo kulesi sigaba sum. Ikakhulukazi, okuguquguqukayo kuyashintsha ngesikhathi sokwenziwa kweluphu i и n.

I-SSA yeqa umkhawulo wokwabela amanani aguquguqukayo kanye nokusebenzisa lokho okubizwa ngokuthi umyalo phi (igama layo lithathwe ezinhlamvwini zezinhlamvu zesiGreki). Iqiniso liwukuthi ukuze ukumelwa kwekhodi kwe-SSA kukhiqizwa ezilimini ezifana no-C, kufanele usebenzise amaqhinga athile. Umphumela wokubiza lo myalelo yinani lamanje lokuguquguquka (i noma n), futhi uhlu lwamabhulokhi ayisisekelo lusetshenziswa njengemingcele yalo. Ngokwesibonelo, cabangela lo myalo:

t0 = phi [entry: 0:int, for.body: t6] #n

Incazelo yalo imi kanje: uma ibhulokhi eyisisekelo yangaphambilini bekuyibhulokhi entry (ukufaka), bese t0 kuyinto engaguquki 0, futhi uma ibhulokhi eyisisekelo yangaphambili ibiyi for.body, khona-ke udinga ukuthatha inani t6 kusuka kule block. Konke lokhu kungase kubonakale kuyimfihlakalo, kodwa le nqubo yiyona eyenza i-SSA isebenze. Ngokombono womuntu, konke lokhu kwenza ikhodi ibe nzima ukuyiqonda, kodwa iqiniso lokuthi inani ngalinye labelwe kanye kuphela lenza ukulungiselelwa okuningi kube lula kakhulu.

Qaphela ukuthi uma ubhala i-compiler yakho, ngokuvamile ngeke kudingeke ubhekane nalolu hlobo lwezinto. Ngisho noClang akakhiqizi yonke le miyalo phi, isebenzisa umshini alloca (kufana nokusebenza neziguquguqukayo zendawo ezijwayelekile). Bese, lapho usebenzisa iphasi yokwenza kahle ye-LLVM ibizwa um2reg, iziyalezo alloca iguqulelwe kwifomu le-SSA. I-TinyGo, nokho, ithola okokufaka okuvela ku-Go SSA, okuthi, ngokufanelekile, isivele iguqulelwe kwifomu le-SSA.

Okunye okusha kocezu lwekhodi emaphakathi okucatshangelwayo ukuthi ukufinyelela ezicini zokusika ngenkomba kumelelwa ngendlela yokusebenza kokubala ikheli kanye nokusebenza kokususa ireferensi kwesikhombi esiwumphumela. Lapha ungabona ukwengezwa okuqondile kwama-constants kukhodi ye-IR (isibonelo - 1:int). Esibonelweni esinomsebenzi myAdd lokhu akuzange kusetshenziswe. Manje njengoba sesizikhiphe lezo zici endleleni, ake sibheke ukuthi le khodi iba yini uma iguqulelwa kufomu le-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
}

Lapha, njengakuqala, singabona isakhiwo esifanayo, esihlanganisa nezinye izakhiwo ze-syntactic. Isibonelo, ezicingweni phi amanani namalebula ashintshiwe. Nokho, kukhona okuthile lapha okufanele ukunakwa ngokukhethekile.

Okokuqala, lapha ungabona isiginesha yomsebenzi ehluke ngokuphelele. I-LLVM ayizisekeli izingcezu, futhi ngenxa yalokho, njengokuthuthukisa, i-TinyGo compiler ekhiqize le khodi emaphakathi yahlukanisa incazelo yalesi sakhiwo sedatha yaba izingxenye. Ingamela izingxenye ezintathu zocezu (ptr, len и cap) njengesakhiwo (isakhiwo), kodwa ukuwamela njengamabhizinisi amathathu ahlukene kuvumela ukulungiselelwa okuthile. Abanye abahlanganisi bangase bamele ucezu ngezinye izindlela, ngokuya ngezimiso zokushaya zemisebenzi yengxenyekazi eqondiwe.

Esinye isici esithakazelisayo sale khodi ukusetshenziswa komyalelo getelementptr (ivame ukufushaniswa njenge-GEP).

Lo myalelo usebenza nezikhombisi futhi usetshenziselwa ukuthola isikhombisi sesici socezu. Isibonelo, ake siyiqhathanise nekhodi elandelayo ebhalwe ngo-C:

int* sliceptr(int *ptr, int index) {
    return &ptr[index];
}

Noma nalokhu okulandelayo okulingana nalokhu:

int* sliceptr(int *ptr, int index) {
    return ptr + index;
}

Okubaluleke kakhulu lapha ukuthi imiyalelo getelementptr ayenzi imisebenzi yokuhlehlisa ireferensi. Imane ibala i-pointer entsha ngokusekelwe kule ekhona. Kungathathwa njengeziyalezo mul и add ezingeni lehadiwe. Ungafunda kabanzi mayelana nemiyalelo ye-GEP lapha.

Esinye isici esithakazelisayo sale khodi ephakathi ukusetshenziswa komyalelo icmp. Lona umyalo wenhloso evamile osetshenziselwa ukusebenzisa ukuqhathanisa okuphelele. Umphumela walo myalelo uhlale uyivelu yohlobo i1 - inani elinengqondo. Kulokhu, ukuqhathanisa kwenziwa kusetshenziswa igama elingukhiye slt (isayinwe ngaphansi kuka), njengoba siqhathanisa izinombolo ezimbili ebezimelelwe uhlobo int. Uma besiqhathanisa izinombolo ezimbili ezingasayiniwe, besizosebenzisa icmp, futhi igama elingukhiye elisetshenziswe ekuqhathaniseni kuzoba ult. Ukuqhathanisa izinombolo zamaphuzu antantayo, kusetshenziswa omunye umyalo, fcmp, esebenza ngendlela efanayo.

Imiphumela

Ngikholelwa ukuthi kulokhu kwaziswa ngihlanganise izici ezibaluleke kakhulu ze-LLVM IR. Yebo, kuningi okwengeziwe lapha. Ikakhulukazi, ukumelwa okumaphakathi kwekhodi kungase kuqukathe izichasiselo eziningi ezivumela amaphasi okuthuthukisa ukuthi acabangele izici ezithile zekhodi ezaziwa ngumdidiyeli ezingeke zivezwe ngenye indlela ku-IR. Ngokwesibonelo, leli ifulege inbounds Imiyalelo ye-GEP, noma amafulegi nsw и nuw, ezingafakwa emiyalweni add. Okufanayo kuya egameni elingukhiye private, okubonisa kusilungiseleli ukuthi umsebenzi esiwumakayo ngeke ukhonjwe ngaphandle kweyunithi yamanje yokuhlanganiswa. Lokhu kuvumela ukulungiselelwa okuningi okuthakazelisayo kwe-interprocedural njengokususa ama-agumenti angasetshenzisiwe.

Ungafunda kabanzi nge-LLVM ku imibhalo, ozobhekisela kukho kaningi lapho uthuthukisa i-LLVM-based compiler yakho. Lapha umhlahlandlela, ebheka ukuthuthukisa umdidiyeli wolimi olulula kakhulu. Yomibili le mithombo yolwazi izoba usizo kuwe lapho udala owakho umhlanganisi.

Bafundi abathandekayo! Ingabe usebenzisa i-LLVM?

I-LLVM ngokombono we-Go

Source: www.habr.com

Engeza amazwana