Проектирование трансляторов

└──┼──┴─┴─┘ ─ ─ ─ ─ ─

└────────────────────────────> │ │

─ ─ ─ ─ ─

│ │

─ ─ ─ ─ ─

│ │

─ ─ ─ ─ ─

│ │

┌────┬──┬──┐

┌──────────────────────────────┼── │-1│ 0│

│ ├────┼──┼──┤

│ ┌────────┼── │ 1│ 3│

│ │ ├────┼──┼──┤

│ │ │ │ 0│ 0│

│ │ └─┼──┴──┴──┘

│ │ │

│ │ │

│ ─ ─ ─ ─ ─ ─ │ ┌─────┘

│ │ │<──┘ │

│ ┌─────┬──┬──┐ │

│ ┌───┼─ │ 2│ 2│ │

┌─────┬──┬──┐ │ │ ├─────┼──┼──┤ ┌─────┬───┬──┐

┌─┼─ │-1│ 2│ │ │┌──┼─ │ 2│ 3│ ┌┼─ │ 0│ 5│

│ ├─────┼──┼──┤ │ ││ ├─────┼──┼──┤ │└─────┴───┴──┘

│ │ │ 0│ 6│<┘ ││ │ │ 2│ 5│ │

│ └───┼─┴──┴──┘ ││ └─┼───┴──┴──┘ │

│ │ ┌─┘│ │ │

│ │ │ ┌┘ ┌─┘ ┌────┘

│ │ │ │ │ │

│ │ │ │ │ │

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐

│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │

└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘


Рис. 20.7 Пример векторов Айлифа для трехмерного массива

сложной структуры


2.3 Замечания по поводу "разреженных" массивов


В некоторых случаях, при хранении массивов по схеме векто-

ров Айлифа или подобной ей схеме с использованием дескрипторов

можно избежать хранения пустых, тривиальных или незаданных значе-

ний элементов. В этих случаях можно рассматривать пару "информа-

ционный элемент" - "значения индексов" как элемент информационно-

го множества, а задание значения (нетривиального) элементу масси-

ва - как пополнение множества, а задание неопределенного (или

тривиального) значения - как удаление элемента из множества.

Представление таких "неполных" (или "разреженных") массивов

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


3. ОРГАНИЗАЦИЯ ПАМЯТИ ВО ВРЕМЯ ТРАНСЛЯЦИИ


3.1 Проблемы распределения памяти


Распределение памяти для определенных программистом перемен-

ных в языках высокого уровня обычно бывает простым. Часто ло-

кальные переменные размещаются в памяти непосредственно после

соответствующей программной единицы. Однако для современных ЭВМ и

ОС, требующих разделения неизменяемой и изменяемой частей прог-

раммы, возникает необходимость помещать локальные переменные в

отдельные области памяти.

Основные проблемы возникают тогда, когда нужно распределить

память для временных переменных, т.е. промежуточных результатов,

потребность в которых появляется при компиляции. Эти переменные

определяются не в программе на входном языке, а компилятором. Ре-

шение о том, сколько для них требуется памяти и как ее распреде-

лить, полностью зависит от компилятора. Поэтому нужен алгоритм

как можно более эффективного размещения в памяти этих переменных.

Здесь под эффективностью обычно понимается стремление минимизиро-

вать объем используемой памяти.

Распределение памяти становится нетривиальной задачей в том

случае, когда у ЭВМ существует более чем один уровень памяти.

У многих машин имеются ограниченные наборы быстрых регис-

тров, которые отличаются от основной памяти либо более быстрым

доступом, либо иными, более удобными свойствами. Эффективное ис-

пользование этих регистров является задачей компилятора, и нужны

алгоритмы оптимального размещения переменных в быстрых регистрах.


3.2 Распределение памяти для временных переменных


Алгоритмы генерации команд не касаются распределения памяти

для временных переменных. Можно считать, что эти алгоритмы берут

новое имя переменной из бесконечного множества неиспользованных

имен каждый раз, когда, согласно алгоритму, требуется новая вре-

менная переменная. Алгоритм распределения памяти должен размес-

тить эти переменные в памяти так, чтобы потребовалось мини-

мальное число ячеек памяти.

ИНТЕРВАЛОМ для переменной называется отрезок времени между

начальным определением этой переменной и ее последним использова-

нием. Очевидно, переменные, интервалы для которых совсем не свя-

заны, могут быть совмещены в памяти.

Рассмотрим набор переменных V1, V2, V3, ..., Vn. Для каждой

переменной Vi определена команда ST Vi, которая присваивает этой

переменной начальное значение и означает начало интервала для Vi.

Определяется также команда U Vi, которая означает очередное

использование этой переменной. Последняя команда этого вида, ис-

пользующая Vi, означает конец интервала для Vi. Команда U будет

применяться для обозначения таких команд, как ADD, SUB и т.д.


Для вычисления значения выражения (a+b*c)/(f*g-(d+e)/(h+k))

генератор команд по дереву разбора сформировал следующую последо-

вательность машинных команд:


L h

ADD k

ST V1

L d

ADD e

DIV V1

ST V2

L f

MPY g

SUB V2

ST V3

L b

MPY c

ADD a

DIV V3


Имена V1, V2 и V3 были взяты из множества неиспользованных

имен. Алгоритм распределения памяти, который мы хотим определить,

должен показать, что фактически эти три переменные могут быть по-

мещены в одну и ту же ячейку памяти T1.

Поскольку этот алгоритм распределения памяти касается опре-

деленных частей последовательности, можно написать


ST V1

U V1

ST V2

U V2

ST V3

U V3


Так как последнее использование каждой переменной встречает-

ся до определения следующей переменной, то легко видеть, что дос-

таточно одной ячейки памяти.

Предположим, что имеется стек неиспользованных ячеек памяти

[T1, T2, T3, ...]. Предположим далее, что каждый раз, когда нуж-

на ячейка, она берется из вершины стека и что сразу после послед-

него использования какой-либо переменной отведенная для нее ячей-

ка возвращается в стек. Тогда алгоритм распределения памяти для

временных переменных проще всего описать следующим образом.

Последовательность команд просматривается НАЧИНАЯ С КОНЦА, В

ОБРАТНОМ ПОРЯДКЕ. Если встречается команда вида U Vi и при этом

для переменной Vi еще не отведена ячейка памяти, то из вершины

стека берется свободная ячейка, ставится в соответствие перемен-

ной Vi и производится замена символа Vi в данной команде на ад-

рес соответствующей ячейки памяти. Такая же замена производится и

в том случае, когда ячейка памяти для переменной Vi уже отведена

ранее. Если встречается команда ST Vi и для переменной Vi еще не

отведена ячейка памяти, то это означает либо ошибку, либо избы-

точность данной команды, так как подразумевается, что переменная

вычисляется без дальнейшего использования. Если для переменной Vi

ранее отведена ячейка памяти, то производится замена символа Vi в

данной команде на адрес соответствующей ячейки памяти и, пос-

кольку это первое обращение к переменной Vi, соответствующая

ячейка в данный момент может быть возвращена в стек свободной па-

мяти, так как для Vi она больше не понадобится.

Данциг и Рейнольдс показали, что этот алгоритм оптимален,

хотя он и не единственный возможный оптимальный алгоритм.

Например, рассмотрим последовательность


(1) ST V1

(2) ST V2

(3) U V2

(4) U V1

(5) ST V3

(6) U V1

(7) U V3

(8) ST V4

(9) U V3

(10) U V4


и предположим, что стек свободной памяти есть [T1, T2, T3].

Начинаем просмотр последовательности с конца; команда (10) поме-

щает переменную V4 в ячейку T1, команда (9) отводит для перемен-

ной V3 ячейку T2, после этого стек остается в виде [T3]. Команда

(8) освобождает ячейку T1, после этого стек принимает вид [T1,

T3]. Команда (6) помещает V1 в ячейку T1. Подобным же образом ко-

манда (5) освобождает ячейку T2; затем эта ячейка отводится ко-

мандой (3) переменной V2.

Если Вам нужна помощь с академической работой (курсовая, контрольная, диплом, реферат и т.д.), обратитесь к нашим специалистам. Более 90000 специалистов готовы Вам помочь.
Бесплатные корректировки и доработки. Бесплатная оценка стоимости работы.

Поможем написать работу на аналогичную тему

Получить выполненную работу или консультацию специалиста по вашему учебному проекту
Нужна помощь в написании работы?
Мы - биржа профессиональных авторов (преподавателей и доцентов вузов). Пишем статьи РИНЦ, ВАК, Scopus. Помогаем в публикации. Правки вносим бесплатно.

Похожие рефераты: