Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛАБОРАТОРНА РОБОТА № 4.doc
Скачиваний:
3
Добавлен:
09.11.2019
Размер:
358.91 Кб
Скачать

Побудова списку тріад по дереву виводу.

Тріади є універсальною, машинно-незалежною формою внутрішнього уявлення в компіляторі результуючої об'єктної програми, а тому не вимагають обмовки додаткових умов при генерації коду. Тріади взаємозв'язані між собою, тому для установки коректного взаємозв'язку процедура генерації коди повинна отримувати також поточний номер i чергової тріади.

Тоді чотирьом формам поточного вузла дерева відповідатимуть послідовності тріад об'єктної коди (табл. 6):

Таблиця 6.

Перетворення типових вузлів дерева виводу в послідовність тріад

Вид вузла дерева

Результуючий код

Примітка

i) act (oper1,oper2)

act - тип тріади

oper1,oper2 - операнди (листя дерева виводу)

i) Code(Узел 2,i)

i+j) act(oper1,^i+j-1)

Узел 2 - вузол дерева виводу, що пролягає нижче

Code(Узел 2,i) - послідовність тріад, що породжується для Узла2, починаючи з тріади з номером i

j - кількість тріад, що породжуються для Узла2

i) Code(Узел 2,i)

i+j) act(^i+j-1,oper2)

Узел 2 - вузол дерева виводу, що пролягає нижче

Code(Узел 2,i) - послідовність тріад, що породжується для Узла2, починаючи з тріади з номером i

j - кількість тріад, що породжуються для Узла2

i) Code(Узел 2,i)

i+j) Code(Узел 3,i+j)

i+j+k) act(^i+j-1,^i+j+k-1)

Узел 2, Узел 3 - вузли дерева виводу, що пролягають нижче

Code(Узел 2,i) - послідовність тріад, що породжується для Узла2, починаючи з тріади з номером i

j - кількість тріад, що породжуються для Узла2

Code(Узел 3,i+j) - послідовність тріад, що породжується для Узла3, починаючи з тріади з номером i+j

k - кількість тріад, що породжуються для Узла3

Розглянемо той же приклад дерева виводу для виразу A := B*c + D - B*10 на мал. 6 і відповідну йому послідовність тріад:

соответствующую ему последовательность триад:

Мал. 6. Дерево виводу для арифметичного виразу.

Крок 1: 1) Code(U2,1)

i) :=(A,^i-1)

Крок 2: 1) Code(U3,1)

j) Code(U5,j)

i-1) -(^j-1,^i-2)

i) :=(A,^i-1)

Крок 3: 1) Code(U4,1)

k) +(^k-1,D)

j) Code(U5,j)

i-1) -(^j-1,^i-2)

i) :=(A,^i-1)

Крок 4: 1) *(B,C)

2) +(^1,D)

3) Code(U5,3)

i-1) -(^j-1,^i-2)

i) :=(A,^i-1)

Крок 5: 1) *(B,C)

2) +(^1,D)

3) *(B,10)

4) -(^2,^3)

5) :=(A,^4)

Слід звернути увагу, що в даному алгоритмі послідовні номери тріад (а отже, і посилання на них) встановлюються не відразу. Це не має значення при рекурсивній організації процедури, але при іншому способі обходу дерева виводу в програмі генерації коди краще пов'язувати тріади між собою саме по посиланню (покажчику), а не по порядковому номеру.

Для тріад розроблені універсальні (машинно-незалежні) алгоритми оптимізації коди. Після їх виконання (оптимізації внутрішнього уявлення) тріади можуть бути перетворені в команди на мові асемблера.

Оптимізація об'єктної коди методом згортки

Згортка об'єктного коду - це виконання під час компіляції тих операцій початкової програми для яких значення операндів вже відомі. Тому немає необхідності багато разів виконувати їх в самій результуючій програмі - цілком достатньо один раз виконати їх при її компіляції.

Простий варіант згортки - виконання в компіляторі операцій, операндами яких є константи. Декілька більш складений процес визначення тих операцій, значення яких можуть бути відомі в результаті виконання інших операцій. Для цього служить спеціальний алгоритм згортки.

Алгоритм згортки працює із спеціальною таблицею T, яка містить пари <переменная>-<константа> для всіх змінних, значення яких вже відомі. Крім того, алгоритм згортки позначає ті операції у внутрішньому уявленні програми, для яких в результаті згортки вже не потрібна генерація коду. Оскільки при виконанні алгоритму згортки враховується взаємозв'язок операцій, то зручною формою уявлення для нього є тріади, оскільки в інших формах представлення операцій (таких як тетради або команди асемблера) потрібні додаткові структури, щоб відобразити зв'язок результатів одних операцій з операндами інших.

Алгоритм згортки тріад послідовно проглядає тріади лінійного списку і для кожної тріади робить наступне:

  1. Якщо операнд є змінна, яка міститься в таблиці T, то операнд замінюється на відповідне значення константи.

  2. Якщо операнд є посилання на особливу тріаду типу C(K,0), то операнд замінюється на значення константи K.

  3. Якщо всі операнди тріади є константами, то тріада може бути згорнута. Тоді дана тріада виконується і замість неї поміщається особлива тріада виду C(K,0), де K - константа, результат виконання згорнутої тріади. (При генерації коди для особливої тріади об'єктний код не породжується, а тому вона надалі може бути просто виключена).

  4. Якщо тріада є привласненням типу A:=b, тоді:

  • якщо B - константа, то A із значенням константи заноситься в таблицю T (якщо там вже було старе значення для A, то це старе значення виключається).

  • якщо B - не константа, то A взагалі виключається з таблиці T, якщо воно там є.

Розглянемо приклад виконання алгоритму.

Хай фрагмент початкової програми (записаною на мові типу Паскаль) має вигляд:

I := 1 + 1;

I := 3;

J := 6*I + I;

Її внутрішньо уявлення у формі тріад матиме вигляд:

  1. + (1,1)

  2. := (I ^1)

  3. := (I, 3)

  4. * (6, I)

  5. + (^4, I)

  6. := (J ^5)

Процес виконання алгоритму згортки можна відобразити в табл. 7:

Таблиця 7.

Приклад роботи алгоритму згортки

Тріада

Крок 1

Крок 2

Крок 3

Крок 4

Крок 5

Крок 6

1

C (2, 0)

C (2, 0)

C (2, 0)

C (2, 0)

C (2, 0)

C (2, 0)

2

:= (I, ^1)

:= (I, 2)

:= (I, 2)

:= (I, 2)

:= (I, 2)

:= (I, 2)

3

:= (I, 3)

:= (I, 3)

:= (I, 3)

:= (I, 3)

:= (I, 3)

:= (I, 3)

4

* (6, I)

* (6, I)

* (6, I)

C (18, 0)

C (18, 0)

C (18, 0)

5

+ (^4, I)

+ (^4, I)

+ (^4, I)

+ (^4, I)

C (21, 0)

C (21, 0)

6

:= (J, ^5)

:= (J, ^5)

:= (J, ^5)

:= (J, ^5)

:= (J, ^5)

:= (J, 21)

Т

( , )

( I, 2 )

( I, 3 )

( I, 3 )

( I, 3 )

( I, 3 ) ( J, 21 )

Якщо виключити особливі тріади типу C(K,0) (які не породжують об'єктної коди), то в результаті виконання згортки отримаємо наступну послідовність тріад:

  1. := (I, 2)

  2. := (I, 3)

  3. := (J, 21)