LLVM amin'ny fomba fijery Go

Asa sarotra tokoa ny famolavolana compiler. Saingy, soa ihany, miaraka amin'ny fivoaran'ny tetikasa toy ny LLVM, ny vahaolana amin'ity olana ity dia tena tsotra, izay mamela na dia programa iray monja aza hamorona fiteny vaovao izay manakaiky ny fampisehoana C. Ny fiaraha-miasa amin'ny LLVM dia sarotra noho ny zava-misy fa ity Ny rafitra dia aseho amin'ny kaody be dia be, miaraka amina antontan-taratasy kely. Mba hanandramana hanitsy izany lesoka izany, ny mpanoratra ny fitaovana, ny fandikana izay avoakantsika anio, dia hampiseho ohatra ny fehezan-dalàna voasoratra ao amin'ny Go ary mampiseho ny fomba nandikana azy ireo voalohany Mandehana SSA, ary avy eo amin'ny LLVM IR mampiasa ny compiler tinyGO. Ny kaody Go SSA sy LLVM IR dia nasiam-panovàna kely mba hanesorana ireo zavatra tsy mifanaraka amin'ny fanazavana omena eto, mba hahatonga ny fanazavana ho azo kokoa.

LLVM amin'ny fomba fijery Go

Ohatra voalohany

Ny asa voalohany hojereko eto dia mekanika tsotra hanampiana isa:

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

Ity fiasa ity dia tena tsotra, ary, angamba, tsy misy na inona na inona mety ho tsotra kokoa. Adika amin'ity kaody Go SSA manaraka ity:

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

Amin'ity fomba fijery ity dia apetraka eo amin'ny ilany havanana ny soso-kevitra karazana data ary azo tsinontsinoavina amin'ny ankamaroan'ny tranga.

Ity ohatra kely ity dia efa ahafahanao mahita ny maha-zava-dehibe ny lafiny iray amin'ny SSA. Izany hoe, rehefa mamadika ny kaody ho endrika SSA, ny fitenenana tsirairay dia rava ao amin'ny ampahany fototra indrindra misy azy. Aminay, ny baiko return a + b, raha ny marina, dia maneho asa roa: manampy isa roa ary mamerina ny valiny.

Ho fanampin'izany, eto ianao dia afaka mahita ireo blocs fototra amin'ny programa; amin'ity code ity dia tsy misy afa-tsy sakana iray - ny sakana fidirana. Hiresaka bebe kokoa momba ny sakana eto ambany isika.

Ny kaody Go SSA dia niova fo ho LLVM IR:

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

Ny zavatra hitanao dia na dia samy hafa aza ny rafitra syntactic ampiasaina eto, ny firafitry ny asa dia tsy miova amin'ny ankapobeny. Ny kaody LLVM IR dia matanjaka kokoa noho ny kaody Go SSA, mitovy amin'ny C. Eto, ao amin'ny fanambarana momba ny asa, voalohany misy famaritana ny karazana data averina, ny karazana argument dia aseho alohan'ny anaran'ny argument. Ho fanampin'izany, mba hanatsorana ny fanaparitahana IR, ny anaran'ny sampana manerantany dia ialohavan'ny marika @, ary alohan'ny anarana eo an-toerana dia misy marika % (heverina ho sampan-draharaha maneran-tany ihany koa ny asa iray).

Ny zavatra iray tokony homarihina momba ity kaody ity dia ny fanapahan-kevitry ny karazana fanehoana an'i Go int, izay azo aseho amin'ny sanda 32-bit na 64-bit, miankina amin'ny compiler sy ny tanjon'ny fanangonana, dia ekena rehefa mamorona ny code IR ny LLVM. Io no iray amin'ireo antony maro mahatonga ny LLVM IR code tsy mahaleo tena, araka ny fiheveran'ny olona maro. Ny kaody toy izany, noforonina ho an'ny sehatra iray, dia tsy azo alaina fotsiny ary atambatra ho an'ny sehatra hafa (raha tsy hoe mety amin'ny famahana ity olana ity ianao am-pitandremana fatratra).

Ny teboka iray hafa mahaliana dia ny hoe ny karazana i64 tsy integer voasonia: tsy miandany amin'ny fanehoana ny mariky ny isa. Miankina amin'ny toromarika, afaka maneho isa voasonia sy tsy misy sonia izy io. Raha ny fanehoana ny asa fanampiny dia tsy maninona izany, noho izany dia tsy misy fahasamihafana amin'ny fiasana amin'ny isa voasonia na tsy misy sonia. Eto aho dia te-hanamarika fa amin'ny fiteny C, ny fihoaram-pefy integer voasonia dia mitarika amin'ny fitondran-tena tsy voafaritra, ka ny Clang frontend dia manampy saina amin'ny asa. nsw (tsy misy fonosana misy sonia), izay milaza amin'ny LLVM fa mety hihevitra fa tsy mihoatra ny fanampiny.

Mety ho zava-dehibe amin'ny fanatsarana sasany izany. Ohatra, manampy soatoavina roa i16 amin'ny sehatra 32-bit (miaraka amin'ny rejisitra 32-bit) dia mitaky, aorian'ny fanampin'izany, ny asa fanitarana famantarana mba hijanonana amin'ny elanelana. i16. Noho izany, matetika dia mahomby kokoa ny manao asa integer mifototra amin'ny haben'ny rejisitra milina.

Ny zava-mitranga manaraka amin'ity kaody IR ity dia tsy mahaliana antsika manokana ankehitriny. Ny kaody dia optimized (fa raha ohatra tsotra tahaka ny antsika dia tsy misy azo atao tsara) ary avy eo avadika ho code machine.

Ohatra faharoa

Ny ohatra manaraka hojerentsika dia ho sarotra kokoa. Izany hoe, miresaka momba ny fiasa iray izay mamintina ampahany amin'ny integer isika:

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

Ity kaody ity dia mivadika ho kaody Go SSA manaraka:

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

Eto ianao dia afaka mahita fanorenana hafa mahazatra amin'ny fanehoana kaody amin'ny endrika SSA. Angamba ny endri-javatra miharihary indrindra amin'ity kaody ity dia ny tsy fisian'ny baiko mifehy ny fikorianan'ny rafitra. Mba hifehezana ny fikorianan'ny kajikajy dia misy ihany ny fitsambikinana misy fepetra sy tsy misy fepetra, ary, raha raisina ho toy ny baiko hifehezana ny fikorianan'ny rivotra io baiko io, dia baiko miverina.

Raha ny marina, eto ianao dia afaka mihaino ny zava-misy fa ny fandaharana dia tsy mizara ho blocs mampiasa olioly braces (toy ny ao amin'ny fianakaviana C ny fiteny). Izy io dia zaraina amin'ny etikety, mampahatsiahy ny fiteny fivoriambe, ary aseho amin'ny endrika blocs fototra. Ao amin'ny SSA, ny blocs fototra dia faritana ho filaharan'ny kaody mifamatotra manomboka amin'ny marika ary mifarana amin'ny toromarika famenoana ny sakana fototra, toy ny − return и jump.

Ny antsipiriany hafa mahaliana amin'ity code ity dia asehon'ny torolàlana phi. Tsy mahazatra ny torolalana ary mety mila fotoana kely vao azony. tadidio fa S.S.A. dia fanafohezana ny Assignment Single Static. Izy io dia fanehoana manelanelana ny kaody ampiasain'ny mpanangom-bokatra, izay anomezana sanda indray mandeha monja ny fari-piainana tsirairay. Tena tsara izany amin'ny fanehoana fiasa tsotra toy ny fiasantsika myAddaseho etsy ambony, fa tsy mety amin'ny asa sarotra kokoa toy ny asa resahina ato amin'ity fizarana ity sum. Indrindra indrindra, miova ny variables mandritra ny fanatanterahana ny loop i и n.

SSA dia mandingana ny famerana amin'ny fanomezana sanda miovaova indray mandeha amin'ny fampiasana ilay antsoina hoe fampianarana phi (nalaina avy amin’ny abidy grika ny anarany). Ny zava-misy dia mba hamoronana ny kaody SSA ho an'ny fiteny toa an'i C, dia tsy maintsy mampiasa fika sasany ianao. Ny vokatry ny fiantsoana an'io torolàlana io dia ny sandan'ny variable ankehitriny (i na n), ary lisitry ny sakana fototra no ampiasaina ho masontsivana. Diniho, ohatra, ity torolalana ity:

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

Toy izao ny heviny: raha ny bloc fototra teo aloha dia bloc entry (fampidirana), avy eo t0 dia tsy miova 0, ary raha ny sakana fototra teo aloha dia for.body, dia mila maka ny sandany ianao t6 avy amin'ity sakana ity. Mety ho toa mistery daholo izany rehetra izany, saingy io mekanika io no mahatonga ny SSA miasa. Amin'ny fomba fijerin'olombelona, ​​izany rehetra izany dia mahatonga ny kaody ho sarotra takarina, fa ny zava-misy fa ny sanda tsirairay dia omena indray mandeha ihany no mahatonga ny fanatsarana maro ho mora kokoa.

Mariho fa raha manoratra ny compiler anao manokana ianao dia matetika tsy mila miatrika zavatra toy izany. Na i Clang aza dia tsy mamoaka ireo torolalana rehetra ireo phi, mampiasa mekanika izy io alloca (mitovitovy amin'ny fiasana amin'ny fari-piainana mahazatra eo an-toerana izany). Avy eo, rehefa mihazakazaka LLVM optimization pass antsoina mem2reg, toromarika alloca niova ho endrika SSA. Na izany aza, i TinyGo dia mahazo fidirana avy amin'ny Go SSA, izay, mety, dia efa niova ho endrika SSA.

Fanavaozana iray hafa amin'ny sombin-kaody mpanelanelana dinihina dia ny fidirana amin'ireo singa amin'ny alàlan'ny fanondroana dia aseho amin'ny endrika fiasan'ny kajy ny adiresy sy ny fiasan'ny dereferencing ny tondro vokatra. Eto ianao dia afaka mahita ny fampidirana mivantana ny constants amin'ny code IR (ohatra - 1:int). Ao amin'ny ohatra miaraka amin'ny function myAdd tsy nampiasaina io. Ankehitriny rehefa afaka ireo endri-javatra ireo isika, andao hojerentsika hoe inona no lasa kaody io rehefa niova ho endrika 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
}

Eto, toy ny teo aloha, dia afaka mahita rafitra mitovy, izay ahitana rafitra syntactic hafa. Ohatra, amin'ny antso phi ny soatoavina sy ny mari-pamantarana nivadika. Misy zavatra tokony hojerena manokana anefa eto.

Hanombohana, eto ianao dia afaka mahita sonia fiasa hafa tanteraka. Ny LLVM dia tsy manohana silaka, ary vokatr'izany, ho fanatsarana, ny compiler TinyGo izay namorona ity kaody mpanelanelana ity dia nizara ny famaritana ity firafitry ny data ity ho ampahany. Izy io dia afaka maneho singa telo (ptr, len и cap) amin'ny maha-rafitra (struct), fa ny fanehoana azy ireo ho singa telo misaraka dia mamela ny fanatsarana sasany. Ny mpanangom-bokatra hafa dia mety maneho ilay silaka amin'ny fomba hafa, miankina amin'ny fivoriam-piantsoana amin'ny asan'ny sehatra kendrena.

Ny endri-javatra mahaliana iray hafa amin'ity code ity dia ny fampiasana ny fampianarana getelementptr (matetika nohafohezina hoe GEP).

Ity torolalana ity dia miasa miaraka amin'ny tondro ary ampiasaina hahazoana tondro ho an'ny singa iray. Ohatra, andeha hampitaha azy amin'ity code manaraka ity voasoratra ao amin'ny C:

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

Na miaraka amin'ny mitovy amin'ity manaraka ity:

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

Ny zava-dehibe indrindra eto dia ny toromarika getelementptr tsy manao asa dereferencing. Kajy tondro vaovao mifototra amin'ny efa misy fotsiny izy io. Azo raisina ho toromarika izany mul и add amin'ny haavon'ny fitaovana. Afaka mamaky bebe kokoa momba ny torolàlana GEP ianao eto.

Ny endri-javatra iray hafa mahaliana amin'ity code intermediate ity dia ny fampiasana ny fampianarana icmp. Ity dia torolàlana tanjona ankapobeny ampiasaina amin'ny fampiharana ny fampitahana integer. Ny vokatr'ity fampianarana ity dia sanda misy karazana foana i1 — sanda lojika. Amin'ity tranga ity, ny fampitahana dia atao amin'ny fampiasana ny teny fototra slt (voasonia latsaky ny), satria mampitaha isa roa nasehon'ilay karazana teo aloha izahay int. Raha mampitaha integer roa tsy misy sonia isika dia hampiasa icmp, ary ny teny fototra ampiasaina amin'ny fampitahana dia ny ult. Mba hampitahana ny isa mitsingevana dia misy toromarika hafa ampiasaina, fcmp, izay miasa amin'ny fomba mitovy.

vokatra

Mino aho fa ato amin'ity fitaovana ity no nandrakofana ireo endri-javatra manan-danja indrindra amin'ny LLVM IR. Mazava ho azy fa mbola betsaka kokoa eto. Indrindra indrindra, ny fanehoana mpanelanelana amin'ny kaody dia mety ahitana fanamarihana maro izay mamela ny optimization pass mba handinika ny endri-javatra sasany amin'ny code fantatry ny compiler izay tsy azo aseho amin'ny IR. Ohatra, ity dia saina inbounds Torolàlana GEP, na saina nsw и nuw, izay azo ampiana amin'ny torolalana add. Toy izany koa ny teny fototra private, izay manondro amin'ny optimizer fa ny fiasa voamarika dia tsy ho voatondro avy any ivelan'ny vondrona fanangonana ankehitriny. Izany dia ahafahan'ny optimization interprocedural mahaliana maro toy ny fanafoanana ny tohan-kevitra tsy ampiasaina.

Azonao atao ny mamaky bebe kokoa momba ny LLVM ao tahirin-kevitra, izay horesahinao matetika rehefa mamorona compiler mifototra amin'ny LLVM anao manokana. Eto mpitarika, izay mijery ny famolavolana compiler ho an'ny fiteny tena tsotra. Ireo loharanom-baovao roa ireo dia hahasoa anao rehefa mamorona compiler anao manokana.

Ry mpamaky malala! Mampiasa LLVM ve ianao?

LLVM amin'ny fomba fijery Go

Source: www.habr.com

Add a comment