2012-03-19 3 views
16

Я понимаю структуру компилятора в отношении интерфейсного и внешнего. Тем не менее, я не уверен, почему компиляторы часто делятся на front-end и back-end. Я уверен, что есть много причин, которые вы можете мне дать? потому что, большинство книг/веб-сайтов говорят вам, что они, но не могут сказать вам, почему!Компилятор - передний конец задней части

спасибо.

ответ

7

Если вы говорите о том, что fron-end является парсером, который токенизирует исходный код, а back-end - это бит, который генерирует исполняемый код на основе токенированного кода, то одна очень веская причина заключается в следующем: переносимость.

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

48

Интерфейс касается самого языка: сканирования, разбора, дерева синтаксического анализа. Задняя часть имеет дело с целевой системой: форматы объектных кодов, сам машинный код ... У двух вещей не так много общего, как для друг друга, и для переносного компилятора очень желательно использовать те же самые front-end с несколькими бэкендами, по одному на цель.

Это можно сделать так, как это делает gcc, а также интерфейс фронта/интерфейса, который не зависит от языка, поэтому вы можете использовать разные интерфейсные интерфейсы с одним и тем же бэкэнд. В прежние времена это называлось проблемой MxN: вы не хотите писать компиляторы MxN, где у вас есть M-языки и N целевых систем. Идея состоит в том, чтобы писать только компиляторы M + N.

+0

Не могли бы вы рассказать мне, как это компиляторы M + N? Я думаю, у нас есть M передних концов, чтобы преобразовать в генераторы кодов ICG и N для преобразования в целевой машинный код. Рассматриваете ли вы каждый фронт и конец в качестве компилятора? – Zephyr

+0

@ Zephyr, Без комбинации FE/BE нам понадобится так много перестановок, которые не нужны/громоздки. –

+0

@ Zephyr Да, комбинация переднего/заднего конца - это компилятор. Неужели это очевидно? – EJP

4

Потому что вы хотите использовать какой-то внутренний псевдокод или таблицы/структуры данных. Например, если у вас есть некоторые строки кода:

a = b + c; 

Вы хотели бы принять это и разорвать его в

load b 
load c 
add b + c 
store a 

в качестве примера, многие решения. Внутренний язык, вероятно, лучше, чем переход на сборку для конкретной цели по нескольким причинам. Внутренний язык, надеюсь, может быть оптимизирован, если у вас есть оптимизатор, и достаточно общий, чтобы использоваться для нескольких целей, если у вас есть желание настроить таргетинг на разные процессоры.

Я не знаю достаточно об этом, но я думаю, что у вас также есть общие используемые синтаксические анализаторы bison/flex, сварить вас в какой-то промежуточный код/​​набор команд, а затем вы напишите для этого бэкэнд.

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

Вы также можете взломать компилятор в блоки логических модулей, вы можете разработать и протестировать передний конец независимо от заднего конца. Например, llvm позволяет экспортировать и импортировать промежуточный язык, вы могли бы, если бы действительно хотели написать код с использованием промежуточного языка и иметь преимущество нескольких целей на бэкэнд.

Смежные вопросы