LLVM mai kahi hiʻohiʻona Go

He hana paʻakikī loa ka hoʻomohala ʻana i kahi mea hoʻopili. Akā, ʻoi aku ka maikaʻi, me ka hoʻomohala ʻana o nā papahana e like me LLVM, ua maʻalahi loa ka hoʻonā ʻana i kēia pilikia, e hiki ai i kahi mea polokalamu hoʻokahi ke hana i kahi ʻōlelo hou e kokoke ana i ka hana iā C. ʻO ka hana ʻana me LLVM paʻakikī i ka ʻoiaʻiʻo o kēia. Hōʻike ʻia ka ʻōnaehana e ka nui o nā code, i lako me nā palapala liʻiliʻi. I mea e ho'āʻo ai e hoʻoponopono i kēia hemahema, e hōʻike ana ka mea kākau o ka mea, ka unuhi a mākou e paʻi nei i kēia lā, i nā hiʻohiʻona o nā code i kākau ʻia ma Go a hōʻike i ke ʻano o ka unuhi mua ʻia ʻana i loko. Hele SSA, a laila ma LLVM IR me ka hoʻohana ʻana i ka compiler ʻO TinyGO. Ua hoʻoponopono iki ʻia ka code Go SSA a me LLVM IR no ka wehe ʻana i nā mea pili ʻole i nā wehewehe i hāʻawi ʻia ma aneʻi, i mea e maopopo ai nā wehewehe.

LLVM mai kahi hiʻohiʻona Go

Laʻana mua

ʻO ka hana mua aʻu e nānā ai ma ʻaneʻi he mīkini maʻalahi no ka hoʻohui ʻana i nā helu:

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

He mea maʻalahi kēia hana, a, ʻaʻohe mea hiki ke maʻalahi. Unuhi ia i ke code Go SSA penei:

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

Me kēia hōʻike, hoʻonoho ʻia nā ʻano ʻikepili o ka hana ma ka ʻākau a hiki ke nānā ʻole ʻia i ka nui o nā hihia.

Hiki i kēia hiʻohiʻona liʻiliʻi ke ʻike iā ʻoe i ke ʻano o kekahi ʻano o SSA. ʻO ia hoʻi, i ka hoʻololi ʻana i ke code i loko o ke ʻano SSA, ua wāwahi ʻia kēlā me kēia ʻōlelo i nā ʻāpana haʻahaʻa loa i haku ʻia. I kā mākou hihia, ke kauoha return a + b, ʻoiaʻiʻo, hōʻike i nā hana ʻelua: hoʻohui i ʻelua helu a hoʻihoʻi i ka hopena.

Eia kekahi, ma aneʻi hiki iā ʻoe ke ʻike i nā poloka kumu o ka papahana; ma kēia code aia hoʻokahi poloka - ka poloka komo. E kamaʻilio hou mākou e pili ana i nā poloka ma lalo nei.

Hoʻololi maʻalahi ke code Go SSA i LLVM IR:

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

ʻO ka mea āu e ʻike ai, ʻoiai ke hoʻohana ʻia nā ʻano syntactic ʻē aʻe ma aneʻi, ʻaʻole loli ke ʻano o ka hana. ʻOi aku ka ikaika o ka code IR LLVM ma mua o ke code Go SSA, e like me C. Eia, i ka hoʻolaha hana, aia ka wehewehe mua o ke ʻano ʻikepili i hoʻihoʻi ʻia, hōʻike ʻia ke ʻano hoʻopaʻapaʻa ma mua o ka inoa hoʻopaʻapaʻa. Eia kekahi, no ka hoʻomaʻamaʻa ʻana i ka parsing IR, ʻo nā inoa o nā hui honua ma mua o ka hōʻailona @, a ma mua o nā inoa kūloko he hōʻailona % (manaʻo ʻia kekahi hana he hui honua).

ʻO kahi mea e hoʻomaopopo ai e pili ana i kēia code ʻo ia ka hoʻoholo hoʻohālikelike ʻano Go int, hiki ke hōʻike ʻia ma ke ʻano he 32-bit a i ʻole 64-bit waiwai, ma muli o ka compiler a me ka pahuhopu o ka hoʻohui ʻana, ʻae ʻia i ka wā i hana ʻia ai ke code LLVM IR. ʻO kēia kekahi o nā kumu he nui ʻole ʻo LLVM IR code, e like me ka manaʻo o ka poʻe he nui, he kahua kūʻokoʻa. ʻO ia code, i hana ʻia no kahi kahua hoʻokahi, ʻaʻole hiki ke lawe wale ʻia a hōʻuluʻulu ʻia no kahi kahua ʻē aʻe (koe ke kūpono ʻoe no ka hoʻoponopono ʻana i kēia pilikia. me ka mālama loa).

ʻO kekahi mea hoihoi e hoʻomaopopo ʻia ʻo ia ke ʻano i64 ʻaʻole ia he integer i pūlima ʻia: kūʻokoʻa ia ma ke ʻano o ka hōʻike ʻana i ka hōʻailona o ka helu. Ma muli o ke aʻo ʻana, hiki iā ia ke hōʻike i nā helu i hoʻopaʻa ʻia a me nā helu ʻole. I ka hihia o ka hōʻike ʻana i ka hana hoʻohui, ʻaʻohe mea nui kēia, no laila ʻaʻohe ʻokoʻa i ka hana ʻana me nā helu i kau inoa ʻia a i ʻole i hoʻopaʻa ʻia. Maʻaneʻi, makemake wau e hoʻomaopopo i ka ʻōlelo C, ʻo ka hoʻonui ʻana i kahi ʻano helu helu i hoʻopaʻa ʻia e alakaʻi i kahi ʻano ʻike ʻole, no laila e hoʻohui ka Clang frontend i kahi hae i ka hana. nsw (ʻaʻole i hoʻopaʻa inoa ʻia), ka mea e haʻi iā LLVM hiki iā ia ke manaʻo ʻaʻole e kahe ka hoʻohui.

He mea koʻikoʻi paha kēia no kekahi mau koho. No ka laʻana, hoʻohui i ʻelua mau waiwai i16 ma kahi paepae 32-bit (me nā papa inoa 32-bit) pono, ma hope o ka hoʻohui ʻana, kahi hana hoʻonui hōʻailona i mea e noho ai i ka laulā. i16. Ma muli o kēia, ʻoi aku ka maikaʻi o ka hana ʻana i nā hana integer e pili ana i ka nui o ka hoʻopaʻa inoa mīkini.

ʻO ka mea e hiki mai ana me kēia code IR ʻaʻole ia he mea hoihoi loa iā mākou i kēia manawa. Hoʻopili ʻia ke code (akā ma ke ʻano o kahi hiʻohiʻona maʻalahi e like me kā mākou, ʻaʻohe mea i hoʻoponopono ʻia) a laila hoʻololi ʻia i code mīkini.

Laʻana lua

ʻO ka hiʻohiʻona aʻe a mākou e nānā ai he mea paʻakikī iki. ʻO ia, ke kamaʻilio nei mākou e pili ana i kahi hana e hōʻuluʻulu i kahi ʻāpana o nā integer:

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

Hoʻololi kēia code i kēia code 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

Ma ʻaneʻi hiki iā ʻoe ke ʻike hou aku i nā hana maʻamau no ka hōʻike ʻana i ke code ma ke ʻano SSA. ʻO ka hiʻohiʻona maopopo loa paha o kēia code ʻo ia ka ʻoiaʻiʻo ʻaʻohe ʻano kauoha hoʻomalu kahe. No ka hoʻomaluʻana i ka holoʻana o ka heluʻana, aia wale nō ke kūlana a me ka leleʻole, a, inā mākou e noʻonoʻo i kēia kauoha ma keʻano he kauoha e mālama i ke kahe, he kauoha hoʻihoʻi.

ʻO kaʻoiaʻiʻo, hiki iā ʻoe ke hoʻolohe i ka ʻoiaʻiʻo ʻaʻole i māhele ʻia ka papahana i nā poloka me ka hoʻohana ʻana i nā braces curly (e like me ka ʻohana C o nā ʻōlelo). Hoʻokaʻawale ʻia e nā lepili, hoʻomanaʻo i nā ʻōlelo hui, a hōʻike ʻia ma ke ʻano o nā poloka kumu. Ma SSA, ua wehewehe ʻia nā poloka kumu ma ke ʻano he mau kaʻina pili o ke code e hoʻomaka ana me kahi lepili a me ka hoʻopau ʻana me nā ʻōlelo aʻoaʻo hoʻopau kumu, e like me − return и jump.

Hōʻike ʻia kekahi kikoʻī hoihoi o kēia code e ke aʻo phi. ʻAʻole maʻamau nā ʻōlelo aʻo a hiki ke lōʻihi ka manawa e hoʻomaopopo ai. e hoomanao, i kela S.S.A. he pōkole no Static Single Assignment. He hōʻike waena kēia o ke code i hoʻohana ʻia e nā mea hōʻuluʻulu, kahi e hāʻawi ʻia ai kēlā me kēia ʻano i ka waiwai i hoʻokahi wale nō. He mea maikaʻi kēia no ka hōʻike ʻana i nā hana maʻalahi e like me kā mākou hana myAddi hōʻike ʻia ma luna, akā ʻaʻole kūpono ia no nā hana paʻakikī e like me ka hana i kūkākūkā ʻia ma kēia ʻāpana sum. Ma keʻano kūikawā, hoʻololi nā mea hoʻololi i ka wā o ka hoʻokō ʻana i ka loop i и n.

Hoʻokaʻawale ʻo SSA i ka palena o ka hāʻawi ʻana i nā waiwai hoʻololi i ka hoʻohana ʻana i kahi ʻōlelo aʻo phi (Ua lawe ʻia kona inoa mai ka huaʻōlelo Helene). ʻO ka mea ʻoiaʻiʻo, i mea e hana ʻia ai ka hōʻike SSA o ke code no nā ʻōlelo e like me C, pono ʻoe e hoʻohana i kekahi mau hoʻopunipuni. ʻO ka hopena o ke kāhea ʻana i kēia ʻōlelo aʻo ʻo ia ka waiwai o kēia manawa o ka hoʻololi (i ai ole ia, n), a hoʻohana ʻia kahi papa inoa o nā poloka kumu e like me kāna mau ʻāpana. No ka laʻana, e noʻonoʻo i kēia ʻōlelo aʻoaʻo:

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

Penei kona manaʻo: inā he poloka ka poloka kumu mua entry (hookomo), alaila t0 he mea mau 0, a inā ʻo ka poloka kumu mua for.body, a laila pono ʻoe e lawe i ka waiwai t6 mai keia poloka. He mea pohihihi paha kēia, akā ʻo kēia ka mea e hana ai ka SSA. Mai kahi hiʻohiʻona kanaka, paʻakikī kēia i ka hoʻomaopopo ʻana i ke code, akā ʻo ka ʻoiaʻiʻo o ka hāʻawi ʻia ʻana o kēlā me kēia waiwai i hoʻokahi wale nō e maʻalahi ai nā loiloi he nui.

E hoʻomaopopo inā ʻoe e kākau i kāu mea hoʻopili ponoʻī, ʻaʻole pono ʻoe e hana i kēia ʻano mea. ʻAʻole hana ʻo Clang i kēia mau ʻōlelo aʻoaʻo phi, hoʻohana ia i kahi mīkini alloca (e like me ka hana ʻana me nā mea hoʻololi kūloko maʻamau). A laila, i ka wā e holo ana i kahi LLVM optimization pass i kapa ʻia mem2reg, kuhikuhi alloca hoʻololi ʻia i ka palapala SSA. Loaʻa naʻe ʻo TinyGo i ka hoʻokomo ʻana mai Go SSA, ka mea maʻalahi, ua hoʻololi ʻia i ka palapala SSA.

ʻO kekahi mea hou o ka ʻāpana o ka code intermediate e noʻonoʻo ʻia nei, ʻo ke komo ʻana i nā mea ʻāpana e ka index i hōʻike ʻia ma ke ʻano o kahi hana o ka helu ʻana i ka helu wahi a me kahi hana o ka dereferencing i ka pointer hopena. Maanei hiki iā ʻoe ke ʻike i ka hoʻohui pololei o nā mea mau i ka code IR (no ka laʻana - 1:int). I ka laʻana me ka hana myAdd ʻaʻole i hoʻohana ʻia kēia. I kēia manawa ua loaʻa iā mākou kēlā mau hiʻohiʻona ma waho o ke ala, e nānā i ke ʻano o kēia code i ka wā e hoʻohuli ʻia ai i ke ʻano 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
}

Maʻaneʻi, e like me ka wā ma mua, hiki iā mākou ke ʻike i ke ʻano like, e komo pū ana me nā hale syntactic ʻē aʻe. Eia kekahi laʻana, ma nā kelepona phi ua hoʻololi ʻia nā waiwai a me nā lepili. Eia naʻe, aia kekahi mea maʻaneʻi e kūpono i ka nānā kūikawā.

No ka hoʻomaka ʻana, ma aneʻi hiki iā ʻoe ke ʻike i kahi pūlima hana ʻokoʻa loa. ʻAʻole kākoʻo ʻo LLVM i nā ʻāpana, a ʻo ka hopena, ma ke ʻano he optimization, ʻo ka TinyGo compiler nāna i hoʻokumu i kēia code waena i hoʻokaʻawale i ka wehewehe ʻana o kēia ʻano ʻikepili i mau ʻāpana. Hiki iā ia ke hōʻike i ʻekolu ʻāpana ʻāpana (ptr, len и cap) ma ke ʻano he ʻano (struct), akā ʻo ka hōʻike ʻana iā lākou ma ke ʻano he ʻekolu hui kaʻawale e hiki ai i kekahi mau koho. Hiki i nā mea hōʻuluʻulu ʻē aʻe ke hōʻike i ka ʻāpana ma nā ʻano ʻē aʻe, e hilinaʻi ana i nā kaʻina kelepona o nā hana o ka platform target.

ʻO kekahi hiʻohiʻona hoihoi o kēia code ka hoʻohana ʻana i ke aʻo getelementptr (hoʻopau pinepine ʻia ʻo GEP).

Hana kēia ʻōlelo aʻo me nā kuhikuhi a hoʻohana ʻia no ka loaʻa ʻana o kahi kuhikuhi i kahi mea ʻāpana. No ka laʻana, e hoʻohālikelike kākou me kēia code i kākau ʻia ma C:

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

A i ʻole me kēia mea like me kēia:

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

ʻO ka mea nui ma ʻaneʻi ʻo ia nā kuhikuhi getelementptr ʻaʻole ia e hana i nā hana dereferencing. Heluhelu wale ʻo ia i kahi kuhikuhi hou e pili ana i ka mea i loaʻa. Hiki ke lawe ʻia ma ke ʻano he kuhikuhi mul и add ma ka pae lako. Hiki iā ʻoe ke heluhelu hou aku e pili ana i nā kuhikuhi GEP maanei.

ʻO kekahi hiʻohiʻona hoihoi o kēia code waena ka hoʻohana ʻana i ke aʻo icmp. He aʻo kumu nui kēia i hoʻohana ʻia e hoʻokō i nā hoʻohālikelike integer. ʻO ka hopena o kēia aʻo ʻana he waiwai mau o ke ʻano i1 — waiwai kūpono. I kēia hihia, hoʻohālikelike ʻia me ka hoʻohana ʻana i ka huaʻōlelo slt (kakau ʻia ma lalo o), ʻoiai ke hoʻohālikelike nei mākou i ʻelua mau helu i hōʻike mua ʻia e ke ʻano int. Inā mākou e hoʻohālikelike i ʻelua mau helu helu ʻole, a laila e hoʻohana mākou icmp, a ʻo ka huaʻōlelo i hoʻohana ʻia ma ka hoʻohālikelike ʻana ult. No ka hoʻohālikelike ʻana i nā helu lana, hoʻohana ʻia kekahi ʻōlelo aʻo, fcmp, e hana like ana.

Nā hopena

Ke manaʻoʻiʻo nei au i loko o kēia mea ua uhi au i nā hiʻohiʻona koʻikoʻi o LLVM IR. ʻOiaʻiʻo, nui nā mea hou aku ma ʻaneʻi. ʻO ka mea nui, hiki i ka hōʻike waena o ke code ke loaʻa i nā annotation he nui e hiki ai i ka optimization pass ke noʻonoʻo i kekahi mau hiʻohiʻona o ke code i ʻike ʻia e ka mea hōʻuluʻulu ʻaʻole hiki ke hōʻike ʻia ma IR. Eia kekahi laʻana, he hae kēia inbounds Nā kuhikuhi GEP, a i ʻole nā ​​hae nsw и nuw, hiki ke hoʻohui i nā kuhikuhi add. Pela no ka huaolelo private, e hōʻike ana i ka optimizer ʻaʻole e kuhikuhi ʻia ka hana āna i hōʻailona ai ma waho o ka pūʻulu hōʻuluʻulu o kēia manawa. Hāʻawi kēia i ka nui o nā loiloi interprocedural hoihoi e like me ka hoʻopau ʻana i nā hoʻopaʻapaʻa i hoʻohana ʻole ʻia.

Hiki iā ʻoe ke heluhelu hou aʻe e pili ana iā LLVM ma palapala, ka mea āu e kuhikuhi pinepine ai i ka wā e hoʻomohala ai i kāu mea hoʻopili LLVM. Eia alakaʻi, e nānā ana i ka hoʻomohala ʻana i kahi mea hōʻuluʻulu no kahi ʻōlelo maʻalahi loa. He mea pono kēia mau kumu ʻike ʻelua iā ʻoe i ka hana ʻana i kāu mea hoʻopili ponoʻī.

E nā mea heluhelu aloha! Ke hoʻohana nei ʻoe iā LLVM?

LLVM mai kahi hiʻohiʻona Go

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka