Jump to content

Компилятор

В вычислительной технике компилятор язык) , — это компьютерная программа , которая переводит компьютерный код, написанный на одном языке программирования ( исходный на другой язык ( целевой язык). Название «компилятор» в основном используется для программ, которые переводят исходный код с языка программирования высокого уровня на язык программирования низкого уровня (например, язык ассемблера , объектный код или машинный код ) для создания исполняемой программы. [1] [2] : п1 [3]

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

Сопутствующее программное обеспечение включает декомпиляторы — программы, которые переводят с языков низкого уровня на языки более высокого уровня; программы, которые переводят между языками высокого уровня, обычно называемые компиляторами исходного кода или транспиляторами ; языка переписчики , обычно программы, переводящие форму выражений без изменения языка; и компиляторы-компиляторы , компиляторы, которые создают компиляторы (или их части), часто в общем и многократно используемом виде, чтобы иметь возможность создавать множество разных компиляторов.

Компилятор, скорее всего, выполнит некоторые или все из следующих операций, часто называемых фазами: предварительная обработка , лексический анализ , синтаксический анализ , семантический анализ ( синтаксически-ориентированный перевод ), преобразование входных программ в промежуточное представление , оптимизация кода и генерация кода для конкретной машины. . Составители обычно реализуют эти этапы в виде модульных компонентов, способствуя эффективному проектированию и правильности преобразований исходных входных данных в целевые выходные данные. Ошибки программы, вызванные неправильным поведением компилятора, бывает очень сложно отследить и обойти; поэтому разработчики компилятора прилагают значительные усилия для обеспечения корректности компилятора . [4]

Компиляторы — не единственный языковой процессор, используемый для преобразования исходных программ. Интерпретатор это компьютерное программное обеспечение, которое преобразует, а затем выполняет указанные операции. [2] : п2 Процесс перевода влияет на дизайн компьютерных языков, что приводит к предпочтению компиляции или интерпретации. Теоретически язык программирования может иметь как компилятор, так и интерпретатор. На практике языки программирования обычно связаны только с одним (компилятором или интерпретатором).

Схема работы типичного многоязычного многоцелевого компилятора

Концепции теоретических вычислений, разработанные учёными, математиками и инженерами, легли в основу развития современных цифровых вычислений во время Второй мировой войны. Примитивные двоичные языки возникли потому, что цифровые устройства понимают только единицы и нули, а также схемы в базовой архитектуре машины. В конце 1940-х годов были созданы языки ассемблера, чтобы предложить более работоспособную абстракцию компьютерных архитектур. [5] Ограниченный объем памяти первых компьютеров привел к серьезным техническим проблемам при разработке первых компиляторов. Поэтому процесс компиляции нужно было разделить на несколько небольших программ. Внешние программы создают продукты анализа, используемые внутренними программами для генерации целевого кода. Поскольку компьютерные технологии предоставили больше ресурсов, конструкции компиляторов могли лучше согласовываться с процессом компиляции.

Программисту обычно более продуктивно использовать язык высокого уровня, поэтому разработка языков высокого уровня естественным образом вытекала из возможностей, предлагаемых цифровыми компьютерами. Языки высокого уровня — это формальные языки , строго определенные своим синтаксисом и семантикой , которые формируют архитектуру языка высокого уровня. Элементы этих формальных языков включают:

  • Алфавит , любой конечный набор символов;
  • String — конечная последовательность символов;
  • Язык , любой набор строк в алфавите.

Предложения на языке могут определяться набором правил, называемых грамматикой. [6]

Форма Бэкуса-Наура (БНФ) описывает синтаксис «предложений» языка. Он был разработан Джоном Бэкусом и использовался для синтаксиса Алгола 60 . [7] Идеи взяты из концепций контекстно-свободной грамматики лингвиста Ноама Хомского . [8] «BNF и его расширения стали стандартными инструментами для описания синтаксиса программных обозначений. Во многих случаях части компиляторов генерируются автоматически на основе описания BNF». [9]

Между 1942 и 1945 годами Конрад Цузе разработал первый (алгоритмический) язык программирования для компьютеров под названием Plankalkül («Плановое исчисление»). Цузе также задумал Planfertigungsgerät («Устройство сборки плана») для автоматического перевода математической формулировки программы в машиночитаемую перфорированную пленку . [10] Хотя фактической реализации не произошло до 1970-х годов, в нем были представлены концепции, позже использованные в APL , разработанном Кеном Айверсоном в конце 1950-х годов. [11] APL — язык математических вычислений.

Между 1949 и 1951 годами Хайнц Рутисхаузер предложил Superplan — язык высокого уровня и автоматический переводчик. [12] Его идеи позже были усовершенствованы Фридрихом Л. Бауэром и Клаусом Самельсоном . [13]

Разработка языков высокого уровня в годы становления цифровых вычислений предоставила полезные инструменты программирования для различных приложений:

  • ФОРТРАН (перевод формул) для инженерных и научных приложений считается одним из первых реально реализованных языков высокого уровня и первым оптимизирующим компилятором. [14]
  • COBOL (Common Business-Oriented Language) развился из A-0 и FLOW-MATIC и стал доминирующим языком высокого уровня для бизнес-приложений. [15]
  • LISP (процессор списков) для символьных вычислений. [16]

Технология компилятора возникла из необходимости строго определенного преобразования исходной программы высокого уровня в целевую программу низкого уровня для цифрового компьютера. Компилятор можно рассматривать как интерфейсную часть для анализа исходного кода и внутреннюю часть для синтеза результатов анализа в целевой код. Оптимизация между интерфейсом и сервером может привести к более эффективному целевому коду. [17]

Некоторые ранние вехи в развитии технологии компиляторов:

Ранние операционные системы и программное обеспечение были написаны на языке ассемблера. В 1960-х и начале 1970-х годов использование языков высокого уровня для системного программирования все еще вызывало споры из-за ограниченности ресурсов. исследовательские и отраслевые усилия положили начало переходу к языкам системного программирования высокого уровня, например, BCPL , BLISS , B и C. Однако некоторые

BCPL (базовый комбинированный язык программирования), разработанный в 1966 году Мартином Ричардсом из Кембриджского университета, изначально был разработан как инструмент для написания компиляторов. [29] Было реализовано несколько компиляторов, книга Ричардса дает представление о языке и его компиляторе. [30] BCPL был не только влиятельным языком системного программирования, который до сих пор используется в исследованиях. [31] но также послужил основой для разработки языков B и C.

BLISS (базовый язык для реализации системного программного обеспечения) был разработан для компьютера PDP-10 Digital Equipment Corporation (DEC) исследовательской группой Университета Карнеги-Меллона (CMU) В.А. Вульфа. Команда CMU продолжила разработку компилятора BLISS-11 год спустя, в 1970 году.

Multics (Мультиплексная информационная и вычислительная служба), проект операционной системы с разделением времени, в котором участвовали MIT , Bell Labs , General Electric (позже Honeywell ), а возглавлял его Фернандо Корбато из MIT. [32] Multics был написан на языке PL/I, разработанном IBM и IBM User Group. [33] Целью IBM было удовлетворить требования бизнеса, науки и системного программирования. Можно было рассмотреть и другие языки, но PL/I предложил наиболее полное решение, хотя оно и не было реализовано. [34] В течение первых нескольких лет проекта Multics подмножество языка можно было скомпилировать в ассемблер с помощью компилятора Early PL/I (EPL), созданного Дугом МакИлори и Бобом Моррисом из Bell Labs. [35] EPL поддерживала проект до тех пор, пока не был разработан загрузочный компилятор для полной версии PL/I. [36]

Bell Labs вышла из проекта Multics в 1969 году и разработала язык системного программирования B на основе концепций BCPL, написанных Деннисом Ритчи и Кеном Томпсоном . Ритчи создал загрузочный компилятор для B и написал операционную систему Unics (Uniplexed Information and Computing Service) для PDP-7 на B. Unics в конечном итоге стал называться Unix.

Bell Labs начала разработку и расширение C на основе B и BCPL. Компилятор BCPL был перенесен в Multics компанией Bell Labs, и BCPL был предпочтительным языком в Bell Labs. [37] Первоначально при разработке компилятора C использовалась интерфейсная программа для компилятора B Bell Labs. В 1971 году новый PDP-11 предоставил возможность определить расширения B и переписать компилятор. К 1973 году разработка языка C была практически завершена, и ядро ​​Unix для PDP-11 было переписано на C. Стив Джонсон начал разработку портативного компилятора C (PCC) для поддержки перенацеливания компиляторов C на новые машины. [38] [39]

Объектно-ориентированное программирование (ООП) открыло некоторые интересные возможности для разработки и сопровождения приложений. Концепции ООП уходят корнями в прошлое, но были частью науки о языках LISP и Simula . [40] Bell Labs заинтересовалась ООП с разработкой C++ . [41] C++ впервые был использован в 1980 году для системного программирования. В первоначальном проекте использовались возможности системного программирования на языке C с концепциями Simula. Объектно-ориентированные возможности были добавлены в 1983 году. [42] В программе Cfront реализован интерфейс C++ для компилятора языка C84. В последующие годы по мере роста популярности C++ было разработано несколько компиляторов C++.

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

DARPA «Компилятор качества продукции» (Агентство перспективных оборонных исследовательских проектов) спонсировало проект компилятора совместно с исследовательской группой Вульфа CMU в 1970 году. Проект PQCC должен был создать компилятор качества продукции (PQC) на основе формальных определений исходного языка и цели. [43] пыталась расширить термин «компилятор-компилятор» за пределы традиционного значения генератора синтаксического анализатора (например, Yacc PQCC без особого успеха ). PQCC правильнее было бы называть генератором компилятора.

Исследование PQCC процесса генерации кода было направлено на создание действительно автоматической системы написания компилятора. В ходе этой работы была обнаружена и разработана фазовая структура PQC. Компилятор BLISS-11 предоставил исходную структуру. [44] Эти этапы включали анализ (передняя часть), промежуточный перевод на виртуальную машину (средний конец) и перевод на цель (внутренняя часть). TCOL был разработан для исследования PQCC для обработки специфичных для языка конструкций в промежуточном представлении. [45] Варианты TCOL поддерживали разные языки. Проект PQCC исследовал методы автоматического построения компилятора. Концепции проектирования оказались полезными при оптимизации компиляторов и компиляторов для (с 1995 года объектно-ориентированного) языка программирования Ada .

Ады СТОНМАН Документ [а] формализовали среду поддержки программ (APSE) наряду с ядром (KAPSE) и минимальным (MAPSE). Интерпретатор Ada из Нью-Йоркского университета/ED поддерживал усилия по разработке и стандартизации совместно с Американским национальным институтом стандартов (ANSI) и Международной организацией по стандартизации (ISO). Первоначальная разработка компилятора Ada Военными службами США включала компиляторы в полностью интегрированную среду проектирования в соответствии с документом STONEMAN . Армия и флот работали над проектом Ada Language System (ALS), ориентированным на архитектуру DEC/VAX, в то время как ВВС приступили к работе над интегрированной средой Ada (AIE), ориентированной на IBM 370 series. Хотя проекты не дали желаемых результатов, они внесли свой вклад в общие усилия по развитию Ada. [46]

Другие разработки компилятора Ada начались в Великобритании в Йоркском университете и в Германии в Университете Карлсруэ. В США компания Verdix (позже приобретенная Rational) поставила армии систему разработки Verdix Ada (VADS). VADS предоставил набор инструментов разработки, включая компилятор. Unix/VADS может размещаться на различных платформах Unix, таких как DEC Ultrix и Sun 3/60 Solaris, предназначенных для Motorola 68020, согласно оценке CECOM армии. [47] Вскоре появилось множество компиляторов Ada, прошедших тесты проверки Ada. Проект GNU Фонда свободного программного обеспечения разработал коллекцию компиляторов GNU (GCC), которая обеспечивает основные возможности для поддержки нескольких языков и целевых систем. Версия Ada GNAT — один из наиболее широко используемых компиляторов Ada. GNAT бесплатен, но существует и коммерческая поддержка, например, компания AdaCore была основана в 1994 году для предоставления коммерческих программных решений для Ada. GNAT Pro включает в себя GNAT на базе GNU GCC с набором инструментов для обеспечения интегрированной среды разработки .

Языки высокого уровня продолжали стимулировать исследования и разработки компиляторов. Основные направления включали оптимизацию и автоматическую генерацию кода. Тенденции в языках программирования и средах разработки повлияли на технологию компиляторов. Больше компиляторов стало включено в дистрибутивы языков (PERL, Java Development Kit) и в качестве компонентов IDE (VADS, Eclipse, Ada Pro). Возросла взаимосвязь и взаимозависимость технологий. Появление веб-сервисов способствовало развитию веб-языков и языков сценариев. Сценарии восходят к первым дням появления интерфейсов командной строки (CLI), где пользователь мог вводить команды, которые будут выполняться системой. Концепции пользовательской оболочки, разработанные с использованием языков для написания программ оболочки. Ранние разработки Windows предлагали простую возможность пакетного программирования. Традиционное преобразование этих языков использовало переводчик. Компиляторы Bash и Batch, хотя и не получили широкого распространения, были написаны. Совсем недавно сложные интерпретируемые языки стали частью набора инструментов разработчиков. Современные языки сценариев включают PHP, Python, Ruby и Lua. (Lua широко используется при разработке игр.) Все они имеют поддержку интерпретатора и компилятора. [48]

«Когда в конце 50-х годов возникла область компиляции, ее внимание было ограничено переводом программ на языках высокого уровня в машинный код... Область компиляции все больше переплетается с другими дисциплинами, включая компьютерную архитектуру, языки программирования, формальные методы и т. д. разработка программного обеспечения и компьютерная безопасность». [49] В статье «Исследование компиляторов: следующие 50 лет» отмечается важность объектно-ориентированных языков и Java. безопасность и параллельные вычисления Среди будущих целей исследований были названы .

Конструкция компилятора

[ редактировать ]

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

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

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

Однопроходные и многопроходные компиляторы

[ редактировать ]

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

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

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

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

Разбиение компилятора на небольшие программы — это метод, используемый исследователями, заинтересованными в создании доказуемо правильных компиляторов. Доказательство корректности набора небольших программ часто требует меньших усилий, чем доказательство корректности более крупной, единственной эквивалентной программы.

Трехэтапная структура компилятора

[ редактировать ]
Дизайн компилятора

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

  • Интерфейсная часть сканирует входные данные и проверяет синтаксис и семантику в соответствии с конкретным исходным языком. Для статически типизированных языков он выполняет проверку типов , собирая информацию о типах. Если входная программа синтаксически неверна или имеет ошибку типа, она генерирует сообщения об ошибках и/или предупреждения, обычно указывая место в исходном коде, где была обнаружена проблема; в некоторых случаях фактическая ошибка может произойти (намного) раньше в программе. Аспекты внешнего интерфейса включают лексический анализ, синтаксический анализ и семантический анализ. Интерфейсная часть преобразует входную программу в промежуточное представление (IR) для дальнейшей обработки средней частью. Этот IR обычно представляет собой представление программы более низкого уровня по отношению к исходному коду.
  • Средний уровень выполняет оптимизацию IR, независимую от целевой архитектуры ЦП. Эта независимость исходного/машинного кода предназначена для того, чтобы обеспечить возможность совместного использования общих оптимизаций между версиями компилятора, поддерживающими разные языки и целевые процессоры. Примерами оптимизации промежуточного уровня являются удаление бесполезного ( устранение мертвого кода ) или недостижимого кода ( анализ достижимости ), обнаружение и распространение постоянных значений ( распространение констант ), перемещение вычислений в менее часто выполняемое место (например, из цикла). ), или специализация вычислений на основе контекста, в конечном итоге создавая «оптимизированный» IR, который используется серверной частью.
  • Серверная часть берет оптимизированный IR из средней части. Он может выполнять дополнительный анализ, преобразования и оптимизации, специфичные для целевой архитектуры ЦП. Серверная часть генерирует зависимый от цели ассемблерный код, выполняя распределение регистров при этом . Серверная часть выполняет планирование инструкций , которое меняет порядок инструкций, чтобы параллельные исполнительные блоки были заняты, заполняя слоты задержки . Хотя большинство задач оптимизации являются NP-сложными , эвристические методы их решения хорошо разработаны и реализованы в компиляторах промышленного качества. Обычно выходные данные серверной части представляют собой машинный код, специализированный для конкретного процессора и операционной системы.

Такой подход к интерфейсу, середине и серверной части позволяет комбинировать интерфейсы для разных языков с серверами для разных процессоров , сохраняя при этом оптимизацию среднего уровня. [50] Практическими примерами такого подхода являются коллекция компиляторов GNU , Clang ( LLVM ), компилятор C/C++ на основе [51] и Amsterdam Compiler Kit , который имеет несколько интерфейсов, общие оптимизации и несколько серверов.

Внешний интерфейс

[ редактировать ]
лексера и парсера Пример C. для Начиная с последовательности символов " if(net>0.0)total+=net*(1.0+tax/100.0);", сканер составляет последовательность токенов и классифицирует каждый из них, например как идентификатор , зарезервированное слово , числовой литерал или оператор . Последняя последовательность преобразуется парсером в синтаксическое дерево , которое затем обрабатывается остальными фазами компилятора. Сканер и парсер обрабатывают обычные и контекстно-свободные части грамматики C соответственно.

Интерфейсная часть анализирует исходный код для создания внутреннего представления программы, называемого промежуточным представлением (IR). Он также управляет таблицей символов — структурой данных, сопоставляющей каждый символ в исходном коде со связанной информацией, такой как местоположение, тип и область действия.

Хотя внешний интерфейс может представлять собой единую монолитную функцию или программу, как в парсере без сканера , он традиционно реализовывался и анализировался как несколько этапов, которые могут выполняться последовательно или одновременно. Этот метод предпочтителен из-за его модульности и разделения задач . Чаще всего интерфейс разбивается на три этапа: лексический анализ (также известный как лексирование или сканирование), синтаксический анализ (также известный как сканирование или синтаксический анализ) и семантический анализ . Лексия и синтаксический анализ включают в себя синтаксический анализ (синтаксис слов и синтаксис фраз соответственно), и в простых случаях эти модули (лексер и синтаксический анализатор) могут быть автоматически сгенерированы из грамматики языка, хотя в более сложных случаях они требуют ручной модификации. . Лексическая грамматика и грамматика фраз обычно представляют собой контекстно-свободные грамматики , что значительно упрощает анализ, а контекстная чувствительность учитывается на этапе семантического анализа. Этап семантического анализа обычно более сложен и пишется вручную, но его можно частично или полностью автоматизировать с помощью Атрибутные грамматики . Сами эти этапы можно разбить на более мелкие части: лексирование как сканирование и оценка, а синтаксический анализ как построение конкретного синтаксического дерева (CST, дерево синтаксического анализа) с последующим преобразованием его в абстрактное синтаксическое дерево (AST, синтаксическое дерево). В некоторых случаях используются дополнительные этапы, в частности реконструкция строки и предварительная обработка, но это происходит редко.

Основные этапы фронтенда включают в себя следующее:

  • Реконструкция строки преобразует входную последовательность символов в каноническую форму, готовую для анализатора. Языки, которые ограничивают свои ключевые слова или допускают произвольные пробелы в идентификаторах, требуют этого этапа. Анализаторы сверху вниз , с рекурсивным спуском управляемые таблицами, использовавшиеся в 1960-х годах, обычно считывали исходный код по одному символу за раз и не требовали отдельной фазы токенизации. Atlas Autocode и Imp (а также некоторые реализации ALGOL и Coral 66 ) являются примерами ограниченных языков, компиляторы которых будут иметь фазу линейной реконструкции .
  • Предварительная обработка поддерживает замену макросов и условную компиляцию . Обычно этап предварительной обработки происходит перед синтаксическим или семантическим анализом; например, в случае C препроцессор манипулирует лексическими токенами, а не синтаксическими формами. Однако некоторые языки, такие как Scheme, поддерживают макроподстановки на основе синтаксических форм.
  • Лексический анализ (также известный как лексирование или токенизация ) разбивает текст исходного кода на последовательность небольших частей, называемых лексическими токенами . [52] Этот этап можно разделить на два этапа: сканирование , при котором входной текст сегментируется на синтаксические единицы, называемые лексемами , и присваивается им категория; и оценка , которая преобразует лексемы в обработанное значение. Токен — это пара, состоящая из имени токена и необязательного значения токена . [53] Общие категории токенов могут включать идентификаторы, ключевые слова, разделители, операторы, литералы и комментарии, хотя набор категорий токенов различается в разных языках программирования . Синтаксис лексемы обычно представляет собой обычный язык , поэтому конечный автомат, созданный на основе регулярного выражения для ее распознавания можно использовать . Программное обеспечение, выполняющее лексический анализ, называется лексическим анализатором . Это может не быть отдельный шаг — его можно объединить с этапом синтаксического анализа при синтаксическом анализе без сканирования , и в этом случае синтаксический анализ выполняется на уровне символов, а не на уровне токена.
  • Синтаксический анализ (также известный как синтаксический анализ ) включает анализ последовательности токенов для определения синтаксической структуры программы. На этом этапе обычно строится дерево синтаксического анализа , в котором линейная последовательность токенов заменяется древовидной структурой, построенной в соответствии с правилами формальной грамматики , определяющими синтаксис языка. Дерево синтаксического анализа часто анализируется, дополняется и преобразуется на последующих этапах компилятора. [54]
  • Семантический анализ добавляет семантическую информацию в дерево разбора и строит таблицу символов . На этом этапе выполняются семантические проверки, такие как проверка типов (проверка ошибок типов), или привязка объектов (связывание ссылок на переменные и функции с их определениями), или определенное присвоение (требующее инициализации всех локальных переменных перед использованием), отклонение неправильных программ или выдача предупреждения. Семантический анализ обычно требует полного дерева синтаксического анализа, а это означает, что этот этап логически следует за этапом синтаксического анализа и логически предшествует этапу генерации кода , хотя часто можно объединить несколько этапов в один проход по коду в реализации компилятора.

Средний конец

[ редактировать ]

Средний уровень, также известный как оптимизатор, выполняет оптимизацию промежуточного представления с целью повышения производительности и качества создаваемого машинного кода. [55] Средний уровень содержит те оптимизации, которые не зависят от целевой архитектуры ЦП.

К основным этапам среднего конца относятся следующие:

Анализ компилятора является предпосылкой любой оптимизации компилятора, и они тесно взаимодействуют. Например, анализ зависимостей имеет решающее значение для преобразования цикла .

Объем анализа и оптимизации компилятора сильно различается; их объем может варьироваться от работы внутри базового блока до целых процедур или даже всей программы. Существует компромисс между степенью детализации оптимизации и стоимостью компиляции. Например, оптимизация «глазок» выполняется быстро во время компиляции, но затрагивает только небольшой локальный фрагмент кода и может выполняться независимо от контекста, в котором этот фрагмент кода появляется. Напротив, межпроцедурная оптимизация требует больше времени компиляции и объема памяти, но обеспечивает оптимизацию, которая возможна только при одновременном рассмотрении поведения нескольких функций.

Межпроцедурный анализ и оптимизация широко распространены в современных коммерческих компиляторах HP , IBM , SGI , Intel , Microsoft и Sun Microsystems . Свободное программное обеспечение GCC долгое время критиковали за отсутствие мощных межпроцедурных оптимизаций, но в этом отношении оно меняется. Еще один компилятор с открытым исходным кодом с полной инфраструктурой анализа и оптимизации — Open64 , который используется многими организациями в исследовательских и коммерческих целях.

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

Задняя часть

[ редактировать ]

Серверная часть отвечает за оптимизацию архитектуры ЦП и генерацию кода. [55] .

Основные этапы серверной части включают в себя следующее:

Корректность компилятора

[ редактировать ]

Корректность компилятора — это раздел разработки программного обеспечения, который пытается показать, что компилятор ведет себя в соответствии со спецификацией своего языка . [57] Методы включают разработку компилятора с использованием формальных методов и тщательное тестирование (часто называемое проверкой компилятора) существующего компилятора.

Компилируемые и интерпретируемые языки

[ редактировать ]

Языки программирования более высокого уровня обычно создаются с учетом типа перевода : либо компилируемого языка , либо интерпретируемого языка . Однако на практике редко что-либо в языке требует исключительной компиляции или исключительной интерпретации, хотя можно создавать языки, которые полагаются на повторную интерпретацию во время выполнения. Классификация обычно отражает наиболее популярные или распространенные реализации языка — например, BASIC иногда называют интерпретируемым языком, а C — компилируемым, несмотря на существование компиляторов BASIC и интерпретаторов C.

Интерпретация не заменяет полностью компиляцию. Он лишь скрывает это от пользователя и делает постепенным. Несмотря на то, что интерпретатор сам по себе может интерпретироваться, где-то в нижней части стека выполнения необходим набор непосредственно выполняемых машинных инструкций (см. машинный язык ).

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

В некоторых спецификациях языка указано, что реализации должны включать средства компиляции; например, Common Lisp . Однако в определении Common Lisp нет ничего, что мешало бы его интерпретации. В других языках есть функции, которые очень легко реализовать в интерпретаторе, но значительно усложняют написание компилятора; например, APL , SNOBOL4 и многие языки сценариев позволяют программам создавать произвольный исходный код во время выполнения с помощью обычных строковых операций, а затем выполнять этот код, передавая его специальной функции оценки . Чтобы реализовать эти функции на компилируемом языке, программы обычно должны поставляться с библиотекой времени выполнения , включающей версию самого компилятора.

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

Собственный компилятор — это компилятор , или размещенный выходные данные которого предназначены для непосредственного запуска на компьютере того же типа и в той же операционной системе, на которой работает сам компилятор. Результаты кросс-компилятора предназначены для работы на другой платформе. Кросс-компиляторы часто используются при разработке программного обеспечения для встраиваемых систем , которые не предназначены для поддержки среды разработки программного обеспечения.

Вывод компилятора, создающего код для виртуальной машины (ВМ), может выполняться или не выполняться на той же платформе, что и компилятор, создавший его. По этой причине такие компиляторы обычно не классифицируются как собственные или кросс-компиляторы.

Язык нижнего уровня, который является целью компилятора, сам может быть языком программирования высокого уровня . C, который некоторые рассматривают как своего рода переносимый язык ассемблера, часто является целевым языком таких компиляторов. Например, Cfront , оригинальный компилятор C++ , использовал C в качестве целевого языка. Код C, сгенерированный таким компилятором, обычно не предназначен для чтения и поддержки людьми, поэтому стиль отступов и создание красивого промежуточного кода C игнорируются. Некоторые из особенностей C, которые делают его хорошим целевым языком, включают: #line директива, которая может быть сгенерирована компилятором для поддержки отладки исходного кода, а также широкая поддержка платформ, доступная компиляторам C.

Хотя общий тип компилятора выводит машинный код, существует множество других типов:

Ассемблеры, которые переводят понятный человеку язык ассемблера в инструкции машинного кода , выполняемые аппаратным обеспечением, не считаются компиляторами. [65] [б] (Обратная программа, которая переводит машинный код на язык ассемблера, называется дизассемблером .)

См. также

[ редактировать ]

Примечания и ссылки

[ редактировать ]
  1. Министерство обороны США (18 февраля 1980 г.) Требования Стоунмана
  2. ^ «Многие особенности исходного языка, описанные в предыдущем разделе, приводят к ряду существенных различий между компиляторами и ассемблерами. По любому отдельному элементу различие может быть нечетким. Более того, может быть трудно отличить простой компилятор от мощный макроассемблер. Тем не менее, различия обычно достаточно существенны, поэтому между ассемблерами и компиляторами остается качественное различие».
  1. ^ «Энциклопедия: Определение компилятора» . PCMag.com . Проверено 2 июля 2022 г.
  2. ^ Перейти обратно: а б Составители: принципы, методы и инструменты Альфреда В. Ахо, Рави Сетхи, Джеффри Д. Уллмана - второе издание, 2007 г.
  3. ^ Сударшанам, Ашок; Малик, Шарад; Фудзита, Масахиро (2002). «Методология перенацеливаемой компиляции для встроенных процессоров цифровых сигналов с использованием машинно-зависимой библиотеки оптимизации кода». Чтения по совместному проектированию аппаратного и программного обеспечения . Эльзевир. стр. 506–515. дои : 10.1016/b978-155860702-6/50045-4 . ISBN  9781558607026 . Компилятор — это компьютерная программа, которая переводит программу, написанную на языке высокого уровня (HLL), например C, в эквивалентную программу на языке ассемблера [2].
  4. ^ Сунь, Чэннянь; Ле, Ву; Чжан, Цирунь; Су, Чжэндун (2016). «На пути к пониманию ошибок компилятора в GCC и LLVM» . Материалы 25-го Международного симпозиума по тестированию и анализу программного обеспечения . Иста 2016. С. 294–305. дои : 10.1145/2931037.2931074 . ISBN  9781450343909 . S2CID   8339241 . {{cite book}}: |journal= игнорируется ( помогите )
  5. ^ Багхай, Кристиан (4 апреля 2023 г.). «Эволюция языков программирования: от примитивных двоичных файлов к абстракциям высокого уровня» . Середина . Проверено 10 июля 2024 г.
  6. ^ Конспекты лекций. Составители: принципы, методы и инструменты. Цзин-Шин Чанг. Департамент компьютерных наук и информационной инженерии. Национальный университет Чи-Нань
  7. ^ Наур, П. и др. «Отчет по Алголу 60». Сообщения ACM 3 (май 1960 г.), 299–314.
  8. ^ Хомский, Ноам; Лайтфут, Дэвид В. (2002). Синтаксические структуры . Вальтер де Грюйтер. ISBN  978-3-11-017279-9 .
  9. ^ Грис, Дэвид (2012). «Приложение 1: Форма Бэкуса-Наура» . Наука программирования . Springer Science & Business Media. п. 304. ИСБН  978-1461259831 .
  10. ^ Хеллиге, Ханс Дитер, изд. (2004 г.) [ноябрь 2002 г.]. Написано в Бремене, Германия. Истории информатики - видения, парадигмы, лейтмотивы (на немецком языке) (1-е изд.). Берлин / Гейдельберг, Германия: Springer-Verlag . стр. 45, 104, 105. doi : 10.1007/978-3-642-18631-8 . ISBN  978-3-540-00217-8 . ISBN   3-540-00217-0 . (xii+514 страниц)
  11. ^ Айверсон, Кеннет Э. (1962). Язык программирования . Джон Уайли и сыновья. ISBN  978-0-471430-14-8 .
  12. ^ Рутисхаузер, Хайнц (1951). «Об автоматическом составлении расчетных планов в вычислительных системах с программным управлением». Журнал прикладной математики и механики (на немецком языке). 31 :255. дои : 10.1002/zamm.19510310820 .
  13. ^ Фоте, Майкл; Уилке, Томас, ред. (2015) [14 ноября 2014 г.]. Написано в Йене, Германия. Подвал, стек и автоматическая память — структура с потенциалом [ Подвал, стек и автоматическая память — структура с потенциалом ] (PDF) (Материалы коллоквиума 14 ноября 2014 г. в Йене). Серия GI: Конспекты лекций по информатике (LNI) - Тематика (на немецком языке). Том Т-7. Бонн, Германия: Gesellschaft für Informatik (GI) / Köllen Druck + Verlag GmbH. стр. 20–21. ISBN  978-3-88579-426-4 . ISSN   1614-3213 . Архивировано (PDF) из оригинала 12 апреля 2020 г. Проверено 12 апреля 2020 г. [1] (77 страниц)
  14. ^ Бэкус, Джон. «История ФОРТРАНА I, II и III» (PDF) . История языков программирования . Архивировано (PDF) из оригинала 10 октября 2022 года. {{cite book}}: |website= игнорируется ( помогите )
  15. Портер Адамс, Вики (5 октября 1981 г.). «Капитан Грейс М. Хоппер: мать КОБОЛа». ИнфоМир. 3 (20): 33. ISSN 0199-6649.
  16. ^ Маккарти, Дж.; Брайтон, Р.; Эдвардс, Д.; Фокс, П.; Ходс, Л.; Лакхэм, Д.; Малинг, К.; Парк, Д.; Рассел, С. (март 1960 г.). «Руководство программиста LISP I» (PDF) . Бостон, Массачусетс: Группа искусственного интеллекта, Вычислительный центр и исследовательская лаборатория Массачусетского технологического института.
  17. ^ Принципы, методы и инструменты компиляторов, 2-е издание Ахо, Лама, Сетхи, Ульмана. ISBN   0-321-48681-1
  18. ^ Хоппер, Грейс Мюррей (1952). «Компьютерное образование» . Материалы Национального собрания ACM 1952 года (Питтсбург) : 243–249. дои : 10.1145/609784.609818 . S2CID   10081016 .
  19. ^ Риджуэй, Ричард К. (1952). «Составление регламентов» . Материалы Национального собрания ACM 1952 года (Торонто) : 1–5. дои : 10.1145/800259.808980 . S2CID   14878552 .
  20. ^ «Список ранних компиляторов и ассемблеров» .
  21. ^ Хоппер, Грейс. «Основное выступление» . Материалы конференции ACM SIGPLAN History of Programming Languages ​​(HOPL), июнь 1978 г. дои : 10.1145/800025.1198341 .
  22. ^ Брюдерер, Герберт. «Создала ли Грейс Хоппер первый компилятор?» .
  23. ^ Строун, Джордж; Строун, Кэндис (2015). «Грейс Хоппер: Компиляторы и Кобол» . ИТ-специалист . 17 (январь-февраль 2015 г.): 62–64. дои : 10.1109/MITP.2015.6 .
  24. ^ Кнут, Дональд Э.; Пардо, Луис Трабб, «Раннее развитие языков программирования», Энциклопедия компьютерных наук и технологий (Марсель Деккер) 7: 419–493
  25. ^ Хоар, ЦАР (декабрь 1973 г.). «Советы по проектированию языков программирования» (PDF) . п. 27. Архивировано (PDF) из оригинала 10 октября 2022 года. (Это утверждение иногда ошибочно приписывают Эдсгеру В. Дейкстре , также участвовавшему в реализации первого компилятора ALGOL 60.)
  26. ^ Абельсон, Хэл; Дыбвиг, РК; и др. Рис, Джонатан; Клингер, Уильям (ред.). «Пересмотренный (3) отчет об алгоритмической языковой схеме (посвящается памяти Алгола 60)» . Проверено 20 октября 2009 г.
  27. ^ « Рекурсивные функции символических выражений и их машинное вычисление », сообщения ACM, апрель 1960 г.
  28. ^ Маккарти, Джон; Абрахамс, Пол В.; Эдвардс, Дэниел Дж.; Харт, Тимоти П.; Левин, Майкл И. (1965). Руководство программиста Lisp 1.5 . Массачусетский технологический институт Пресс. ISBN  978-0-26213011-0 .
  29. ^ « BCPL: инструмент для написания компиляторов и системного программирования » М. Ричардс, Математическая лаборатория Кембриджского университета, Англия, 1969 г.
  30. ^ BCPL: Язык и его компилятор, М. Ричардс, Cambridge University Press (впервые опубликовано 31 декабря 1981 г.)
  31. ^ Руководство пользователя BCPL Cintsys и Cintpos, М. Ричардс, 2017 г.
  32. ^ Корбато, Ф.Дж.; Высоцкий В.А. «Введение и обзор системы МУЛЬТИКС» . Осень 1965 г. Объединенная компьютерная конференция . Multicians.org.
  33. ^ Отчет II Комитета по развитию языков SHARE, 25 июня 1964 г.
  34. ^ Статья Multicians.org «Выбор PL/I», редактор / Том Ван Флек
  35. ^ «PL/I как инструмент для системного программирования», FJ Corbato, Datamation, выпуск от 6 мая 1969 г.
  36. ^ « Компилятор Multics PL/1 », RA Freiburghouse, GE, Осенняя объединенная компьютерная конференция, 1969 г.
  37. ^ Деннис М. Ричи, « Развитие языка C », Конференция ACM «Вторая история языков программирования», апрель 1993 г.
  38. ^ SC Johnson, «Портативный компилятор C: теория и практика», 5-й симпозиум ACM POPL, январь 1978 г.
  39. ^ А. Снайдер, Портативный компилятор для языка C , Массачусетский технологический институт, 1974.
  40. ^ К. Нигаард, Университет Осло, Норвегия, « Основные концепции объектно-ориентированного программирования », SIGPLAN Уведомления V21, 1986 г.
  41. ^ Б. Страуструп: «Что такое объектно-ориентированное программирование?» Материалы 14-й конференции АГУ, 1986 г.
  42. ^ Бьерн Страуструп, «Обзор языка программирования C++», Справочник по объектным технологиям (редактор: Саба Замир, ISBN   0-8493-3135-8 )
  43. ^ Леверетт, Кеттелл, Хоббс, Новичок, Райнер, Шац, Вульф: «Обзор проекта компилятора-компилятора качества продукции», CMU-CS-89-105, 1979
  44. ^ В. Вульф, К. Нори, « Отложенное связывание в компиляторах, сгенерированных PQCC », Отчет о результатах исследований CMU, CMU-CS-82-138, 1982
  45. ^ Джозеф М. Ньюкомер, Дэвид Алекс Ламб, Брюс В. Леверетт, Майкл Тай, Уильям А. Вульф - Университет Карнеги-Меллона и Дэвид Левин, Эндрю Х. Рейнерит - Интерметрики: «TCOL Ada: пересмотренный отчет о промежуточном представлении для Стандартный язык программирования Министерства обороны США", 1979 г.
  46. ^ Уильям А. Уитакер, «Ада - проект: Рабочая группа высшего порядка Министерства обороны», Уведомления ACM SIGPLAN (том 28, № 3, март 1991 г.)
  47. ^ Центр разработки программного обеспечения CECOM, передовые программные технологии, «Итоговый отчет - оценка набора тестов ACEC для приложений реального времени», AD-A231 968, 1990
  48. ^ П.Биггар, Э. де Врис, Д. Грегг, «Практическое решение для компиляторов языков сценариев», представлено в журнал Science of Computer Programming, 2009 г.
  49. ^ М.Холл, Д. Падуя, К. Пингали, «Исследования компиляторов: следующие 50 лет», ACM Communications, 2009, том 54, № 2.
  50. ^ Купер и Торчон 2012, с. 8
  51. ^ Латтнер, Крис (2017). «ЛЛВМ» . В Брауне, Эми; Уилсон, Грег (ред.). Архитектура приложений с открытым исходным кодом . Архивировано из оригинала 2 декабря 2016 года . Проверено 28 февраля 2017 г.
  52. ^ Ахо, Лам, Сетхи, Ульман 2007, с. 5–6, 109–189
  53. ^ Ахо, Лам, Сетхи, Ульман 2007, с. 111
  54. ^ Ахо, Лам, Сетхи, Ульман 2007, с. 8, 191 – 300
  55. ^ Перейти обратно: а б Блинделл, Габриэль Хьорт (3 июня 2016 г.). Выбор инструкций: принципы, методы и приложения . Швейцария: Шпрингер. ISBN  978-3-31934019-7 . OCLC   951745657 .
  56. ^ Купер и Точон (2012), с. 540
  57. ^ «S1-A Simple Compiler» , Создание компилятора с использованием Java, JavaCC и Yacc , Хобокен, Нью-Джерси, США: John Wiley & Sons, Inc., стр. 289–329, 28 февраля 2012 г., doi : 10.1002/9781118112762.ch12 , ISBN  978-1-118-11276-2 , получено 17 мая 2023 г.
  58. ^ Ильюшин, Евгений; Намиот, Дмитрий (2016). «О компиляторах исходного кода» . Международный журнал открытых информационных технологий . 4 (5): 48–51. Архивировано из оригинала 13 сентября 2022 года . Проверено 14 сентября 2022 г.
  59. ^ Эйкок, Джон (2003). «Краткая история системы «точно в срок». АКМ Компьютер. Сурв . 35 (2 июня): 93–113. дои : 10.1145/857076.857077 . S2CID   15345671 .
  60. ^ Шварц, Джордан С.; Бетц, Во; Роуз, Джонатан (22–25 февраля 1998 г.). «Быстрый маршрутизатор с возможностью маршрутизации для FPGA» (PDF) . Материалы шестого международного симпозиума ACM/SIGDA 1998 года по программируемым вентильным матрицам - FPGA '98 . Монтерей, Калифорния: ACM . стр. 140–149. дои : 10.1145/275107.275134 . ISBN  978-0897919784 . S2CID   7128364 . Архивировано (PDF) из оригинала 9 августа 2017 года.
  61. ^ Посох Ксилинкс (2009). «Обзор синтеза XST» . Xilinx, Inc. Архивировано из оригинала 2 ноября 2016 года . Проверено 28 февраля 2017 г.
  62. ^ Альтера Персонал (2017). «Двигатель Spectra-Q™» . Альтера.com. Архивировано из оригинала 10 октября 2016 года . Проверено 28 февраля 2017 г.
  63. ^ «Декомпиляторы — обзор | Темы ScienceDirect» . www.sciencedirect.com . Проверено 12 июня 2022 г.
  64. ^ Чандрасекаран, Сиддхарт (26 января 2018 г.). «Кросс-компиляция демистифицирована» . встроить журнал.com . Проверено 5 марта 2023 г.
  65. ^ Калингаерт и Горовиц 1979, стр. 186-187.

Дальнейшее чтение

[ редактировать ]
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 5118a6d1e64ad0666b17962c12f84dd2__1720615080
URL1:https://arc.ask3.ru/arc/aa/51/d2/5118a6d1e64ad0666b17962c12f84dd2.html
Заголовок, (Title) документа по адресу, URL1:
Compiler - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)