LLVM los ntawm ib qho kev xav mus

Tsim ib tug compiler yog ib txoj hauj lwm nyuaj heev. Tab sis, hmoov zoo, nrog rau kev txhim kho cov haujlwm zoo li LLVM, kev daws teeb meem rau qhov teeb meem no yooj yim heev, uas tso cai rau txawm tias ib tus programmer los tsim cov lus tshiab uas nyob ze rau kev ua haujlwm C. Ua haujlwm nrog LLVM yog qhov nyuaj los ntawm qhov tseeb tias qhov no. system yog sawv cev los ntawm ib tug loj npaum li cas ntawm code, nruab nrog me me cov ntaub ntawv. Yuav kom sim kho qhov tsis txaus no, tus kws sau cov khoom, cov lus txhais uas peb tab tom tshaj tawm hnub no, yuav los ua piv txwv ntawm cov lej sau hauv Go thiab qhia tias lawv thawj zaug txhais li cas. Mus rau SSA, thiab tom qab ntawd hauv LLVM IR siv lub compiler txia GO. Go SSA thiab LLVM IR code tau raug kho me ntsis kom tshem tawm yam tsis cuam tshuam rau cov lus piav qhia ntawm no, txhawm rau ua kom cov lus piav qhia nkag siab ntau dua.

LLVM los ntawm ib qho kev xav mus

Thawj qhov piv txwv

Thawj qhov haujlwm kuv yuav saib ntawm no yog ib qho yooj yim mechanism rau ntxiv cov lej:

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

Qhov kev ua haujlwm no yooj yim heev, thiab, tej zaum, tsis muaj dab tsi yuav yooj yim dua. Nws txhais rau hauv Go SSA code hauv qab no:

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

Nrog rau qhov kev pom no, kev ua haujlwm cov ntaub ntawv hom lus qhia tau muab tso rau ntawm sab xis thiab tuaj yeem tsis quav ntsej rau feem ntau.

Qhov piv txwv me me no twb tso cai rau koj pom qhov tseem ceeb ntawm ib qho ntawm SSA. Namely, thaum hloov cov cai rau hauv SSA daim ntawv, txhua qhov kev qhia tau tawg mus rau hauv feem ntau ntawm cov ntsiab lus uas nws tau tsim. Hauv peb cov ntaub ntawv, cov lus txib return a + b, qhov tseeb, sawv cev rau ob txoj haujlwm: ntxiv ob tus lej thiab rov qab cov txiaj ntsig.

Tsis tas li ntawd, ntawm no koj tuaj yeem pom cov blocks yooj yim ntawm qhov kev zov me nyuam; hauv qhov chaws no tsuas muaj ib qho thaiv - qhov nkag nkag. Peb mam li tham ntxiv txog blocks hauv qab no.

Go SSA code yooj yim hloov mus rau LLVM IR:

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

Qhov koj tuaj yeem pom yog tias txawm tias cov qauv sib txawv sib txawv siv ntawm no, cov qauv ntawm kev ua haujlwm yog qhov tsis hloov pauv. Lub LLVM IR code yog me ntsis muaj zog dua Go SSA code, zoo ib yam li C. Ntawm no, hauv kev tshaj tawm ua haujlwm, ua ntej muaj cov lus piav qhia ntawm cov ntaub ntawv nws rov qab, hom kev sib cav yog qhia ua ntej lub npe sib cav. Tsis tas li ntawd, txhawm rau ua kom yooj yim IR parsing, cov npe ntawm cov koom haum thoob ntiaj teb yog ua ntej los ntawm lub cim @, thiab ua ntej cov npe hauv zos muaj ib lub cim % (ib txoj haujlwm tseem suav hais tias yog lub koom haum thoob ntiaj teb).

Ib yam uas yuav tsum nco ntsoov txog cov cai no yog qhov Go hom kev txiav txim siab sawv cev int, uas tuaj yeem sawv cev raws li tus nqi 32-ntsis lossis 64-ntsis, nyob ntawm qhov muab tso ua ke thiab lub hom phiaj ntawm kev muab tso ua ke, tau txais thaum LLVM tsim cov IR code. Qhov no yog ib qho ntawm ntau qhov laj thawj uas LLVM IR code tsis yog, raws li ntau tus neeg xav, platform ywj siab. Xws li cov cai, tsim rau ib lub platform, tsis tuaj yeem tsuas yog muab thiab muab tso ua ke rau lwm lub platform (tshwj tsis yog koj tsim nyog los daws qhov teeb meem no nrog kev saib xyuas hnyav).

Lwm qhov nthuav qhia tsim nyog sau cia yog tias hom i64 tsis yog tus lej kos npe: nws yog nruab nrab ntawm kev sawv cev ntawm tus lej. Nyob ntawm cov lus qhia, nws tuaj yeem sawv cev rau ob tus lej kos npe thiab tsis tau kos npe. Nyob rau hauv cov ntaub ntawv ntawm tus sawv cev ntawm kev ua hauj lwm ntxiv, qhov no tsis muaj teeb meem, yog li tsis muaj qhov sib txawv ntawm kev ua haujlwm nrog tus lej kos npe lossis tsis tau kos npe. Ntawm no kuv xav kom nco ntsoov tias nyob rau hauv C hom lus, overflowing ib tug kos npe integer variable ua rau undefined tus cwj pwm, yog li Clang frontend ntxiv ib tug chij rau lub lag luam. nsw (tsis muaj kos npe qhwv), uas qhia LLVM tias nws tuaj yeem xav tias qhov sib ntxiv tsis dhau.

Qhov no yuav yog qhov tseem ceeb rau qee qhov kev ua kom zoo. Piv txwv li, ntxiv ob qhov txiaj ntsig i16 ntawm 32-ntsis platform (nrog 32-ntsis sau npe) xav tau, tom qab ntxiv, kos npe nthuav dav ua haujlwm kom nyob twj ywm hauv ntau yam i16. Vim tias qhov no, nws feem ntau ua haujlwm tau zoo dua los ua cov haujlwm ua lej raws li lub tshuab sau npe ntau thiab tsawg.

Dab tsi tshwm sim tom ntej nrog IR code no tsis yog qhov tshwj xeeb rau peb tam sim no. Cov code yog optimized (tab sis nyob rau hauv cov ntaub ntawv ntawm ib tug yooj yim piv txwv li peb li, tsis muaj dab tsi yog optimized) thiab ces hloov dua siab tshiab rau hauv tshuab code.

Piv txwv thib ob

Cov piv txwv tom ntej peb yuav saib yuav nyuaj me ntsis. Namely, peb tab tom tham txog ib qho kev ua haujlwm uas suav cov lej ntawm cov lej:

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

Cov lej no hloov mus rau Go SSA code hauv qab no:

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

Ntawm no koj tuaj yeem pom ntau qhov kev tsim qauv tsim rau sawv cev rau hauv daim ntawv SSA. Tej zaum qhov pom tseeb tshaj plaws ntawm cov cai no yog qhov tseeb tias tsis muaj cov txheej txheem khiav tswj cov lus txib. Txhawm rau tswj kev khiav ntawm kev suav, tsuas yog muaj xwm txheej thiab tsis muaj kev hloov pauv, thiab, yog tias peb xav txog cov lus txib no raws li cov lus txib los tswj cov ntws, rov qab hais kom ua.

Qhov tseeb, ntawm no koj tuaj yeem xyuam xim rau qhov tseeb tias qhov kev zov me nyuam tsis muab faib ua cov blocks siv curly braces (raws li hauv C tsev neeg ntawm hom lus). Nws muab faib los ntawm cov ntawv sau, nco txog cov lus sib dhos, thiab nthuav tawm hauv daim ntawv ntawm cov blocks yooj yim. Hauv SSA, cov blocks yooj yim txhais tau tias yog cov kab sib txuas sib txuas ntawm cov lej pib nrog daim ntawv lo thiab xaus nrog cov lus qhia ua tiav kev thaiv, xws li - return ΠΈ jump.

Lwm qhov nthuav dav ntawm cov cai no yog sawv cev los ntawm cov lus qhia phi. Cov lus qhia txawv txawv heev thiab yuav siv sij hawm qee lub sij hawm los nkag siab. nco, tias SSA luv luv rau Static Single Assignment. Qhov no yog ib qho kev sawv cev nruab nrab ntawm cov cai siv los ntawm cov neeg sau ntawv, uas txhua qhov sib txawv tau muab tus nqi ib zaug xwb. Qhov no yog qhov zoo rau kev nthuav qhia cov haujlwm yooj yim xws li peb txoj haujlwm myAddqhia saum toj no, tab sis tsis haum rau ntau txoj haujlwm nyuaj xws li kev ua haujlwm tau tham hauv ntu no sum. Hauv tshwj xeeb, qhov hloov pauv hloov thaum lub sijhawm ua haujlwm ntawm lub voj i ΠΈ n.

SSA hla qhov kev txwv ntawm kev muab cov txiaj ntsig sib txawv ib zaug siv qhov kev qhia hu ua phi (nws lub npe yog muab los ntawm cov tsiaj ntawv Greek). Qhov tseeb yog tias nyob rau hauv kev txiav txim rau SSA tus sawv cev ntawm code yuav tsum tau generated rau cov lus zoo li C, koj yuav tsum mus rau ib co tricks. Qhov tshwm sim ntawm kev hu cov lus qhia no yog tus nqi tam sim no ntawm qhov sib txawv (i los yog n), thiab ib daim ntawv teev cov blocks yooj yim yog siv raws li nws cov kev txwv. Piv txwv li, xav txog cov lus qhia no:

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

Nws lub ntsiab lus yog raws li nram no: yog hais tias yav dhau los qhov yooj yim block yog ib qho thaiv entry (input), ces t0 yog qhov tsis tu ncua 0, thiab yog hais tias yav dhau los qhov yooj yim thaiv yog for.body, ces koj yuav tsum coj tus nqi t6 los ntawm qhov thaiv no. Qhov no tej zaum yuav zoo li tsis meej pem, tab sis cov txheej txheem no yog qhov ua rau SSA ua haujlwm. Los ntawm tib neeg txoj kev xav, txhua yam no ua rau cov cai nyuaj rau kev nkag siab, tab sis qhov tseeb tias txhua tus nqi raug muab tsuas yog ib zaug ua rau ntau qhov kev txhim kho yooj yim dua.

Nco ntsoov tias yog koj sau koj tus kheej compiler, feem ntau koj yuav tsis tau nrog cov khoom zoo li no. Txawm Clang tsis tsim tag nrho cov lus qhia no phi, nws siv ib tug mechanism alloca (nws zoo li ua haujlwm nrog cov hloov pauv hauv zos zoo ib yam). Tom qab ntawd, thaum khiav LLVM optimization pass hu ua mav 2reg, cov lus qhia alloca hloov mus rau SSA daim ntawv. TinyGo, txawm li cas los xij, tau txais cov tswv yim los ntawm Go SSA, uas, yooj yim, twb tau hloov mus rau SSA daim ntawv.

Lwm qhov kev tsim kho tshiab ntawm cov kab nruab nrab ntawm qhov nruab nrab hauv kev txiav txim siab yog tias nkag mus rau cov ntawv hlais los ntawm kev ntsuas yog sawv cev rau hauv daim ntawv ntawm kev ua haujlwm ntawm kev suav qhov chaw nyob thiab kev ua haujlwm ntawm deferencing qhov tshwm sim pointer. Ntawm no koj tuaj yeem pom qhov sib ntxiv ntawm qhov tsis tu ncua rau IR code (piv txwv li - 1:int). Hauv qhov piv txwv nrog lub luag haujlwm myAdd qhov no tsis tau siv. Tam sim no peb tau txais cov yam ntxwv no tawm ntawm txoj kev, cia peb saib seb qhov chaws no dhau los thaum hloov mus rau LLVM IR daim ntawv:

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
}

Ntawm no, ib yam li ua ntej, peb tuaj yeem pom tib cov qauv, uas suav nrog lwm cov qauv syntactic. Piv txwv li, hauv kev hu phi cov nqi thiab cov ntawv sib pauv. Txawm li cas los xij, muaj qee yam ntawm no uas tsim nyog them nyiaj tshwj xeeb rau.

Pib nrog, ntawm no koj tuaj yeem pom qhov sib txawv kiag li kos npe. LLVM tsis txhawb nqa cov hlais, thiab vim li ntawd, raws li kev ua kom zoo, TinyGo compiler uas tsim cov cai nruab nrab no faib cov lus piav qhia ntawm cov qauv ntaub ntawv no rau hauv qhov chaw. Nws tuaj yeem sawv cev peb ntu (ptr, len ΠΈ cap) raws li ib tug qauv (struct), tab sis sawv cev rau lawv raws li peb cais chaw tso cai rau ib co optimizations. Lwm cov compilers tuaj yeem sawv cev rau daim hlais hauv lwm txoj hauv kev, nyob ntawm kev hu cov rooj sib tham ntawm lub hom phiaj platform txoj haujlwm.

Lwm qhov nthuav dav ntawm cov cai no yog kev siv cov lus qhia getelementptr (feem ntau abbreviated li GEP).

Cov lus qhia no ua haujlwm nrog cov pointers thiab siv kom tau txais tus pointer rau ib lub caij hlais. Piv txwv li, cia peb piv nws nrog cov lej hauv qab no sau hauv C:

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

Los yog nrog cov hauv qab no sib npaug rau qhov no:

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

Qhov tseem ceeb tshaj plaws ntawm no yog cov lus qhia getelementptr tsis ua haujlwm dereferencing. Nws tsuas yog xam tus taw tes tshiab raws li qhov uas twb muaj lawm. Nws tuaj yeem ua raws li cov lus qhia mul ΠΈ add ntawm qib hardware. Koj tuaj yeem nyeem ntxiv txog GEP cov lus qhia no.

Lwm qhov nthuav tshwj xeeb ntawm cov lej nruab nrab no yog kev siv cov lus qhia icmp. Qhov no yog ib qho kev qhia dav dav uas siv los ua qhov sib piv cov lej. Qhov tshwm sim ntawm kev ua raws li cov lus qhia no yeej ib txwm muaj txiaj ntsig ntawm hom i1 β€” logical tus nqi. Hauv qhov no, kev sib piv yog tsim los ntawm kev siv lo lus tseem ceeb slt (kos npe tsawg dua), txij li peb tab tom sib piv ob tus lej yav dhau los sawv cev los ntawm hom int. Yog tias peb muab piv rau ob tus lej tsis tau kos npe, ces peb yuav siv icmp, thiab lo lus tseem ceeb siv hauv kev sib piv yuav yog ult. Txhawm rau piv cov lej ntab ntab, lwm cov lus qhia yog siv, fcmp, uas ua haujlwm zoo ib yam.

Cov txiaj ntsim tau los

Kuv ntseeg tias hauv cov khoom no kuv tau them cov yam ntxwv tseem ceeb tshaj plaws ntawm LLVM IR. Tau kawg, muaj ntau ntau ntawm no. Tshwj xeeb, qhov nruab nrab tus sawv cev ntawm tus lej yuav muaj ntau cov lus piav qhia uas tso cai rau kev ua kom zoo dua los coj mus rau hauv tus account qee yam ntawm cov cai paub rau lub compiler uas tsis tuaj yeem hais tawm hauv IR. Piv txwv li, qhov no yog ib tug chij inbounds GEP cov lus qhia, lossis chij nsw ΠΈ nuw, uas tuaj yeem muab ntxiv rau cov lus qhia add. Ib yam mus rau lo lus tseem ceeb private, qhia rau tus optimizer tias cov haujlwm uas nws cov cim yuav tsis raug xa mus los ntawm sab nraud ntawm chav muab tso ua ke tam sim no. Qhov no tso cai rau ntau qhov kev nthuav dav ntawm kev ua kom zoo dua qub xws li tshem tawm cov lus tsis siv.

Koj tuaj yeem nyeem ntxiv txog LLVM hauv cov ntaub ntawv, uas koj yuav xa mus rau feem ntau thaum tsim koj tus kheej LLVM-raws li compiler. Ntawm no kev ua thawj coj, uas saib ntawm kev tsim lub compiler rau cov lus yooj yim heev. Ob qho ntawm cov ntaub ntawv no yuav pab tau rau koj thaum tsim koj tus kheej compiler.

Nyob zoo nyeem! Koj puas siv LLVM?

LLVM los ntawm ib qho kev xav mus

Tau qhov twg los: www.hab.com

Ntxiv ib saib