LLVM с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Go

Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° компилятора β€” ΠΎΡ‡Π΅Π½ΡŒ тяТёлая Π·Π°Π΄Π°Ρ‡Π°. Но, ΠΊ ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, с Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΠ΅ΠΌ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ LLVM, Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ этой Π·Π°Π΄Π°Ρ‡ΠΈ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ упрощаСтся, Ρ‡Ρ‚ΠΎ позволяСт Π΄Π°ΠΆΠ΅ программисту-ΠΎΠ΄ΠΈΠ½ΠΎΡ‡ΠΊΠ΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ язык, Π±Π»ΠΈΠ·ΠΊΠΈΠΉ ΠΏΠΎ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΊ C. Π Π°Π±ΠΎΡ‚Π° с LLVM ослоТняСтся Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ эта систСма прСдставлСна ΠΎΠ³Ρ€ΠΎΠΌΠ½Ρ‹ΠΌ ΠΎΠ±ΡŠΡ‘ΠΌΠΎΠΌ ΠΊΠΎΠ΄Π°, снабТённого нСбольшой Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ. Для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ этот нСдостаток ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ, Π°Π²Ρ‚ΠΎΡ€ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π°, ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΌΡ‹ сСгодня ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅ΠΌ, собираСтся ΠΏΡ€ΠΎΠ΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΊΠΎΠ΄Π°, написанного Π½Π° Go, ΠΈ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ Ρ‚Ρ€Π°Π½ΡΠ»ΠΈΡ€ΡƒΡŽΡ‚ΡΡ сначала Π² Go SSA, Π° ΠΏΠΎΡ‚ΠΎΠΌ β€” Π² LLVM IR с использованиСм компилятора TinyGO. Код Go SSA ΠΈ LLVM IR Π±Ρ‹Π» Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΡ‚Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½, ΠΈΠ· Π½Π΅Π³ΠΎ Π±Ρ‹Π»ΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΎ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π½Π΅ относится ΠΊ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠΌΡ‹ΠΌ Ρ‚ΡƒΡ‚ пояснСниям, Ρ€Π°Π΄ΠΈ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ эти пояснСния оказались Π±Ρ‹ Π±ΠΎΠ»Π΅Π΅ понятными.

LLVM с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Go

ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€

ΠŸΠ΅Ρ€Π²Π°Ρ функция, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ я ΡΠΎΠ±ΠΈΡ€Π°ΡŽΡΡŒ Ρ‚ΡƒΡ‚ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒ, прСдставляСт собой простой ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ для слоТСния чисСл:

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

Π­Ρ‚Π° функция ΠΎΡ‡Π΅Π½ΡŒ проста, ΠΈ, ΠΏΠΎΠΆΠ°Π»ΡƒΠΉ, Π½ΠΈΡ‡Π΅Π³ΠΎ ΠΏΡ€ΠΎΡ‰Π΅ ΡƒΠΆΠ΅ ΠΈ Π½Π΅ ΠΏΡ€ΠΈΠ΄ΡƒΠΌΠ°Ρ‚ΡŒ. Она транслируСтся Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ Go SSA:

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

ΠŸΡ€ΠΈ Ρ‚Π°ΠΊΠΎΠΌ прСдставлСнии Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ подсказки ΠΎ Ρ‚ΠΈΠΏΠ°Ρ… Π΄Π°Π½Π½Ρ‹Ρ… Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°ΡŽΡ‚ΡΡ справа, Π² Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ случаСв Π½Π° Π½ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ Π½Π΅ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒ внимания.

Π­Ρ‚ΠΎΡ‚ малСнький ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΡƒΠΆΠ΅ позволяСт ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ ΡΡƒΡ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· аспСктов SSA. А ΠΈΠΌΠ΅Π½Π½ΠΎ, ΠΏΡ€ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠΈ ΠΊΠΎΠ΄Π° Π² Ρ„ΠΎΡ€ΠΌΡƒ SSA ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ разбиваСтся Π½Π° самыС элСмСнтарныС части, ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΠ½ΠΎ состоит. Π’ нашСм случаС ΠΊΠΎΠΌΠ°Π½Π΄Π° return a + b, Π½Π° самом Π΄Π΅Π»Π΅, прСдставляСт собой Π΄Π²Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ: слоТСниС Π΄Π²ΡƒΡ… чисСл ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.

ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ ΠΈ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ Π±Π»ΠΎΠΊΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π² Π΄Π°Π½Π½ΠΎΠΌ ΠΊΠΎΠ΄Π΅ имССтся всСго ΠΎΠ΄ΠΈΠ½ Π±Π»ΠΎΠΊ β€” Π²Ρ…ΠΎΠ΄Π½ΠΎΠΉ (entry block). ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ Π±Π»ΠΎΠΊΠ°Ρ… ΠΌΡ‹ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π½ΠΈΠΆΠ΅.

Код Go SSA Π»Π΅Π³ΠΊΠΎ прСобразуСтся Π² LLVM IR:

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

МоТно Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ хотя Ρ‚ΡƒΡ‚ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ синтаксичСскиС конструкции, структура Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π² основном, Π½Π΅ измСнилась. Код LLVM IR Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ сильнСС, Ρ‡Π΅ΠΌ ΠΊΠΎΠ΄ Go SSA, ΠΏΠΎΡ…ΠΎΠΆ Π½Π° C. Π—Π΄Π΅ΡΡŒ, Π² объявлСнии Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, сначала ΠΈΠ΄Ρ‘Ρ‚ описаниС Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ Π΅ΠΉ Ρ‚ΠΈΠΏΠ° Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‚ΠΈΠΏ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° указываСтся ΠΏΠ΅Ρ€Π΅Π΄ ΠΈΠΌΠ΅Π½Π΅ΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, для упрощСния IR-парсинга, ΠΏΠ΅Ρ€Π΅Π΄ ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Ρ… сущностСй стоит символ @, Π° ΠΏΠ΅Ρ€Π΅Π΄ ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… β€” символ % (функция Ρ‚ΠΎΠΆΠ΅ считаСтся глобальной ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒΡŽ).

Одна ΠΈΠ· особСнностСй этого ΠΊΠΎΠ΄Π°, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΎ прСдставлСнии Ρ‚ΠΈΠΏΠ° Go int, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ прСдставлСн 32-Π±ΠΈΡ‚Π½Ρ‹ΠΌ ΠΈΠ»ΠΈ 64-Π±ΠΈΡ‚Π½Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, Π² зависимости ΠΎΡ‚ компилятора ΠΈ ΠΎΡ‚ Ρ†Π΅Π»ΠΈ компиляции, принимаСтся ΠΏΡ€ΠΈ создании LLVM IR-ΠΊΠΎΠ΄Π°. Π­Ρ‚ΠΎ β€” ΠΎΠ΄Π½Π° ΠΈΠ· ΠΌΠ½ΠΎΠ³ΠΈΡ… ΠΏΡ€ΠΈΡ‡ΠΈΠ½ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ LLVM IR-ΠΊΠΎΠ΄ Π½Π΅ являСтся, ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΈΠ΅ Π΄ΡƒΠΌΠ°ΡŽΡ‚, ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½Π½ΠΎ-нСзависимым. Π’Π°ΠΊΠΎΠΉ ΠΊΠΎΠ΄, созданный для ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹, нСльзя просто Π²Π·ΡΡ‚ΡŒ ΠΈ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ для Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹ (Ссли Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ ΠΏΠΎΠ΄ΠΎΠΉΡ‚ΠΈ ΠΊ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡŽ этой Π·Π°Π΄Π°Ρ‡ΠΈ с особой ΠΎΡΡ‚ΠΎΡ€ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ).

Π•Ρ‰Ρ‘ ΠΎΠ΄ΠΈΠ½ интСрСсный ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ стоит ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Ρ‚ΠΈΠΏ i64 β€” это Π½Π΅ Ρ†Π΅Π»ΠΎΠ΅ число со Π·Π½Π°ΠΊΠΎΠΌ: ΠΎΠ½ Π½Π΅ΠΉΡ‚Ρ€Π°Π»Π΅Π½ Π² ΠΏΠ»Π°Π½Π΅ прСдставлСния Π·Π½Π°ΠΊΠ° числа. Π’ зависимости ΠΎΡ‚ инструкции ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ ΠΊΠ°ΠΊ числа со Π·Π½Π°ΠΊΠΎΠΌ, Ρ‚Π°ΠΊ ΠΈ числа Π±Π΅Π· Π·Π½Π°ΠΊΠ°. Π’ случаС с прСдставлСниСм ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ слоТСния это Ρ€ΠΎΠ»ΠΈ Π½Π΅ ΠΈΠ³Ρ€Π°Π΅Ρ‚, поэтому здСсь Π½Π΅Ρ‚ Ρ€Π°Π·Π½ΠΈΡ†Ρ‹ Π² Ρ€Π°Π±ΠΎΡ‚Π΅ с числами со Π·Π½Π°ΠΊΠΎΠΌ ΠΈΠ»ΠΈ Π±Π΅Π· Π·Π½Π°ΠΊΠ°. Π’ΡƒΡ‚ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π² языкС C ΠΏΠ΅Ρ€Π΅ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ цСлочислСнной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ со Π·Π½Π°ΠΊΠΎΠΌ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Π½Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½ΠΎΠΌΡƒ повСдСнию, поэтому Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄ Clang добавляСт ΠΊ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ„Π»Π°Π³ nsw (no signed wrap), Ρ‡Ρ‚ΠΎ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ LLVM Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ…ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΈΠ· прСдполоТСния ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ слоТСнии Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ происходит пСрСполнСния.

Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π²Π°ΠΆΠ½Ρ‹ΠΌ для Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΉ. НапримСр, слоТСниС Π΄Π²ΡƒΡ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ i16 Π½Π° 32-Π±ΠΈΡ‚Π½ΠΎΠΉ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅ (с 32-Π±ΠΈΡ‚Π½Ρ‹ΠΌΠΈ рСгистрами) нуТдаСтся, послС выполнСния слоТСния, Π² ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ Π·Π½Π°ΠΊΠ°, для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ i16. Из-Π·Π° этого часто Π±ΠΎΠ»Π΅Π΅ эффСктивным оказываСтся Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ цСлочислСнных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ с ΡƒΡ‡Ρ‘Ρ‚ΠΎΠΌ ΠΌΠ°ΡˆΠΈΠ½Π½Ρ‹Ρ… Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠ² рСгистра.

Π’ΠΎ, Ρ‡Ρ‚ΠΎ происходит Π² дальнСйшСм с этим IR-ΠΊΠΎΠ΄ΠΎΠΌ, сСйчас нас Π½Π΅ особСнно интСрСсуСт. Код оптимизируСтся (Π½ΠΎ Π² случаС с Ρ‚Π°ΠΊΠΈΠΌ простым ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΌ, ΠΊΠ°ΠΊ наш, Π½ΠΈΡ‡Π΅Π³ΠΎ ΡƒΠΆΠ΅ Π½Π΅ оптимизируСтся), Π° Π·Π°Ρ‚Π΅ΠΌ прСобразуСтся Π² ΠΌΠ°ΡˆΠΈΠ½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄.

Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ рассмотрим, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ слоТнСС. А ΠΈΠΌΠ΅Π½Π½ΠΎ, Ρ€Π΅Ρ‡ΡŒ ΠΈΠ΄Ρ‘Ρ‚ ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, которая суммируСт слайс Ρ†Π΅Π»Ρ‹Ρ… чисСл:

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

Π­Ρ‚ΠΎΡ‚ ΠΊΠΎΠ΄ прСобразуСтся Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ 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

Π’ΡƒΡ‚ ΡƒΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ большС конструкций, Ρ…Π°Ρ€Π°ΠΊΡ‚Π΅Ρ€Π½Ρ‹Ρ… для прСдставлСния ΠΊΠΎΠ΄Π° Π² Ρ„ΠΎΡ€ΠΌΠ΅ SSA. ВСроятно, Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎΠΉ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒΡŽ этого ΠΊΠΎΠ΄Π° являСтся Ρ‚ΠΎΡ‚ Ρ„Π°ΠΊΡ‚, Ρ‡Ρ‚ΠΎ здСсь Π½Π΅Ρ‚ структурированных ΠΊΠΎΠΌΠ°Π½Π΄ управлСния ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ вычислСний. Для управлСния ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ вычислСний здСсь ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ лишь условныС ΠΈ бСзусловныС ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Ρ‹, ΠΈ, Ссли ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ эту ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ для управлСния ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ, ΠΊΠΎΠΌΠ°Π½Π΄Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π°.

На самом Π΄Π΅Π»Π΅, Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π½Π΅ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π° Π½Π° Π±Π»ΠΎΠΊΠΈ с использованиСм Ρ„ΠΈΠ³ΡƒΡ€Π½Ρ‹Ρ… скобок (ΠΊΠ°ΠΊ Π² языках сСмСйства C). Она Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π° ΠΌΠ΅Ρ‚ΠΊΠ°ΠΌΠΈ, Ρ‡Ρ‚ΠΎ Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ ассСмблСрныС языки, ΠΈ прСдставлСна Π² Π²ΠΈΠ΄Π΅ Π±Π°Π·ΠΎΠ²Ρ‹Ρ… Π±Π»ΠΎΠΊΠΎΠ². Π’ SSA Π±Π°Π·ΠΎΠ²Ρ‹ΠΌΠΈ Π±Π»ΠΎΠΊΠ°ΠΌΠΈ Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π½Π΅ΠΏΡ€Π΅Ρ€Ρ‹Π²Π½Ρ‹Π΅ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΊΠΎΠ΄Π°, Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‰ΠΈΠ΅ΡΡ с ΠΌΠ΅Ρ‚ΠΊΠΈ ΠΈ Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°ΡŽΡ‰ΠΈΠ΅ΡΡ инструкциями Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ°, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ β€” return ΠΈ jump.

Π•Ρ‰Ρ‘ ΠΎΠ΄Π½Π° интСрСсная Π΄Π΅Ρ‚Π°Π»ΡŒ этого ΠΊΠΎΠ΄Π° прСдставлСна инструкциСй phi. Π˜Π½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡ это довольно нСобычная, Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ с Π½Π΅ΠΉ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ врСмя. ΠŸΠΎΠΌΠ½ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ SSA β€” это сокращСниС для Static Single Assignment. Π­Ρ‚ΠΎ β€” ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ΅ прСдставлСниС ΠΊΠΎΠ΄Π°, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠ³ΠΎ компиляторами, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ присваиваСтся лишь Π΅Π΄ΠΈΠ½ΠΎΠΆΠ΄Ρ‹. Π­Ρ‚ΠΎ ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ для выраТСния простых Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ нашСй Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ myAdd, ΠΏΠΎΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π²Ρ‹ΡˆΠ΅, Π½ΠΎ Π½Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ для Π±ΠΎΠ»Π΅Π΅ слоТных Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ β€” Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ рассматриваСмой Π² этом Ρ€Π°Π·Π΄Π΅Π»Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sum. Π’ частности, Π² Ρ…ΠΎΠ΄Π΅ выполнСния Ρ†ΠΈΠΊΠ»Π° ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ i ΠΈ n.

SSA ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ Π½Π° ΠΎΠ΄Π½ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎΠ΅ присваиваниС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… с использованиСм Ρ‚Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠΉ инструкции phi (Π΅Ρ‘ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ взято ΠΈΠ· грСчСского Π°Π»Ρ„Π°Π²ΠΈΡ‚Π°). Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ SSA-прСдставлСниС ΠΊΠΎΠ΄Π° ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ ΡΡ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ для языков Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ C, приходится ΠΏΡ€ΠΈΠ±Π΅Π³Π°Ρ‚ΡŒ ΠΊ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ хитростям. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π° этой инструкции являСтся Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ (i ΠΈΠ»ΠΈ n), Π° Π² качСствС Π΅Ρ‘ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ список Π±Π°Π·ΠΎΠ²Ρ‹Ρ… Π±Π»ΠΎΠΊΠΎΠ². НапримСр, рассмотрим Ρ‚Π°ΠΊΡƒΡŽ ΠΈΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ:

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

Π•Ρ‘ смысл Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ: Ссли ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΌ Π±Π°Π·ΠΎΠ²Ρ‹ΠΌ Π±Π»ΠΎΠΊΠΎΠΌ Π±Ρ‹Π» Π±Π»ΠΎΠΊ entry (Π²Ρ…ΠΎΠ΄Π½ΠΎΠΉ), Ρ‚ΠΎ t0 β€” это константа 0, Π° Ссли ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΌ Π±Π°Π·ΠΎΠ²Ρ‹ΠΌ Π±Π»ΠΎΠΊΠΎΠΌ Π±Ρ‹Π» for.body, Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ Π²Π·ΡΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ t6 ΠΈΠ· этого Π±Π»ΠΎΠΊΠ°. Π’Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ всё это ΠΌΠΎΠΆΠ΅Ρ‚ довольно-Ρ‚Π°ΠΊΠΈ таинствСнным, Π½ΠΎ благодаря этому ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡƒ обСспСчиваСтся Ρ€Π°Π±ΠΎΡ‚Π° SSA. Π‘ чСловСчСской Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния всё это услоТняСт ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π°, Π½ΠΎ Ρ‚ΠΎΡ‚ Ρ„Π°ΠΊΡ‚, Ρ‡Ρ‚ΠΎ ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ назначаСтся лишь ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·, Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ ΠΌΠ½ΠΎΠ³ΠΈΠ΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Ссли Π²Ρ‹ ΠΏΠΈΡˆΠ΅Ρ‚Π΅ собствСнный компилятор, Ρ‚ΠΎ Π²Π°ΠΌ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π½Π΅ приходится ΠΈΠΌΠ΅Ρ‚ΡŒ Π΄Π΅Π»ΠΎ с ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹ΠΌΠΈ Π²Π΅Ρ‰Π°ΠΌΠΈ. Π”Π°ΠΆΠ΅ Clang Π½Π΅ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ всС эти инструкции phi, ΠΎΠ½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ alloca (ΠΎΠ½ Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρƒ с ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌΠΈ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ). Π—Π°Ρ‚Π΅ΠΌ, ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΏΡ€ΠΎΡ…ΠΎΠ΄Π° ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ LLVM, Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ³ΠΎ mem2reg, инструкции alloca ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΡŽΡ‚ΡΡ Π² Ρ„ΠΎΡ€ΠΌΡƒ SSA. TinyGo, ΠΎΠ΄Π½Π°ΠΊΠΎ, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ Π²Ρ…ΠΎΠ΄Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ Go SSA, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅, Ρ‡Ρ‚ΠΎ ΡƒΠ΄ΠΎΠ±Π½ΠΎ, ΡƒΠΆΠ΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½Ρ‹ Π² Ρ„ΠΎΡ€ΠΌΡƒ SSA.

Π•Ρ‰Ρ‘ ΠΎΠ΄Π½ΠΎ Π½ΠΎΠ²ΡˆΠ΅ΡΡ‚Π²ΠΎ рассматриваСмого Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π° ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π° Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ доступ ΠΊ элСмСнтам слайса ΠΏΠΎ индСксу прСдставлСн Π² Π²ΠΈΠ΄Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ вычислСния адрСса ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ разымСнования ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ указатСля. Π’ΡƒΡ‚ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ ΠΈ нСпосрСдствСнноС Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ констант Π² IR-ΠΊΠΎΠ΄ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ β€” 1:int). Π’ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ myAdd ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎΠ΅ Π½Π΅ использовалось. Π’Π΅ΠΏΠ΅Ρ€ΡŒ, Ρ€Π°Π·ΠΎΠ±Ρ€Π°Π²ΡˆΠΈΡΡŒ с этими особСнностями, взглянСм Π½Π° Ρ‚ΠΎ, Π²ΠΎ Ρ‡Ρ‚ΠΎ прСвратится этот ΠΊΠΎΠ΄ ΠΏΡ€ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠΈ Π΅Π³ΠΎ Π² Ρ„ΠΎΡ€ΠΌΡƒ 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
}

Π’ΡƒΡ‚, ΠΊΠ°ΠΊ ΠΈ ΠΏΡ€Π΅ΠΆΠ΄Π΅, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ Ρ‚Π°ΠΊΡƒΡŽ ΠΆΠ΅ структуру, Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΡƒΡŽ Π² сСбя Π΄Ρ€ΡƒΠ³ΠΈΠ΅ синтаксичСскиС конструкции. НапримСр, Π² Π²Ρ‹Π·ΠΎΠ²Π°Ρ… phi помСнялись мСстами значСния ΠΈ ΠΌΠ΅Ρ‚ΠΊΠΈ. Однако Ρ‚ΡƒΡ‚ Π΅ΡΡ‚ΡŒ ΠΈ ΠΊΠΎΠ΅-Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅, Π½Π° Ρ‡Ρ‚ΠΎ стоит ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ особоС Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅.

Для Π½Π°Ρ‡Π°Π»Π°, Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ Π΄Ρ€ΡƒΠ³ΡƒΡŽ сигнатуру Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. LLVM Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ слайсы, Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅, Π² Π²ΠΈΠ΄Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ, компилятор TinyGo, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ сформировал этот ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΉ ΠΊΠΎΠ΄, Ρ€Π°Π·Π΄Π΅Π»ΠΈΠ» описаниС этой структуры Π΄Π°Π½Π½Ρ‹Ρ… Π½Π° части. Он ΠΌΠΎΠ³ Π±Ρ‹ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Ρ‚Ρ€ΠΈ элСмСнта слайса (ptr, len ΠΈ cap) Π² Π²ΠΈΠ΄Π΅ структуры (struct), Π½ΠΎ прСдставлСниС ΠΈΡ… Π² Π²ΠΈΠ΄Π΅ Ρ‚Ρ€Ρ‘Ρ… ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… сущностСй позволяСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ. Π”Ρ€ΡƒΠ³ΠΈΠ΅ компиляторы ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ слайс Π΅Ρ‰Ρ‘ ΠΊΠ°ΠΊ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ, это зависит ΠΎΡ‚ соглашСний ΠΎ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Ρ†Π΅Π»Π΅Π²ΠΎΠΉ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹.

Π•Ρ‰Ρ‘ ΠΎΠ΄Π½ΠΎΠΉ интСрСсной ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒΡŽ этого ΠΊΠΎΠ΄Π° являСтся использованиС инструкции getelementptr (часто Π΅Ρ‘ сокращённо Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ GEP).

Π­Ρ‚Π° инструкция Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ с указатСлями ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для получСния указатСля Π½Π° элСмСнт слайса. НапримСр, Π΄Π°Π²Π°ΠΉΡ‚Π΅ сопоставим Π΅Ρ‘ со ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΊΠΎΠ΄ΠΎΠΌ, написанным Π½Π° C:

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

Или со ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ, эквивалСнтным этому:

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

Π‘Π°ΠΌΠΎΠ΅ Π³Π»Π°Π²Π½ΠΎΠ΅ Ρ‚ΡƒΡ‚ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ инструкция getelementptr Π½Π΅ выполняСт ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ разымСнования. Она лишь вычисляСт Π½ΠΎΠ²Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, ΠΎΡΠ½ΠΎΠ²Ρ‹Π²Π°ΡΡΡŒ Π½Π° ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΌ. Π•Ρ‘ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ ΠΊΠ°ΠΊ инструкции mul ΠΈ add Π½Π° Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚Π½ΠΎΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΡΡ‚ΠΈ ΠΎΠ± инструкции GEP ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ здСсь.

Π•Ρ‰Ρ‘ ΠΎΠ΄Π½Π° интСрСсная ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ этого ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π° Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² использовании инструкции icmp. Π­Ρ‚ΠΎ β€” инструкция ΠΎΠ±Ρ‰Π΅Π³ΠΎ назначСния, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠ°Ρ для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сравнСния Ρ†Π΅Π»Ρ‹Ρ… чисСл. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния этой инструкции всСгда являСтся Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° i1 β€” логичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС производится сравнСниС с использованиСм ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ³ΠΎ слова slt (signed less than), Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ сравниваСм ΠΌΡ‹ Π΄Π²Π° числа, Ρ€Π°Π½Π΅Π΅ прСдставлСнных Ρ‚ΠΈΠΏΠΎΠΌ int. Если Π±Ρ‹ ΠΌΡ‹ сравнивали Π΄Π²Π° Ρ†Π΅Π»Ρ‹Ρ… числа Π±Π΅Π· Π·Π½Π°ΠΊΠ°, Ρ‚ΠΎΠ³Π΄Π° Π² качСствС инструкции ΠΌΡ‹ воспользовались Π±Ρ‹ icmp, Π° ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹ΠΌ словом, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΌ ΠΏΡ€ΠΈ сравнСнии, Π±Ρ‹Π»ΠΎ Π±Ρ‹ ult. Для сравнСния чисСл с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ другая инструкция, fcmp, Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰Π°Ρ ΠΏΠΎΡ…ΠΎΠΆΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ.

Π˜Ρ‚ΠΎΠ³ΠΈ

Полагаю, Ρ‡Ρ‚ΠΎ Π² этом ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π΅ я рассмотрСл самыС Π²Π°ΠΆΠ½Ρ‹Π΅ особСнности LLVM IR. ΠšΠΎΠ½Π΅Ρ‡Π½ΠΎ, Ρ‚ΡƒΡ‚ Π΅ΡΡ‚ΡŒ Π΅Ρ‰Ρ‘ ΠΎΡ‡Π΅Π½ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ всСго. Π’ частности, Π² ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠΌ прСдставлСнии ΠΊΠΎΠ΄Π° ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΡΡƒΡ‚ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ мноТСство Π°Π½Π½ΠΎΡ‚Π°Ρ†ΠΈΠΉ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΡ… ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΡ…ΠΎΠ΄Π°Ρ… ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹Π΅ особСнности ΠΊΠΎΠ΄Π°, извСстныС компилятору, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ нСльзя Π΄Ρ€ΡƒΠ³ΠΈΠΌ способом Π²Ρ‹Ρ€Π°Π·ΠΈΡ‚ΡŒ Π² IR. НапримСр, это Ρ„Π»Π°Π³ inbounds инструкции GEP, ΠΈΠ»ΠΈ Ρ„Π»Π°Π³ΠΈ nsw ΠΈ nuw, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ ΠΊ инструкции add. Π’ΠΎ ΠΆΠ΅ самоС касаСтся ΠΈ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ³ΠΎ слова private, ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰Π΅Π³ΠΎ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ‚ΠΎΡ€Ρƒ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΎΡ‚ΠΌΠ΅Ρ‡Π΅Π½Π½ΡƒΡŽ ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ ΠΈΠ·Π²Π½Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Π΅Π΄ΠΈΠ½ΠΈΡ†Ρ‹ компиляции. Π­Ρ‚ΠΎ позволяСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ мноТСство интСрСсных ΠΌΠ΅ΠΆΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π½Ρ‹Ρ… ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΉ Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ устранСния Π½Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ².

ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΡΡ‚ΠΈ ΠΎ LLVM ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π²Ρ‹ Π±ΡƒΠ΄Π΅Ρ‚Π΅ часто ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ, разрабатывая собствСнный компилятор, основанный Π½Π° LLVM. Π’ΠΎΡ‚ руководство, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ рассматриваСтся Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° компилятора для ΠΎΡ‡Π΅Π½ΡŒ простого языка. Оба этих источника ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ пригодятся Π²Π°ΠΌ ΠΏΡ€ΠΈ создании собствСнного компилятора.

Π£Π²Π°ΠΆΠ°Π΅ΠΌΡ‹Π΅ Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΠΈ! ΠŸΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ΡΡŒ Π»ΠΈ Π²Ρ‹ LLVM?

LLVM с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Go

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com