Принципы компиляции внешнего интерфейса (1): Введение в компиляцию

внешний интерфейс JavaScript
Принципы компиляции внешнего интерфейса (1): Введение в компиляцию

Автор: холодная трава
WeChat: hancao97
Введение: Другой программист Beidrift (молодой программист, работающий 10 месяцев), добро пожаловать в WeChat для критики и исправления навыков общения или совместной игры и назначения встречи.

введение

Все могло бы сказать что-то о чувствах

В период, когда я начал писать статью, я разместил эту статьюЯ, 24 года, смотрю вперед?Там упоминались не только мои разные возмутительные флаги, но и моя альма-матер.Я скучаю по тому времени, и поскольку я не провел весь выпускной год в своей альма-матер из-за эпидемии, не было ни выпускных фотографий, ни выпускного. поездки.И очень неудачно.
Тем не менее, я до сих пор помню хорошие времена, которые у меня были в моей альма-матер, и编译原理Кроме того, это был последний профессиональный курс, о котором у меня сложилось впечатление во время учебы там. Два дня назад я тоже обсуждал свою с другимиjs реализует мастер кнопок — попробуйте реализовать автоматическое тестирование на интерфейсе (1), в процессе обмена и обсуждения я чувствую, что на самом деле научился编译原理Это действительно влияет на то, как я думаю.
Поэтому я извлек учебные материалы университета и объединил дополнительные материалы, чтобы завершить свой учебный курс.前端学编译原理Эта серия:

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

Зачем изучать принципы компиляции

Во-первых, я фронтенд-инженер, поэтому я думаю об этой проблеме с точки зрения фронтенда:

Зачем нам нужно изучать принципы компиляции?

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

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

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

  • eslint: проверка кода
  • es6, инструмент транскодирования ts: Babel (для преобразования кода, написанного на синтаксисе ECMAScript 2015+, в обратно совместимый синтаксис JavaScript), tsc (для преобразования TypeScript в код JavaScript)
  • Различные механизмы шаблонов (ввод строки шаблона + данные, получение отображаемой строки): он впервые появился при разработке динамических страниц на стороне сервера, таких как механизмы шаблонов, такие как JSP, PHP, ASP и т. д. С момента быстрого развития Node.js мир внешнего интерфейса произвел много колес, в том числе EJS, арт-шаблон, мопс, усы и т. д. 【Лично я мало что знаю о механизмах шаблонов.Перечисленные здесь механизмы шаблонов принадлежат всемогущим пользователям сети.
  • CSS Preprocessor.:sass, меньше и т.д., освободимся от косой черты и сгорим в эпоху чистого css. Это дает фронтенд-инженерам более мощные возможности написания стилей (хотя я могу использовать только мех, предоставленный ими, но поддержка вложенности CSS действительно мое сердце).
  • Приложения в основных фреймворках: В отличие от механизма шаблонов, не следует путать интерфейсный фреймворк и механизм шаблонов.Многие основные фреймворки используют принцип компиляции, включая vue, react и angular.
  • markdown: Например, я пишу свою статью в Наггетс, левая сторона — это синтаксис уценки, а правая сторона может синхронно просматривать окончательный эффект отображения ~
  • ...

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

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

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

Я не знаю, смогу ли я ясно объяснить такую ​​большую тему с моим неглубоким пониманием и плохим знанием языка, но это вопрос человеческих усилий, и я сделаю все возможное, чтобы эта серия стала возможной на основе обеспечения правильности. обновление на веб-сайте, и пусть каждый испытает красоту компиляции со мной с моей точки зрения.
Я также опубликовал много серий статей ранее:
Механизм рендеринга в браузере
Тема обещания
Если у вас есть интерес к вышеуказанному контенту, вы можете прочитать и обсудить со мной.Как новичок, который только что вошел в отрасль менее года, я также с нетерпением жду критики и исправлений от всех старших и старших. .

ладно, меньше сплетен, давайте к делу.

Языки программирования и компиляторы

Основные понятия языков низкого уровня

представлять:

включая машинный язык и язык ассемблера
машинный язык: Относится к языку программирования, который машина может напрямую распознать. Без перевода каждый код операции имеет соответствующую схему внутри компьютера для его завершения или относится к языку программирования или коду инструкции, который может быть непосредственно понят и принят машиной без перевода. Аппаратное обеспечение компьютера может распознавать только два физических состояния: «открыто» и «закрыто», то есть 0 и 1. Машинный язык использует абсолютные адреса и абсолютные коды операций. Разные компьютеры имеют свой машинный язык, то есть систему команд.Машинные языки разных типов компьютеров неодинаковы.Программа, составленная по машинным инструкциям одного компьютера, не может быть выполнена на другом компьютере. С точки зрения использования машинный язык является языком самого низкого уровня.

  • код операции: код операции дает функцию завершения инструкции
  • адресный код: Код адреса дает адрес, связанный с операндом или самим операндом.
  • Команда 10110110【Код операции】 00000000【Код адреса】 Указывает операцию сложения
  • Команда 10110101【Код операции】 00000000【Код адреса】 Указывает на операцию вычитания

язык ассемблера: любой язык низкого уровня, используемый в электронных компьютерах, микропроцессорах, микроконтроллерах или других программируемых устройствах, также известный как符号语言. В языке ассемблера мнемоники (Mnemonics) используются для замены кодов операций машинных инструкций, а адресные символы (Symbols) или метки (Label) используются для замены адресов инструкций или операндов. В разных устройствах язык ассемблера соответствует разным наборам инструкций машинного языка и преобразуется в машинные инструкции в процессе сборки. Вообще говоря, существует однозначное соответствие между определенным языком ассемблера и набором инструкций определенного машинного языка, и он не может быть напрямую перенесен между различными платформами. Например,а = а + б выражение:

  • MOV AX,1
  • MOV BX,2
  • ADD AX,BX

ps: По сравнению с предыдущими 0 и 1 сейчас можно примерно понять?

преимущество:

  • высокоскоростной

недостаток:

  • Трудно понять, высокий уровень ошибок, сложно поддерживать
  • Зависит от конкретной машины, плохая переносимость

Обнаружить:

  • Язык более низкого уровня более дружелюбен к машине и больше соответствует образу мышления машины, поэтому эффективность выполнения высока.
  • Чем более совершенен язык, тем более он дружелюбен к людям и тем больше соответствует образу человеческого мышления, поэтому эффективность разработки высока.

Основные понятия языков высокого уровня

формальный язык

представлять:

Язык, определяемый точными математическими или машинно-обрабатываемыми формулами. Соответствуя естественному языку, естественный язык — это язык, на котором говорят люди.Этот вид языка считается не разработанным, а естественным образом развившимся. Формальные языки — это искусственно созданные языки для конкретных приложений.Существуют разные области, такие как различные символы операций для математиков, различные молекулярные формулы для химиков и编程语言也是一种形式语言,是专门设计用来表达计算过程的形式语言.

Функции:

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

язык высокого уровня

представлять:

По сравнению с низкоуровневыми языками язык программирования с высокой степенью инкапсуляции ближе к нашему нормальному человеческому мышлению.Его главная особенность заключается в том, что его легко писать, а код читабельен. Достижение той же функции занимает меньше времени с использованием языка высокого уровня, а программный код короче и легче читается. Во-вторых, языки высокого уровня переносимы, то есть фрагмент кода можно запускать на разных типах компьютеров практически без модификации. Языки, которые сегодня использует большинство людей, такие как C, C++, Python, Java, Javascript и т. д., являются языками высокого уровня.

преимущество:

  • естественное выражение
  • Легче учиться, легче понимать, легче модифицировать
  • высокая портативность

недостаток:

  • Запуск требует поддержки других программ (компилятор и т.д.)
  • По сравнению со сравнением
  • Занимает относительно больше места

Выполнение высокоуровневых программ и программ на ассемблере

переводчик

Переводчик может перевести программу, написанную на одном языке программирования, на другой язык программирования.输入对象是源程序, как правило, программа, написанная на языке высокого уровня,输出对象是目标程序Однако это может быть машинный язык, язык ассемблера, пользовательская программа на промежуточном языке или другие расширенные языки. Программа перевода может включать:

  • Ассемблер
  • Компилятор
  • ...

image.png

Линкер:Буду目标文件内容вместе с运行时库程序синтезируется в计算机能够加载和执行的目标程序

способ исполнения

Существует три способа выполнения программ на языке высокого уровня:

  • Метод компиляции
  • способ интерпретации
  • Метод преобразования

Ниже я подробно расскажу об этом~

Составление и интерпретация

Метод компиляции image.png
способ интерпретации image.png Подробное введение
Здесь я впервые использую пример пользователей сети Zhihu, разница в этом процессе очень похожа:

A — носитель английского языка, B — аудитория, C — переводчик. Затем компилятор: переводчик организует все содержание речи А (после речи А) в переведенный файл за один раз и отправляет его аудитории Б для просмотра. Переводчик: когда переводчик С говорит, А произносит предложение, а С переводит предложение аудитории В.

На самом деле, этот пример все еще очень яркий, если резюмировать его следующим образом:

  • Компилятор генерирует инструкции целевой платформы перед запуском кода и может выполняться независимо от компилятора.
  • Интерпретатор генерирует инструкции целевой платформы во время выполнения кода, поэтому его нельзя запустить независимо от интерпретатора.

Итак, мы видим, что скомпилированные языки нужно скомпилировать, а затем запустить, в то время как интерпретируемые языки «запускают» исходный код напрямую.

то есть их根本区别То есть при запуске интерпретатор должен интерпретировать программу в инструкции целевой платформы для запуска, что занимает много процедур, в то время как тип компилятора уже позволяет компилятору скомпилировать программу в инструкции целевой платформы перед запуском, поэтому он быстрее.
пс: Здесь можно совместить спинку辩证的看 этот абзац лучше

Сравнение интерпретаторов и компиляторов с разных сторон

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

диалектически

Можно было бы посмотреть на это и под другим углом.На самом деле, если мы просто исходим из определения метода компиляции и метода интерпретации, они настолько несовместимы, но границы между компиляцией и интерпретацией не так четки.Например ( ниже есть блок-схема).Java необходимо заранее скомпилировать код в инструкции виртуальной машины, а затем запустить эти инструкции виртуальной машины.Некоторые учебники станут гибридными или полукомпилируемыми.Одним из преимуществ этого является то, что байт-код компилируется на одной машине.Его можно интерпретировать и выполняться на другой машине, а миграция между машинами может быть выполнена через сеть. Так что на самом деле нам немного неразумно их раздирать.Я также обнаружил, что у многих людей разные мнения на этот счет.На мой взгляд,выполнение нашего высокоуровневого кода есть не более чем переход от высокоуровневой абстракции к низкоуровневое выполнение кода. Процесс иерархической абстракции. В этом процессе мы можем использовать интерпретатор или компилятор. Нет конфликта между использованием двух. Как и в приведенном выше примере, это не что иное, как то, что мы можем снижение уровня абстракции кода.В процессе есть разные этапы, и используются разные схемы.Будь то компиляция и выполнение или интерпретация и выполнение, это не должно иметь ничего общего с языком, но какая схема используется сделать код понятным для машины, поэтому纠结一个语言是解释型还是编译型语言在我的认知中是不必要из

Блок-схема предыдущего абзаца на Java:
image.png

Метод преобразования

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

  • Если мы хотим реализовать язык L
  • Теперь у нас есть компилятор для языков L1.
  • Затем мы можем сначала преобразовать программу, написанную на языке L, в эквивалентную программу на языке L1.
  • Перейдите к использованию компилятора языка L1 для реализации L

Ясно, что мы используем конвертер без компилятора языковой программы L L1 в существующий компилятор, чтобы преобразовать его для перехода к целевой программе. .image.png

Структура компилятора

Введение. Никто не является островом, как и компиляторы.

Языки программирования - это нотации, которые описывают вычислительные процессы как для людей, так и для машин.Мир зависит от языков программирования, потому что все программное обеспечение, которое работает на всех компьютерах, написано на каком-то языке программирования, но прежде чем программа сможет работать, ей необходимо быть сначала переведены в исполняемую компьютером форму. Что представляет из себя этот перевод?编译器. Проще говоря, компилятор — это программа, которая может прочитать программу, написанную на одном языке, и преобразовать ее в эквивалентную программу, написанную на другом языке.
—— Цитата из введения к главе 1 «Принципов компиляции (второе издание)».

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

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

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

image.pngХорошо, мы представили компилятор и его партнеров, так что давайте взглянем на внутреннюю структуру таинственного внешнего вида компилятора.

Обзор внутренней структуры компилятора

С точки зрения наших разработчиков, мы пишем код, а затем компилируем и запускаем его. На самом деле, большую часть времени мы не знаем о компиляторе. Мы можем чаще нажимать «запустить», а затем кричать «Старт ссылки»! Код начинает работать.Конечно, предполагается, что мало кто будет иметь такое чувство ритуала (на самом деле, нормальные люди называют такое поведение миддл 2). Так что компилятор для нас как черный ящик, приоткрываем его и видим, что он состоит из двух частей:

  • Раздел анализа
  • Общий раздел

Часто часть анализа называетсявнешний интерфейс, интегральная часть называетсязадняя часть.

Аналитическая часть (передняя часть)

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

Часть анализа также собирает информацию об исходной программе и сохраняет информацию в файле с именем符号表в структуре данных (后期寒草: "Таблица символов будет упомянута много раз позже~"). Таблицы символов и представления промежуточного кода используются в качестве входных данных для секции синтеза.

Интегрированная часть (бэкенд)

Часть синтеза строит целевую программу, ожидаемую пользователем, в соответствии с информацией в промежуточном представлении и таблице символов.

Пошаговое введение в компилятор

В последнем абзаце мы разделили компилятор на две фазы: front-end и back-end. Но если мы сможем подробно изучить процесс компиляции, мы обнаружим, что он будет последовательно выполнять набор шагов, типичный способ разложения принципа компиляции на несколько шагов.Следующие две картинки. Конечно, на практике несколько шагов могут быть сгруппированы вместе, и нет необходимости создавать промежуточные представления между сгруппированными шагами.存放整个源程序的信息的符号表可以由编译器的各个步骤使用.

image.pngСреди них, чтобы создать лучшую целевую программу для части синтеза (внутренняя программа), если код генерируется на основе неоптимизированного промежуточного представления, это повлияет на качество кода, поэтому может быть добавлен этап оптимизации кода. Два этапа оптимизации кода на рисунке можно опустить.

Итак подведем краткие итоги, по сути весь процесс можно примерно описать как следующие этапы:

  • лексический анализ
  • Разбор
  • Семантический анализ
  • Генерация промежуточного кода
  • Промежуточная оптимизация кода
  • генерация объектного кода

лексический анализ

представлять

Первым шагом компилятора является лексический анализ, входом которого является последовательность символов исходной программы. Определите каждое слово и его тип и представьте его в форме TOKEN:image.png tip:

  • Этап лексического анализа не зависит от определения грамматики языка.
  • Результат лексического анализа является входом грамматического анализа.

Лексический анализ также может:

  • Обнаружение идентификаторов с ошибками
  • Удалить комментарии из кода

Пример

Например, вы можете понять:

float sum, first;
sum = first + 10;

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

image.pngМогут быть отличия в реализации.Здесь,чтобы всем было понятнее,все упрощено,но мы все же можем понять по этому.Я думаю вы сможете понять процесс после прочтения примера.

Почему первая сумма становится идентификатором 1. На самом деле соответствующее значение после идентификатора фактически указывает на符号表Ссылка, первая соответствует 2 по той же причине

морфема: Наименьшая единица грамматических функций. Вышеупомянутые float, sum, first, + и т. д. являются морфемами.

Разбор

представлять

Разбор — это второй шаг компилятора, при разборе будет использоватьсяПоследовательность TOKEN, сгенерированная лексическим анализом, и согласноГрамматические правила исходного языкаПромежуточное представление связующего дерева. Это промежуточное представление дает грамматическую структуру потока токенов, полученного в результате лексического анализа.

наконечник:

  • Если при анализе обнаружены ошибки, вывод места ошибки и типа
  • Если ошибок не обнаружено, входные данные синтаксического анализа (выходные данные лексического анализа) преобразуются в промежуточную форму дерева.синтаксическое дерево

Синтаксическое дерево: каждый внутренний узел в дереве представляет операцию, а дочерние узлы этого узла представляют компоненты этой операции.

войти:

  • Когда лексический анализатор является подпрограммой анализатора: на вход подается последовательность символов исходной программы.
  • Когда лексический анализ независим: вход представляет собой последовательность токенов

Пример

Продолжите предыдущий пример лексического анализа. Прежде всего, наш пример по-прежнему равен sum=first+10. Его соответствующая последовательность TOKEN лексического анализа:
<标识符,1> <运算符,=> <标识符,2> <运算符,+> <整形常量,10> <分隔符,;>

где 1 соответствует сумме, а 2 соответствует первой.

image.png

Семантический анализ

представлять

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

  • Проверьте исходную программу на предмет семантических ошибок.
  • Сбор информации о типе для генерации кода

проверка типов: проверка типов является важной частью семантического анализа.Компилятор проверяет, есть ли у каждого оператора соответствующий компонент, например:

  1. Нижний индекс массива должен быть целым числом, и при использовании числа с плавающей запятой в качестве нижнего индекса будет сообщено об ошибке.
  2. Условное выражение должно быть логическим
  3. Полно ли значение оператора присваивания
  4. ...

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

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

Пример

См. комментарии для семантических ошибок:

float sum, first;
sum = first + 10;
count = sum; //count无定义
first = sum % 10;//sum是浮点型,不能进行取余数运算

Генерация промежуточного кода

представлять

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

Синтаксическое дерево — это промежуточное представление, используемое как в синтаксическом, так и в семантическом анализе.

После завершения синтаксического и семантического анализа многие компиляторы генерируют явное низкоуровневое или машиноподобное промежуточное представление. Это промежуточное представление должно обладать двумя важными свойствами:

  • 易于生成
  • 可以轻松的翻译为目标机器上的语言

Конечно, этот промежуточный код может существовать во многих формах:

  • 后缀式(栈式)中间代码
  • 三地址中间代码(三元式和四元式)
  • 图结构的中间代码(树,DAG)

Пример

Код:

float sum, first, count;
sum = first + count * 10;

Промежуточный код (четвертичный):

(int-to-float, 10, , t1)
(*, count, t1, t2)
(+, first, t2, t3)
(=, t3, , sum)

Кратко объясните:

  • Счетчик и первый в реальном промежуточном коде будут представлены как ссылки в таблице символов.
  • (*, count, t1, t2) в качестве примера означает, что t2 = t1 * count

О трехадресной инструкции:

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

Оптимизация кода

представлять

Цель: Улучшение промежуточного кода с целью создания лучшего объектного кода.

Лучше обычно означает быстрее, но могут быть и другие цели, например, более короткий или менее энергозатратный код.

Объем работы, выполняемой разными компиляторами в процессе оптимизации кода, может сильно различаться, и те компиляторы, которые выполняют большую работу по оптимизации (так называемые优化编译器) будет тратить много времени на этапе оптимизации, а некоторые простые методы оптимизации могут значительно повысить эффективность работы целевой программы без слишком большого снижения скорости компиляции.

Общие методы оптимизации:

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

Пример

Промежуточный код (четвертичный):

(int-to-float, 10, , t1)
(*, count, t1, t2)
(+, first, t2, t3)
(=, t3, , sum)

Оптимизация постоянного выражения:

(*, count, 10.0, t2)
(+, first, t2, t3)
(=, t3, , sum)

генерация объектного кода

представлять

Генератор кода принимает промежуточное представление исходной программы (промежуточный код) в качестве входных данных и отображает его на целевой язык. Если целевой язык — машинный код, то:

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

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

Пример

Исходная программа:

float sum, first, count;
sum = first + count * 10;

Код сборки:

MOV count, R1
MULT R1, #10.0
MOV first, R2
ADD R1, R2
MOV R1, sum

Краткое содержание главы

Согласно предыдущему введению, компилятор можно условно разделить на следующие этапы:

  • лексический анализ
  • Разбор
  • Семантический анализ
  • Генерация промежуточного кода
  • Промежуточная оптимизация кода
  • генерация объектного кода

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

заключительные замечания

image.pngСодержание статьи взято из:

  • «Теория компилятора (второе издание)»
  • Программа обучения альма-матер
  • Вопросы и ответы, проверенные и проверенные мной
  • Мое понимание (мое понимание, вероятно, наименее авторитетная часть, ххх)

Содержание темы больше и глубже.Если есть проблемы, то это может быть неизбежно.Надеюсь, вы дадите мне свой совет.Если будут проблемы, я буду их активно исправлять~

Я также надеюсь, что вы заинтересованы и можете поддержать мою предыдущую серию статей:
Механизм рендеринга в браузере
Тема обещания
...
Не только это, но и много интересного контента:
Домашняя страница Cold Grass Nuggets
наш гитхаб
наконец! ! !
少年与爱永不老去,即便披荆斩棘,丢失怒马鲜衣
я холодная трава
Прерывистая кровь, непрерывная скульптура из песка, надежда вырасти вместе со всеми и стать партнерами, которые работают вместе.
WeChat: hancao97