Code generation — kompilyatorning oraliq tasvirdan maqsad platformada bajariladigan ko‘rsatmalar yoki boshqa chiqish kodini hosil qiladigan bosqichidir. Native kompilyatorda natija odatda assembler yoki mashina kodi bo‘ladi; transpilerda esa boshqa yuqori darajali til kodi yaratilishi mumkin. Bu bosqich dastur ma’nosini maqsad arxitekturasining registrlari, ko‘rsatmalari va ABI qoidalariga moslashtiradi.
Ko‘rsatma tanlash
Instruction selection IR operatsiyalarini protsessor ko‘rsatmalariga aylantiradi. Bitta IR amali bir ko‘rsatmaga to‘g‘ri kelishi yoki bir necha ko‘rsatmaga ajralishi mumkin. Aksincha, maqsad arxitekturasidagi murakkab ko‘rsatma bir nechta IR amalini birlashtirishi mumkin. Tanlovda operand shakli, darhol beriladigan qiymat chegarasi, manzillash rejimi va ko‘rsatma narxi hisobga olinadi.
Maqsadga bog‘liq legalizatsiya apparat bevosita bajara olmaydigan tur yoki amalni qo‘llab-quvvatlanadigan ketma-ketlikka tushiradi. Masalan, ma’lum kenglikdagi butun son amali yordamchi kutubxona chaqirig‘i bilan bajarilishi mumkin. SIMD mavjud bo‘lsa, mustaqil amallar vektor ko‘rsatmalariga birlashtiriladi, ammo xotira hizalanishi va xavfsiz chegaralar saqlanishi zarur.
Registr ajratish va rejalashtirish
IR odatda cheksiz sonli virtual registrlardan foydalanadi, real protsessorda esa registrlar cheklangan. Register allocation faol qiymatlarni fizik registrlarga joylaydi. Sig‘magan qiymat stackdagi joyga vaqtincha yoziladi; bu spill deb ataladi va qo‘shimcha xotira amallarini keltiradi. Graph coloring va linear scan keng tarqalgan yondashuvlardir. JIT ko‘pincha tezligi sabab linear scan kabi sodda algoritmni tanlaydi.
Instruction scheduling ma’lumot bog‘liqligini saqlagan holda ko‘rsatmalar tartibini protsessor quvuridan samarali foydalanish uchun o‘zgartiradi. Uzoq kechikuvchi yuklash bilan mustaqil hisobni orasiga joylashtirish kutishni yashirishi mumkin. Zamonaviy protsessor ham dinamik qayta tartiblaydi, lekin kompilyatorning statik rejalashtirishi ayrim arxitekturalarda muhim qoladi.
ABI va chiqish fayli
Funksiya chaqiruvlari platformaning application binary interface qoidalariga mos bo‘lishi kerak. Argumentlarning registr yoki stack orqali uzatilishi, qaytish qiymati, saqlanishi shart bo‘lgan registrlar, stack hizalanishi va nom formatlari ABI bilan belgilanadi. Qoidaga zid kod boshqa modul bilan bog‘langanda xato ishlaydi, hatto alohida funksiya ichidagi hisob to‘g‘ri bo‘lsa ham.
Generator mashina baytlari bilan birga symbol, relocation, unwind va debug ma’lumotlarini obyekt fayliga yozadi. Linker tashqi nomlarni hal qiladi va bo‘limlarga yakuniy manzil beradi. AOT usulida bu jarayon dastur ishga tushishidan oldin, JITda esa bajarilish vaqtida amalga oshadi. Kod generatori testlarida bir ko‘rsatmaning ko‘rinishi emas, turli kirishlar uchun kuzatiladigan natija va ABI mosligi ham tekshiriladi.
To‘g‘rilikni tekshirish
Backend xatosi kam uchrasa ham, noto‘g‘ri mashina kodi barcha yuqori darajali tekshiruvlardan keyin paydo bo‘lishi mumkin. Instruction selector va register allocator uchun maqsadli testlar bilan birga tasodifiy dasturlarni turli optimizatsiya darajasida kompilyatsiya qilib natijani solishtirish qo‘llanadi. Emulator yoki bir nechta real arxitektura CI’da platformaga xos xatolarni topadi. Disassembly tekshiruvi maxsus ko‘rsatma tanlanganini tasdiqlashi mumkin, ammo baytlar ketma-ketligiga haddan tashqari bog‘langan test foydali ekvivalent o‘zgarishni to‘sadi. Asosiy mezon kuzatiladigan semantika, calling convention va xotira xavfsizligining saqlanishidir.
Kod hajmi ham backend qaroridir. Embedded muhitda ixcham ketma-ketlik tezroq variantdan afzal bo‘lishi mumkin, serverda esa instruction cache bosimi inlining chegarasini belgilaydi. Cost model maqsad CPU xususiyatlari va optimizatsiya maqsadiga mos sozlanadi.
Bog‘liq tushunchalar
Compiler backend, Instruction selection, Register allocation, ABI, Object file, Linker, JIT