Bosh sahifa Wiki Three-Address Code

Three-Address Code

Three-Address Code (TAC) — murakkab ifodalarni odatda bitta operator va ko‘pi bilan uchta manzilga ega sodda ko‘rsatmalarga ajratadigan oraliq kod. Manzillar operandlar va natijani ifodalaydi; temporary variable’lar hisoblash ketma-ketligini aniq qiladi.

Ko‘rsatma shakli

x = a + b * c ifodasi t1 = b * c va x = a + t1 ko‘rsatmalariga parchalanadi. Conditional jump, unconditional jump, parameter passing, call va return ham TAC instruction shakllariga ega. Bu soddalik control-flow graph hamda data-flow tahlillarini source syntaxdan mustaqil bajarishga yordam beradi.

Tasvir variantlari

Quadruple yozuvida (op, arg1, arg2, result), triple yozuvida esa natija alohida nom o‘rniga instruction indeksiga bog‘lanadi. Indirect triple instruction tartibini almashtirishni yengillashtiradi. Tanlov optimizer va backend ma’lumot tuzilmasiga bog‘liq; uchala ko‘rinish bir xil semantik g‘oyani ifodalaydi.

Backend bilan aloqa

TAC hali target machine instructioni emas. Bitta TAC operatori bir nechta assembly instructionga aylanishi yoki aksincha bir nechta TAC amali bitta target instructionga birlashtirilishi mumkin. SSA formda har variable definitioni yagona bo‘ladi va phi tugunlari qo‘shiladi; oddiy TAC esa mutable nomlarga ruxsat beradi.

Semantik ehtiyot choralari

Generator expression evaluation order, short-circuit boolean semantics va side effectlarni saqlashi kerak. f() + g() tartibi til spetsifikatsiyasida belgilangan bo‘lsa, temporarylar shu tartibni aks ettiradi. Undefined behavior mavjud tilda optimizer faqat ruxsat etilgan semantik taxminlar doirasida o‘zgartirish qiladi.

Tekshiruv

Sinovda TAC interpreter yoki reference evaluator original AST natijasi bilan solishtiriladi. Har jump target mavjud blockka borishi, temporary use oldidan tegishli definition kelishi va call convention metadata saqlanishi tekshiriladi. Debug buildda source locationni instructionlarga bog‘lash xato joyini qayta ko‘rsatishga imkon beradi.

Three-Address Code bo‘yicha tahlil natijasi faqat yakuniy xulosa bilan emas, uni hosil qilgan IR versiyasi, target xususiyatlari va qo‘llangan taxminlar bilan birga saqlanadi. Compiler passlari ketma-ket o‘zgarganda oldingi natija avtomatik ravishda haqiqiy deb olinmaydi: tegishli dependencylar invalidatsiya qilinib, zarur qism qayta hisoblanadi. Debug rejimida asosiy invariant buzilgan nuqta va undan oldingi transformatsiya qayd etiladi; release rejimida esa tekshiruvlarning arzon qismi qoldiriladi. Shu yondashuv nazariy jihatdan qonuniy qoida implementatsiya xatosi yoki noto‘g‘ri cost model sabab zararli qarorga aylangan holatni ajratishga yordam beradi.

Kengaytirilgan jihatlar

Basic blocklar TACning ketma-ket instructionlarini branchsiz bo‘laklarga ajratadi. Leader sifatida entry, jump target va jumpdan keyingi instruction olinadi; blocklar orasidagi edge CFGni hosil qiladi. Optimizer temporary nomlar uchun type, signedness va possible side effect metadata saqlashi kerak. Load va store amallari oddiy arifmetik instructiondan farqli ravishda memory state bilan bog‘langan; call ham memoryni o‘zgartirishi mumkin. Exception chiqaradigan division yoki bounds checkni boshqa amal bilan erkin almashtirish xato tartibini o‘zgartiradi. Shuning uchun TAC sodda ko‘rinsa ham, uning formal operational semanticsi aniq belgilanishi zarur.

TAC dump har instructionga barqaror block label va temporary type beradi, bu optimizatsiya oldi-keyin diffini o‘qishni osonlashtiradi. Pass verifier har transformatsiyadan keyin CFG targetlari, operand definitionlari va type mosligini tekshiradi. Katta production buildda to‘liq verifier tanlab yoqiladi, arzon structural tekshiruv esa doimiy qolishi mumkin.

Bog‘liq tushunchalar

intermediate representation, quadruple, basic block, control-flow graph, SSA, code generation