Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 94 стр.

UptoLike

Структурные конструкции удобны тем, что имеют ровно один вход и
ровно один выход. Этот факт в сочетании с тем, что они вкладываются
друг в друга, позволяет использовать для их порождения рекурсивные ал-
горитмы. В данном разделе мы предложим как раз рекурсивный вариант
генерации структурных конструкций.
5.3.1. Генерация кода для логических выражений
Логические выражения отличаются от рассмотренных ранее в этой
главе арифметических выражений тем, что могут вычисляться не полно-
стью. Например, в выражении
(a = 10) and (sin(x) = 0.5)
второе равенство имеет смысл вычислять, только если первое равенство
истинно (то есть если значение переменной a равно 10).
Это означает, что в коде, вычисляющем логические выражения,
должны активно использоваться условные переходы.
Динамическая генерация кода
175
В таблице 5.3 приведен список некоторых образцов и замен, которые
можно использовать для peephole-оптимизации CIL-кода.
5.3. Генерация развилок
Генерация кода, содержащего инструкции переходов, представляет
некоторую сложность по сравнению с генерацией линейного кода. Дело в
том, что появляются переходы вперед по коду, то есть переходы на инст-
рукции, которые еще не были сгенерированы. Общий метод решения этой
проблемы заключается в том, что такие инструкции переходов генериру-
ются частично, то есть сначала вместо них в код вставляются заглушки, в
которых не прописаны адреса переходов, а затем, когда адрес становится
известен, заглушки заменяются на настоящие инструкции переходов.
Интересен факт, что генерация развилок существенно упрощается,
если в процессе генерации придерживаться определенных требований
структурированной парадигмы в программировании. Эти требования за-
ключаются в том, что в генерируемой программе используются только
пять структурных конструкций, а именно: последовательность (рис. 5.2a),
выбор (рис. 5.2b), множественный выбор (рис. 5.2c), цикл с предусловием
(рис. 5.2d) и цикл с постусловием (рис. 5.2e). При этом конструкции могут
быть вложены друг в друга.
174
CIL и системное программирование в Microsoft .NET
dup
stloc.0
stloc.1
ldloc.0
dup
dup
stloc.0
stloc.1
Рис. 5.1. Peephole-оптимизация
Образец Замена
stloc(starg) x dup
ldloc(ldarg) x stloc(starg) x
ldloc (ldarg) x ldloc (ldarg) x
ldloc (ldarg) x dup
ckfinite ckfinite
ckfinite
not(neg) pop
pop
add(sub,mul,div,...) pop
pop pop
ldc.i4.0
add(sub)
ldloca(ldarga) x ldc.i4.0
initobj int32 stloc(starg) x
stloc(starg) x dup
ldloc(ldarg) y stloc(starg) x
ldloc(ldarg) x ldloc(ldarg) y
add (или любая коммутативная add (или любая коммутативная
бинарная операция) бинарная операция)
Таблица 5.3. Некоторые образцы и замены для peephole-оптимизации
CIL-кода
174                         CIL и системное программирование в Microsoft .NET   Динамическая генерация кода                                        175


                                                                                     Таблица 5.3. Некоторые образцы и замены для peephole-оптимизации
                                                                                     CIL-кода

                                                                                Образец                           Замена
                                                                                stloc(starg) x                    dup
             dup                                          dup                   ldloc(ldarg) x                    stloc(starg) x
                                                                                ldloc (ldarg) x                   ldloc (ldarg) x
            stloc.0                                       dup
                                                                                ldloc (ldarg) x                   dup
            stloc.1                                     stloc.0                 ckfinite                          ckfinite
                                                                                ckfinite
            ldloc.0                                     stloc.1                 not(neg)                          pop
                                                                                pop
                                                                                add(sub,mul,div,...)              pop
                                                                                pop                               pop
                                                                                ldc.i4.0                          –
                                                                                add(sub)
                                                                                ldloca(ldarga) x                  ldc.i4.0
      Рис. 5.1. Peephole-оптимизация
                                                                                initobj int32                     stloc(starg) x
    В таблице 5.3 приведен список некоторых образцов и замен, которые           stloc(starg) x                    dup
можно использовать для peephole-оптимизации CIL-кода.                           ldloc(ldarg) y                    stloc(starg) x
                                                                                ldloc(ldarg) x                    ldloc(ldarg) y
                                                                                add (или любая коммутативная      add (или любая коммутативная
5.3. Генерация развилок                                                         бинарная операция)                бинарная операция)
     Генерация кода, содержащего инструкции переходов, представляет
некоторую сложность по сравнению с генерацией линейного кода. Дело в                 Структурные конструкции удобны тем, что имеют ровно один вход и
том, что появляются переходы вперед по коду, то есть переходы на инст-          ровно один выход. Этот факт в сочетании с тем, что они вкладываются
рукции, которые еще не были сгенерированы. Общий метод решения этой             друг в друга, позволяет использовать для их порождения рекурсивные ал-
проблемы заключается в том, что такие инструкции переходов генериру-            горитмы. В данном разделе мы предложим как раз рекурсивный вариант
ются частично, то есть сначала вместо них в код вставляются заглушки, в         генерации структурных конструкций.
которых не прописаны адреса переходов, а затем, когда адрес становится
известен, заглушки заменяются на настоящие инструкции переходов.                5.3.1. Генерация кода для логических выражений
     Интересен факт, что генерация развилок существенно упрощается,                  Логические выражения отличаются от рассмотренных ранее в этой
если в процессе генерации придерживаться определенных требований                главе арифметических выражений тем, что могут вычисляться не полно-
структурированной парадигмы в программировании. Эти требования за-              стью. Например, в выражении
ключаются в том, что в генерируемой программе используются только                    (a = 10) and (sin(x) = 0.5)
пять структурных конструкций, а именно: последовательность (рис. 5.2a),         второе равенство имеет смысл вычислять, только если первое равенство
выбор (рис. 5.2b), множественный выбор (рис. 5.2c), цикл с предусловием         истинно (то есть если значение переменной a равно 10).
(рис. 5.2d) и цикл с постусловием (рис. 5.2e). При этом конструкции могут            Это означает, что в коде, вычисляющем логические выражения,
быть вложены друг в друга.                                                      должны активно использоваться условные переходы.