Разное

Компилятор что это: Что такое компилятор? – Hexlet Guides

Содержание

Что такое компилятор

Если вы программист, то наверняка слышали слово “компилятор”. Но знаете ли вы, что это такое на самом деле? Вы когда-нибудь задумывались, что происходит под капотом, когда вы запускаете команду javac(если у вас код на Java)? Вы когда-нибудь хотели создать свой собственный язык программирования?  —  и просто заводили бесполезный репозиторий GitHub, где все равно есть только один readme.md, потому что вы даже не знаете, с чего начать. Я думаю, что начинать стоит с этого: узнать больше о компиляторе.

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

  • введение в компилятор;
  • типы компиляторов;
  • архитектура компилятора.

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

Вступление

Компилятор  —  это не что иное, как переводчик исходного кода.

Задача компилятора  —  перевести исходный код с одного языка на другой. Это означает, что если вы скормите компилятору исходный код Java, то сможете получить исходный код Python (не самый лучший пример, просто для понимания сути. На самом деле вы получите байт-код Java, который можно запустить на JVM). Для выполнения этого процесса у компилятора есть несколько взаимосвязанных компонентов.

Типы компиляторов

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

Классификация компиляторов в соответствии с этапами компиляции

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

Таким образом, в соответствии с этой классификацией можно выделить три типа компиляторов:

  1. Однопроходной компилятор.
  2. Двухпроходной компилятор.
  3. Многопроходной компилятор.

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

Классификация компиляторов в соответствии с исходным кодом и целевым кодом

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

  1. Кросс-компиляторы  —  такие компиляторы работают на одной платформе и производят код для запуска на другой платформе. Например, компилятор работает на платформе X и создает код для запуска на платформе Y. Такими компиляторами пользуются разработчики встроенных систем.
  2. Традиционные компиляторы  —  нам лучше всего знаком именно этот тип компиляторов. Такие компиляторы преобразуют исходный код языка высокого уровня в исходный код машинного языка. Набор компиляторов GCC преобразует эти языки в низкоуровневые, которые выполняются на этих платформах.
  3. Транспилеры  —  они преобразуют исходный код языка высокого уровня в исходный код другого языка высокого уровня. Например, Babel transpiler преобразует ECMAScript 2015+ в JavaScript.
  4. Декомпиляторы  —  они принимают низкоуровневый исходный код в качестве входных данных и пытаются создать высокоуровневый исходный код, который может быть успешно перекомпилирован.

Архитектура компилятора

Когда компилятор компилирует (переводит) исходный код, он проходит несколько этапов:

  1. Исходный код.
  2. Лексический анализ.
  3. Синтаксический анализ.
  4. Семантический анализ.
  5. Промежуточная генерация кода.
  6. Оптимизация кода.
  7. Генерация кода.
  8. Целевой код.

Мы можем разделить все эти этапы на две фазы, примерно как фронтенд и бэкенд. Эти фазы включают в себя следующие этапы:

Фронтенд

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

Бэкенд

  • Оптимизация кода.
  • Генерация кода.

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

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

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

KEYWORD, BRACKET, IDENTIFIER, OPERATOR, NUMBER на приведенной выше диаграмме  —  это и есть маркеры. Компилятор использует лексический анализ для идентификации маркеров, и если он получает маркер, который не определен заранее в грамматике языка, то это будет считаться ошибкой.

Синтаксический анализ (парсинг)

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

Здесь мы сначала определили грамматику. Затем компилятор пытается построить дерево синтаксического анализа для исходного кода 2 + 3 * 3. В этом случае компилятору удается построить дерево синтаксического анализа (с правой стороны) в соответствии с грамматикой, следовательно в этой программе нет синтаксических ошибок.

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

Просто потому, что программа не содержит синтаксических ошибок, код еще не может считаться правильным. Рассмотрим предложение ниже.

I love compilers

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

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

Теперь рассмотрим предложение ниже.

I eat compilers

Предположим, что eat  —  правильный маркер в соответствии с грамматикой. Таким образом, предложение признается правильным на этапе лексического и синтаксического анализа, поскольку слова расположены в правильном порядке. Но в этом предложении нет никакого смысла  —  никто не может есть компиляторы.

Итак, согласно этапу семантического анализа, эта программа содержит ошибку. Мы называем эту разновидность ошибок семантическими ошибками. Взгляните на этот простой Java-код:

class SemanticAnalysis{
  public static void main(String[] args){
    int a = 5;
    int b = 10;
    int total = c + d;
  }
}

Здесь нет синтаксических ошибок. Все маркеры упорядочены правильно. Но на пятой строке int total = c + d  —  не имеет никакого значения, так как идентификаторы c и d не определены. Это и есть семантическая ошибка. 

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

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

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

Существует два основных типа промежуточных представлений:

  • Высокоуровневый  —  более близкий к высокоуровневому языку.
  • Низкоуровневый  —  более близкий к машинному коду.

Существует также несколько способов представления промежуточного представления.

  • AST  —  абстрактное синтаксическое дерево (графическое).
  • Постфиксная нотация.
  • Трехадресный код.
  • Двухадресный код.

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

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

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

Существует два способа оптимизации кода:

  • Машинно-независимая оптимизация.
  • Машинно-зависимая оптимизация.

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

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

Генерация кода

Генерация кода  —  это последний этап процесса компиляции. Да, после может следовать машинно-зависимая оптимизация кода. Но мы можем рассматривать и то, и другое вместе как генерацию кода. На этом этапе компилятор генерирует машинно-зависимый код. Генератор кода должен иметь представление о среде выполнения целевой машины и ее наборе команд.

На этом этапе компилятор выполняет несколько основных задач:

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

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

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

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Buddhika Chathuranga: “What is the Compiler”

Компилятор — это… Что такое Компилятор?

  • КОМПИЛЯТОР — (ново лат., от лат. compilare грабить, обирать, выбирать). Составитель статей или книг путем заимствования отрывков из сочинений разных авторов. Словарь иностранных слов, вошедших в состав русского языка. Чудинов А.Н., 1910. КОМПИЛЯТОР… …   Словарь иностранных слов русского языка

  • компилятор — См. писатель… Словарь русских синонимов и сходных по смыслу выражений. под. ред. Н. Абрамова, М.: Русские словари, 1999. компилятор автор, писатель; транслятор, халтурщик, программа Словарь русских синонимов …   Словарь синонимов

  • КОМПИЛЯТОР — КОМПИЛЯТОР, КОМПЬЮТЕРНАЯ ПРОГРАММА, которая переводит символы ЯЗЫКА ПРОГРАММИРОВАНИЯ в команды, которые может непосредственно воспринимать компьютер. Программы по большей части пишутся на ЯЗЫКАХ ВЫСОКОГО УРОВНЯ, таких как «Си», Паскаль или Бейсик …   Научно-технический энциклопедический словарь

  • КОМПИЛЯТОР — КОМПИЛЯТОР, компилятора, муж. (книжн.). Автор компиляции. || Литератор, способный писать только компиляции (пренебр.). Жалкий компилятор. Толковый словарь Ушакова. Д.Н. Ушаков. 1935 1940 …   Толковый словарь Ушакова

  • компилятор — а, м. compilateur <, лат. compilator. Автор компиляции, лицо, занимающееся компиляцией (заимствованием материалов, изложением результатов чужих трудов без самостоятельной обработки источников). БАС 1. Собирающий из разных сочинений в одно;… …   Исторический словарь галлицизмов русского языка

  • КОМПИЛЯТОР — (англ. compiler от compile составлять компилировать), в информатике то же, что транслятор …   Большой Энциклопедический словарь

  • КОМПИЛЯТОР — КОМПИЛЯТОР, а, муж. (книжн.). Человек, к рый занимается компиляцией. | жен. компиляторша, и (разг.). | прил. компиляторский, ая, ое. Толковый словарь Ожегова. С.И. Ожегов, Н.Ю. Шведова. 1949 1992 …   Толковый словарь Ожегова

  • КОМПИЛЯТОР — (compiler) Компьютерная программа, переводящая программу, написанную на языке высокого уровня (high level language), в подробные команды (называемые машинным кодом (machine code), которые компьютер может выполнить. Программа должна быть… …   Словарь бизнес-терминов

  • компилятор — Программа или техническое средство, выполняющие компиляцию. [ГОСТ 19781 90] Тематики обеспеч. систем обраб. информ. программное EN compiler …   Справочник технического переводчика

  • Компилятор — в вычислительной технике, то же, что транслятор.   …   Иллюстрированный энциклопедический словарь

  • 1.3 Компилятор и интерпретатор — Основы программирования

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

    Компилятор

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

    На картинке показано базовое очертание процесса компиляции. Тут программа написанная на языке высокого уровня показана как «Исходный код», а сконвертированный называется «Исполняемый код».

    Интерпретатор

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

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

    Ниже перечислены главные отличия между компилятором и интерпретатором:

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

    Компилятор в программировании — простыми словами + ссылки

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

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

    IdeOne

    Онлайн компилятор кода IdeOne оснащен интегрированным отладчиком, предоставляющим возможность выполнять код непосредственно в браузере. Эта онлайн-программа поддерживает компиляцию на более чем 60 языках. В частности, ее можно использовать для компиляции на Java, PHP, C++, Phyton и т.д.

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

    Repl.it

    Работа с этим онлайн-компилятором не вызовет никаких трудностей. Для компиляции проекта необходимо только выбрать язык программирования и добавить исходный код. Интерфейс Repl.it также достаточно прост. Он состоит из двух столбцов – редактора и консоли. Для того чтобы выполнить онлайн компиляцию необходимо нажать комбинацию клавиш Ctrl+Enter. Этот компилятор оснащен функцией автоматического дополнения и подсветки синтаксиса.

    CodePad

    Изучая бесплатные компиляторы для языков программирования, стоит отметить сервис CodePad. Его главным преимуществом является простота применения. Этот сервис позволяет хранить код и делиться результатами компилирования с другими разработчиками. CodePad также оснащен функцией автоматического подключения стандартных заголовков и возможностью интеграции с Vim/Emacs.

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

    Koding

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

    Hackerearth

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

    Особенностью этого сервиса считается современный и красивый интерфейс.

    PHPFiddle и SandBox

    Эти сервисы обеспечивают запуск PHP кода и получение результата его компиляции в один клик. Данные компиляторы практически не имеют различий. Основная разница заключается в более удобном дизайне PHPFiddle.

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

    GCC GodBolt

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

    GCC GodBolt

    OnlineGDB и C++ shell

    Еще один пример простых и доступных онлайн-комплиляторов для C и C++. Следует заметить, что оба сервиса оснащены отладчиком. Главным отличием между этими программами является тот факт, что OnlineGDB поддерживает не только C и C++, но и другие популярные языки программирования – PHP, Python, Ruby, Java и т.д.

    Codingground

    На этом сайте представлены различные компиляторы для преобразования кода, написанного на F#, Swift 4.0, Rust, Lisp, Julia и других языках программирования. Пользователи могут самостоятельно задавать параметры сборки. Более того, Codingground позволяет собирать множество файлов в один проект.

    Теги:

    Что делает компилятор just-in-time (JIT)?

    Что конкретно делает компилятор JIT в отличие от компилятора, не являющегося JIT? Может ли кто-нибудь дать краткое и понятное описание?

    compilation

    compiler-construction

    jit

    Поделиться

    Источник


    Michiel Borkent    

    18 сентября 2008 в 18:52

    18 ответов


    • CUDA Шаблоны выражений и компиляция Just in Time (JIT)

      У меня есть несколько вопросов о компиляции Just-In-Time (JIT) с CUDA. Я реализовал библиотеку на основе шаблонов выражений в соответствии с этой статьей J.M. Коэн, обработка массивов устройства C метапрограммирования с++, GPU вычислительной драгоценные камни — нефрит издание Кажется, это работает…

    • Что делает компилятор JIT?

      Я просто смотрел видео Google IO, и они говорили о компиляторе JIT, который они включили в android. Они показали демонстрацию улучшений производительности благодаря компилятору JIT. Я задавался вопросом, что именно делает компилятор JIT, и хотел услышать от разных людей. Итак, в чем же заключается…



    529

    Компилятор JIT запускается после запуска программы и компилирует код (обычно байт-код или какие-то инструкции VM) на лету (или just-in-time, как его называют) в форму, которая обычно быстрее, как правило, собственный набор команд хоста CPU. A JIT имеет доступ к динамической информации времени выполнения, в то время как стандартный компилятор этого не делает, и может делать лучшие оптимизации, такие как встроенные функции, которые часто используются.

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

    Перефразируя, обычные компиляторы строят всю программу как EXE файл BEFORE при первом запуске. Для более новых программ стиля assembly генерируется с псевдокодом (p-код). Только AFTER вы выполняете программу на OS (например, дважды щелкнув по ее значку), компилятор (JIT) включится и сгенерирует машинный код (m-код), который поймет процессор Intel или что-то еще.

    Поделиться


    Mark Cidade    

    18 сентября 2008 в 18:55



    260

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

    В какой-то момент эволюции языков компиляторы компилировали язык высокого уровня в псевдокод, который затем интерпретировался (интерпретатором) для запуска вашей программы. Это устранило объектный код и исполняемые файлы и позволило переносить эти языки на несколько операционных систем и аппаратных платформ. Pascal (который компилировался в P-код) был одним из первых; Java и C#-более поздние примеры. В конце концов термин P-код был заменен байт-кодом, так как большинство псевдо-операций имеют длину в байт.

    Компилятор Just-In-Time (JIT)-это функция интерпретатора времени выполнения, которая вместо интерпретации байт-кода при каждом вызове метода компилирует байт-код в инструкции машинного кода запущенной машины, а затем вызывает этот объектный код. В идеале эффективность выполнения объектного кода преодолеет неэффективность перекомпиляции программы при каждом ее запуске.

    Поделиться


    Craig Trader    

    18 сентября 2008 в 19:06



    69

    JIT-как раз вовремя
    само слово говорит, когда оно нужно (по требованию)

    Типичный сценарий:

    Исходный код полностью преобразуется в машинный код

    JIT сценарий:

    Исходный код будет преобразован в assembly language like structure [for ex IL (intermediate language) for C#, ByteCode for java].

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

    Сравнение JIT против не-JIT:

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

    • Как машинный код будет сгенерирован при запуске time….the JIT
      компилятор будет создавать машинный код, оптимизированный для работы
      архитектуры CPU машины.

    JIT примеры:

    1. В Java JIT находится в JVM (виртуальная машина Java)
    2. В C# он находится в CLR (Common Language Runtime)
    3. В Android он находится в DVM (виртуальная машина Dalvik) или ART (Android RunTime) в более новых версиях.

    Поделиться


    Durai Amuthan.H    

    29 апреля 2013 в 08:55


    • Как узнать Just-in-Time компиляцию?

      Существует множество книг, объясняющих традиционные статические теории и методы компиляции, но в этих книгах мало говорится о компиляторах Just-in-Time. Хотя чтение исходного кода JIT — это способ обучения,код не всегда ясно объясняет предпосылки и проблемы для решения. Каков наилучший способ…

    • Есть ли что-то вроде «compile-time JIT»?

      Насколько я понимаю, JIT (компиляция just-in-time) относится к процессу выполнения, в котором байт-код компилируется (переводится) в машинный код для повышения производительности во время выполнения. С другой стороны, оценка времени компиляции является обычной практикой для общего программирования…



    26

    Как уже упоминали другие

    JIT означает Just-in-Time, что означает, что код компилируется тогда, когда это необходимо, а не перед выполнением.

    Просто чтобы добавить точку в вышеприведенное обсуждение, JVM ведет подсчет того, сколько раз выполняется функция. Если это число превышает заданный предел, JIT компилирует код на машинный язык, который может быть непосредственно выполнен процессором (в отличие от обычного случая, когда javac компилирует код в байт — код, а затем java-интерпретатор интерпретирует этот байт-код построчно, преобразует его в машинный код и выполняет).

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

    Поделиться


    Aniket Thakur    

    10 декабря 2013 в 13:20



    14

    Компилятор JIT компилирует байт-код только в эквивалентный машинный код при первом выполнении. При каждом последующем выполнении JVM просто использует уже скомпилированный машинный код для оптимизации производительности.

    Без компилятора JIT интерпретатор JVM переводит байт-код line-by-line, чтобы он выглядел так, как будто выполняется собственное приложение.

    Источник

    Поделиться


    Unknown    

    19 января 2018 в 04:37



    12

    JIT означает Just-in-Time, что означает, что код компилируется тогда, когда это необходимо, а не перед выполнением.

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

    Поделиться


    Brian Lyttle    

    18 сентября 2008 в 19:00



    9

    После того, как байт-код (который является архитектурно нейтральным) был сгенерирован компилятором Java, выполнение будет обработано JVM (в Java). Байтовый код будет загружен загрузчиком в JVM, а затем каждая байтовая инструкция будет интерпретирована.

    Когда нам нужно вызвать метод несколько раз, нам нужно интерпретировать один и тот же код много раз, и это может занять больше времени, чем требуется. Итак, у нас есть компиляторы JIT (just-in-time). Когда байт был загружен в JVM (его время выполнения), весь код будет скомпилирован, а не интерпретирован, что сэкономит время.

    Компиляторы JIT работают только во время выполнения, поэтому у нас нет никакого двоичного вывода.

    Поделиться


    User    

    10 августа 2012 в 08:46



    7

    Just In Time Compiler (JIT) :

    Он компилирует байт-коды java в машинные инструкции этого конкретного CPU.

    Например, если у нас есть оператор цикла в нашем коде java :

    while(i<10){
        // ...
        a=a+i;
        // ...
     }
    

    Приведенный выше код цикла выполняется 10 раз, если значение i равно 0.

    Нет необходимости компилировать байт-код 10 раз снова и снова, так как одна и та же инструкция будет выполняться 10 раз. В этом случае необходимо скомпилировать этот код только один раз, и значение может быть изменено необходимое количество раз. Таким образом, компилятор Just In Time (JIT) отслеживает такие операторы и методы (как было сказано выше) и компилирует такие фрагменты байтового кода в машинный код для лучшей производительности.

    Другой подобный пример заключается в том, что поиск шаблона с использованием «Regular Expression» в списке strings/sentences.

    JIT компилятор не компилирует весь код в машинный код. Он компилирует код, который имеет аналогичный шаблон во время выполнения.

    См. эту документацию Oracle на Understand JIT, чтобы узнать больше.

    Поделиться


    Anands23    

    27 февраля 2016 в 02:25



    4

    У вас есть код, который компилируется на какой-то IL (промежуточный язык). Когда вы запускаете свою программу, компьютер не понимает этот код. Он понимает только машинный код. Таким образом, компилятор JIT компилирует ваш IL в машинный код на лету. Он делает это на уровне метода.

    Поделиться


    Charles Graham    

    18 сентября 2008 в 18:56



    4

    Я знаю, что это старый поток, но оптимизация времени выполнения-еще одна важная часть компиляции JIT, которая, похоже, здесь не обсуждается. В принципе, компилятор JIT может контролировать программу во время ее выполнения, чтобы определить способы улучшения выполнения. Затем он может вносить эти изменения на лету — во время выполнения. Google JIT optimization (javaworld имеет довольно хорошую статью об этом. )

    Поделиться


    eze    

    21 марта 2014 в 13:36



    3

    Компилятор just in time (JIT) — это часть программного обеспечения, которая принимает неисполняемые входные данные и возвращает соответствующий машинный код для выполнения. Например:

    Intermediate representation    JIT    Native machine code for the current CPU architecture
    
         Java bytecode            --->        machine code
         Javascript (run with V8) --->        machine code
    

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

    Разница компилятора, интерпретатора и JIT

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

    1. Компилятор: принимает исходный код и возвращает исполняемый файл
    2. Интерпретатор: выполняет программу инструкция за инструкцией. Он берет исполняемый сегмент исходного кода и превращает этот сегмент в машинные инструкции. Этот процесс повторяется до тех пор, пока весь исходный код не преобразуется в машинные инструкции и не выполняется.
    3. JIT: возможно множество различных реализаций a JIT, однако a JIT обычно представляет собой комбинацию комплайлера и интерпретатора. JIT первые промежуточные данные поворота (например, Java байт-код), который он получает в машинный язык через интерпретацию. A JIT часто может чувствовать, когда определенная часть кода выполняется часто, и будет компилировать эту часть для более быстрого выполнения.

    Поделиться


    Willem van der Veen    

    26 сентября 2018 в 17:15



    2

    Jit расшифровывается как Just in time compiler
    jit-это программа, которая превращает java байт-код в инструкцию, которая может быть отправлена непосредственно в процессор.

    Использование компилятора java just in time (на самом деле второго компилятора) на конкретной системной платформе соответствует байт-коду в конкретный системный код,после того как код был повторно скомпилирован компилятором jit ,он обычно будет работать быстрее в компьютере.

    Компилятор just-in-time поставляется вместе с виртуальной машиной и используется опционально. Он компилирует байт-код в специфичный для платформы исполняемый код, который немедленно выполняется.

    Поделиться


    user3459027    

    16 апреля 2014 в 06:41



    2

    just-in-time (JIT) компиляция (также динамическая трансляция или компиляция во время выполнения) – это способ выполнения компьютерного кода , который включает компиляцию во время выполнения программы – во время выполнения- а не до выполнения .

    Компиляция IT представляет собой комбинацию двух традиционных подходов к переводу в машинный код – компиляции ahead-of-time (AOT) и интерпретации – и сочетает в себе некоторые преимущества и недостатки обоих. JIT компиляция сочетает в себе скорость компилируемого кода с гибкостью интерпретации .

    Давайте рассмотрим JIT, используемый в JVM,

    Например, компиляторы HotSpot JVM JIT генерируют динамические оптимизации. Другими словами, они принимают решения по оптимизации во время работы приложения Java и генерируют высокопроизводительные собственные машинные инструкции , предназначенные для базовой архитектуры системы.

    Когда метод выбран для компиляции, JVM передает свой байт-код компилятору Just-In-Time (JIT). JIT должен понять семантику и синтаксис байт-кода, прежде чем он сможет правильно скомпилировать метод. Чтобы помочь компилятору JIT проанализировать метод, его байт-код сначала переформулируется во внутреннее представление, называемое деревьями trace, которое больше напоминает машинный код, чем байт-код. Затем анализ и оптимизация выполняются на деревьях метода. В конце деревья переводятся в машинный код.

    Дерево trace-это структура данных,которая используется при компиляции программного кода во время выполнения. Trace деревья используются в типе «just in time compiler», который отслеживает выполнение кода во время горячих точек и компилирует его. Обратитесь к этому .

    Ссылаться :

    Поделиться


    prime    

    06 апреля 2018 в 09:44



    1

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

    Поделиться


    Unknown    

    18 сентября 2008 в 19:08



    0

    20% байт-кода используется 80% времени. Компилятор JIT получает эти статистические данные и оптимизирует этот 20% байт-код для более быстрой работы, добавляя встроенные методы, удаляя неиспользуемые блокировки и т. д., а также создавая байт-код, специфичный для этой машины. Я цитирую эту статью, я нашел ее удобной. http:/ / java.dzone.com / articles / just-time-compiler-jit-hotspot

    Поделиться


    Santosh budhe    

    06 июля 2014 в 10:12



    0

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

    Поделиться


    Venkata Santhosh Piduri    

    03 ноября 2014 в 13:08



    0

    JVM фактически выполняет шаги компиляции во время выполнения по соображениям производительности. Это означает, что Java не имеет четкого разделения компиляции и выполнения. Сначала он выполняет так называемую статическую компиляцию из исходного кода Java в байт-код. Затем этот байт-код передается в JVM для выполнения. Но выполнение байт-кода происходит медленно, поэтому JVM измеряет, как часто выполняется байт-код, и когда он обнаруживает «hotspot» кода, который выполняется очень часто, он выполняет динамическую компиляцию из байт-кода в машинный код кода «hotspot» (hotspot profiler). Так эффективно сегодня Java программ выполняются с помощью выполнения машинного кода.

    Поделиться


    hi.nitish    

    13 декабря 2015 в 05:21



    0

    Just In Time compiler, также известный как компилятор JIT, используется для
    повышения производительности в Java. Он включен по умолчанию. Это
    компиляция, выполняемая во время выполнения, а не раньше.
    Java популяризировал использование компилятора JIT, включив его в
    JVM.

    Поделиться


    Ganesh Giri    

    22 марта 2020 в 09:56


    Похожие вопросы:

    Какие оптимизации делают компилятор C# и компилятор JIT?

    Я продолжаю свою работу над компилятором C# для моего класса компиляторов. На данный момент я почти закончил главы по оптимизации компиляторов в моем учебнике. По большей части мой учебник не имел в…

    C# just-in-time (JIT) отладка вместо этого диалогового окна

    See the end of this message for details on invoking just-in-time (JIT) debugging instead of this dialog box. ************** Exception Text ************** System.InvalidOperationException: Failed to…

    Android TargetApi аннотация и компилятор Just-In-Time

    Я включаю поддержку Android Beam для нашего приложения. Но поскольку мы все еще поддерживаем 2.2 * кхе-кхе, кхе-кхе, кхе-кхе, кхе-кхе, кхе-кхе * я упаковал весь код NFC в классе NfcHandler с…

    CUDA Шаблоны выражений и компиляция Just in Time (JIT)

    У меня есть несколько вопросов о компиляции Just-In-Time (JIT) с CUDA. Я реализовал библиотеку на основе шаблонов выражений в соответствии с этой статьей J.M. Коэн, обработка массивов устройства C…

    Что делает компилятор JIT?

    Я просто смотрел видео Google IO, и они говорили о компиляторе JIT, который они включили в android. Они показали демонстрацию улучшений производительности благодаря компилятору JIT. Я задавался…

    Как узнать Just-in-Time компиляцию?

    Существует множество книг, объясняющих традиционные статические теории и методы компиляции, но в этих книгах мало говорится о компиляторах Just-in-Time. Хотя чтение исходного кода JIT — это способ…

    Есть ли что-то вроде «compile-time JIT»?

    Насколько я понимаю, JIT (компиляция just-in-time) относится к процессу выполнения, в котором байт-код компилируется (переводится) в машинный код для повышения производительности во время…

    Как компилятор just-in-time оптимизирует параллельные потоки Java?

    Некоторое время назад был задан интересный вопрос : Can (a == 1 && a == 2 && a == 3) evaluate to true in Java? Я решил доказать, что это возможно, используя Java 8 Stream API…

    Что может сделать компилятор JIT, чего не может сделать компилятор AOT?

    Компилятор Just-in-Time (JIT) может оптимизировать программу на основе информации о времени выполнения, недоступной компилятору Ahead-of-Time (AOT). Наиболее очевидным примером этой информации о…

    Почему компилятор JIT (Java)не сохраняет результаты?

    Как я изучал о компиляторе JIT отсюда: Что делает компилятор just-in-time (JIT)? и там нет *.exe или *.dll, сгенерированных Java JIT для Windows. Он записывает инструкции процессора в память (RAM) и…

    Как устроен компилятор? | KV.by

    В шестом номере
    «Компьютерных вестей» за этот
    год я рассказал вам о том, как
    устроен отладчик. Конечно, с тех пор
    прошло уже немало времени, но
    узнавать новое никогда не поздно.
    Сегодня мы с вами поговорим об
    устройстве ничуть не менее важного
    для программиста инструмента —
    компилятора.

    Конечно, во многих ВУЗах есть
    специальные курсы, посвящённые
    устройству различных компонентов
    современных компиляторов и
    интерпретаторов. И современные
    компиляторы слишком сложны для
    того, чтобы рассказать о них в одной
    статье достаточно подробно. Тем не
    менее, базовые механизмы работы
    компиляторов остались неизменными
    со времён выпуска первого
    компилятора языка Фортран.


    С высоты птичьего полёта…

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

    Итак, что же это за части? Это
    лексический анализатор, или сканер;
    синтаксический анализатор, или
    парсер; семантический анализатор; а
    также один или несколько
    генераторов кода и один или
    несколько оптимизаторов. Также к
    компилятору часто относят
    дополнительные инструменты, нужные
    для создания исполняемого файла —
    сборщик и компоновщик.

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


    От «А» до «Я»

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

    Следом за лексическим анализом
    может быть препроцессор. Тем, кто
    знаком с языками программирования C
    или С++, нет нужды объяснять, в чём
    состоит его функция. Для остальных
    же скажу, что основная задача
    препроцессора — это замена одних
    лексем другими, которые были
    заранее определены в тексте
    программы. Используется
    препроцессор также для условной
    компиляции (т.е. когда кусок кода
    должен быть откомпилирован только
    при выполнении определённых
    условий — для определённой
    платформы, только при отладочном
    билде и т.д. и т.п.), для выполнения
    определённых макросов (как в том же
    C/C++) и некоторых других подобных
    вещей. Препроцессор не является
    обязательной частью компилятора,
    поскольку многие языки
    программирования не нуждаются в
    нём.

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

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

    Дальше пути различных
    компиляторов расходятся. В
    большинстве компиляторов следом за
    этапом семантического анализа идёт
    перевод программы в некоторый
    промежуточный код, который может
    использоваться для генерации кода
    под разные аппаратные платформы.
    Если компилятор выполняет
    компиляцию только для какой-то
    одной аппаратной платформы, то
    программа может транслироваться в
    коды на языке Ассемблера
    соответствующей процессорной
    архитектуры, или, если компилятор
    трудится для какой-то виртуальной
    машины (как, например, в случае Java
    или Microsoft .NET), то переводиться
    программа может затем в
    специальный байт-код, понятный
    соответствующей виртуальной
    машине. Тем не менее, в большинстве
    современных компиляторов нет
    непосредственной трансляции в
    ассемблерный код — даже если в итоге
    компилятор не должен стараться для
    создания кросс-платформенных
    программ, всё равно, сначала идёт
    трансляция программы в какой-то
    промежуточный код, а только потом
    уже в исполняемый. Причина этого в
    оптимизации кода.

    Современные компиляторы, даже
    самые слабенькие и плохонькие,
    поддерживают хотя бы базовую
    оптимизацию кода. Более мощные
    коммерческие компиляторы содержат
    в себе очень мощные алгоритмы
    оптимизации кода, которые
    позволяют при некоторых условиях
    сделать её в разы быстрее. Особенно
    мощными в плане оптимизации
    давным-давно тому назад считались
    компиляторы производства Watcom,
    сейчас, вроде бы, постепенно
    восстанавливающие свою былую славу
    в виде open-source продукта. Потом пальма
    первенства перешла к компиляторам
    Intel, и сейчас именно они считаются
    самыми лучшими компиляторами в
    плане оптимизации. Что ж, это
    довольно логично — кому, как ни
    создателям процессоров, знать, как
    лучше всего оптимизировать
    программы для работы на них.
    Впрочем, не важно, плоха
    оптимизация в компиляторе или нет —
    главное, что в любом оптимизирующем
    компиляторе есть модуль,
    называемый оптимизатором, который
    начинает свою работу после
    генератора промежуточного кода.
    Справедливости ради стоит сказать,
    что оптимизатор может работать и
    после генерации уже исполняемого
    кода, но в наши дни такая схема
    встречается уже редко, поскольку
    производители компиляторов, как
    правило, выпускают целую линейку
    подобных продуктов для разных
    языков программирования и
    стараются делать оптимизаторы,
    которые можно встроить в любой из
    этих компиляторов. Какими именно
    методами оптимизатор может
    повышать скорость работы программы
    — это тема отдельной статьи,
    которую, возможно, вы когда-нибудь и
    сможете увидеть на страницах
    «Компьютерных вестей».

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

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


    Дополнительные компоненты

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

    Ассемблер и компоновщик в ряде
    случаев встроены прямо в
    компилятор, в других же случаях они
    выделяются в отдельные программы,
    которые запускаются после
    завершения работы самого
    компилятора. Их может и вовсе не
    быть, как, например, для
    компиляторов, преобразующих
    программы с одного языка высокого
    уровня на другой высокоуровневый
    язык (так называемых фронт-эндов),
    или они могут присутствовать
    только в виде, например,
    специфического сборщика,
    создающего код для виртуальной
    машины и помещающего его в какую-то
    специальную оболочку компоновщика
    (классический пример — Java с её
    JAR-файлами). Стоит, тем не менее,
    сказать пару слов о назначении этих
    двух инструментов.

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

    Компоновщик создаёт из того кода,
    который сгенерировал ассемблер,
    исполняемые файлы. Даже для одной и
    той же процессорной архитектуры
    исполняемые файлы будут отличаться
    в зависимости от операционной
    системы. Например, для Windows формат
    исполняемых файлов — это Portable Executable
    (PE), а для Linux — Executable Linked File (EXE).


    Резюме

    Как видите, если смотреть на
    компиляторы со стороны, то всё в них
    просто и не вызывает никаких
    особенно заковыристых вопросов. На
    практике всё, мягко говоря, немного
    сложнее. И если вы вдруг решите
    написать собственный компилятор,
    то не стоит заранее пугаться, хотя к
    определённым сложностям нужно, как
    и в любой новой работе, быть
    готовым. Я бы лично рекомендовал
    начинать знакомство с предметом с
    написания какого-нибудь простого
    эзотерического языка вроде Brainfuck
    или Whitespace. Поскольку сам я в своё
    время интересовался благодаря
    своему знакомому Марату Духану
    первым из них, то и вам рекомендую
    его.

    Вообще, если же вы вдруг решили
    проникнуть глубже в тайны создания
    компиляторов, то в Интернете для
    вас найдётся масса литературы — и
    простой, и академически точной и
    подробной. Начать можно, например,
    отсюда: kit.kulichki.net.
    Хотя сайт уже не обновлялся целую
    вечность, информация, размещённая
    на нём, подойдёт для новичка и не
    устареет ещё не один десяток лет.
    Вообще, если погуглить, информации
    найдёте очень много, даже придётся
    её фильтровать. Так что успехов вам
    с компиляторами!

    Вадим СТАНКЕВИЧ

    Программирование: Что такое компилятор и зачем он нужен

    Компилятор — это программа, которая переводит написанный человеком код в машинный, то есть понятный компьютеру 

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

    Что происходит, когда компилируется код?

    Сложность компиляции зависит от синтаксиса языка программирования и от того, насколько сильно этот язык использует абстракции. Например, компилятор для C гораздо проще, чем для C++ или C#. Кстати, если вы, вдруг, плохо знаете английский язык, но вам нужно найти ответ на свой технический вопрос, то вам поможет сайт CodeRoad — вопросы/ответы по программированию. Здесь переводят на русский язык самые популярные вопросы со StackOverflow.

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

    Сначала компилятор читает все символы исходного кода, затем создает описания для этих символов. Например, код на C++: int A = (B*C) + 15; может быть описан так:
    • Тип «int»; значение «C»; равно; левая скобка; значение «A»; умножить; значение «B»; правая скобка; плюс; литерал «15».

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

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

    Если значения «B» и «C» были раннее объявлены и находятся в доступной области видимости, компилятор скажет:

    • «B»: объявленный идентификатор.
    Если переменные были объявлены, но им не присвоено значение, то компилятор выдаст предупреждение:
    • Локальное значение «B» использовано без инициализации.

    Не игнорируйте предупреждения компилятора. Ошибки, приводящие к возникновению предупреждений, могут сломать ваш код.

    Один проход или два?

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

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

    Генерация машинного кода

    После успешных лексического и синтаксического анализов начинается финальная стадия — генерация машинного кода. Этот процесс еще более сложен на современных процессорах из-за многопоточности.

    Скорость скомпилированного кода должна быть максимально возможной. Она может изменяться в зависимости от качества кода и его оптимизации.

    Генерация кода — это сложно

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

    • Instruction pipelining
    • Внутренний кэш

    Если все инструкции цикла хранятся в кэше процессора, то цикл выполняет гораздо быстрее, чем когда инструкции приходится извлекать из оперативной памяти. Кэш центрального процессора — это блок памяти, встроенный в чип ЦП. Доступ к кэшу процессора осуществляется в разы быстрее, чем к ОЗУ.

    Кэши и очереди

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

    • Целочисленная арифметика (целые числа)
    • Арифметика с числами с плавающей точкой (дробные числа)

    Эти операции часто выполняются параллельно, чтобы ускорить работу кода.

    Что такое компилятор? — Определение из Техопедии

    Что означает компилятор?

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

    Формально результат компиляции называется объектным кодом или иногда объектным модулем. Объектный код — это машинный код, который процессор может выполнять по одной инструкции за раз.

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

    Компилятор выполняет четыре основных шага:

    1. Сканирование: Сканер считывает по одному символу из исходного кода и отслеживает, какой символ присутствует в какой строке.
    2. Лексический анализ: Компилятор преобразует последовательность символов, которая появляется в исходном коде, в серию строк символов (известных как токены), которые связаны определенным правилом с помощью программы, называемой лексическим анализатором.Таблица символов используется лексическим анализатором для хранения слов в исходном коде, которые соответствуют сгенерированному токену.
    3. Синтаксический анализ: На этом этапе выполняется синтаксический анализ, который включает предварительную обработку, чтобы определить, находятся ли токены, созданные во время лексического анализа, в правильном порядке в соответствии с их использованием. Правильный порядок набора ключевых слов, который может дать желаемый результат, называется синтаксисом. Компилятор должен проверить исходный код, чтобы убедиться в синтаксической точности.
    4. Семантический анализ: Этот шаг состоит из нескольких промежуточных шагов. Сначала проверяется структура токенов, а также их порядок относительно грамматики на данном языке. Значение структуры токена интерпретируется синтаксическим анализатором и анализатором для окончательной генерации промежуточного кода, называемого объектным кодом.

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

    Techopedia объясняет компилятор

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

    Причина, по которой комментарии должны быть помечены, заключается в том, что они полностью нечитаемы процессором. Процессор не может понять слова или сигналы, поэтому он не может ничего выдать из кода комментария. Но то же самое в значительной степени верно для частей кода, которые не являются комментариями: вызов функции, такой как «get», ничего не значит для компьютера. Таким образом, компилятор берет код и отображает его в двоичном формате, который управляет логическими операциями процессора.

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

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

    Напротив, интерпретатор будет собирать код для каждого выполнения по запросу.

    Эта часть объяснения ясна. Что становится менее ясным, так это то, как именно это происходит, и какие языки являются компилируемыми, а какие интерпретируются.Например, C ++ часто называют ярким примером языка, использующего компилятор, хотя появление CINT в качестве интерпретатора C ++ делает этот случай более тонким.

    Или возьмем случай JavaScript, который часто описывают как интерпретируемую программу, а не как компилируемую. Если углубиться в практику объединения JavaScript, становится ясно, что части кода можно скомпилировать, что приводит к гораздо более подробному объяснению того, как работают эти два процесса.Эксперты могут говорить об использовании байт-кода или инструкций виртуальной машины по-разному, которые составляют либо лексический анализ, синтаксический анализ и семантический анализ компиляции, либо динамическое выполнение интерпретации по запросу.

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

    Что такое компилятор и как его использовать?

    Введение в компиляторы C ++

    Чтобы начать работу с C ++, вам нужно немного узнать о компиляторах и о том, как C ++ работает на вашем компьютере.

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

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

    Ассемблер — это прямое соотношение 1 к 1 с машинным языком. Такие языки, как C, C ++ и COBOL, немного выше и требуют компиляции. Он идет еще выше. Такие языки, как JavaScript и Python, имеют компоненты, которые перед компиляцией переводятся на C ++ или другие языки низкого уровня, что фактически делает их «более высокими» языками, чем C или C ++.

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

    Как работают компиляторы

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

    Когда вы запускаете компилятор для своего кода, сначала препроцессор считывает исходный код (файл C ++, который вы только что написали).Препроцессор ищет любые директивы препроцессора (строки кода, начинающиеся с символа #). Директивы препроцессора заставляют препроцессор каким-либо образом изменять ваш код (обычно добавляя некоторую библиотеку или другой файл C ++).

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

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

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

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

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

    Как скомпилировать файл

    Допустим, у вас есть файл C ++ с именем helloWorld.cpp

    Если вы работаете в Windows

    Использование и IDE, например CodeBlocks

    Это так же просто, как нажатие кнопок сборки и запуска, они создадут файл в папке проекта.

    Использование командной строки

    1. Откройте командную строку разработчика. Для этого шага вам понадобится Microsoft Visual Studio или другая IDE, которая позволит вам компилировать вашу программу из командной строки. Вы также можете найти в Интернете компиляторы C ++.
    2. Перейти к исходному коду напрямую
    3. Запустить компилятор для исходного кода (при условии, что вы используете компилятор Microsoft Visual Studio) cl / EHsc helloWorld.cpp

    Теперь будет создан объектный файл и автоматически его свяжут для тебя. Если вы заглянете в ту же папку, вы увидите исполняемый файл hellWorld.exe (обратите внимание на расширение exe).

    1. Введите helloWorld в приглашение для запуска исполняемого файла

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

    Если вы работаете в Linux или OSX

    1. Откройте окно терминала и перейдите в каталог исходного кода
    2. Запустите компилятор для исходного кода g ++ helloWorld.cpp -o helloWorld

    Это создаст объектный файл и автоматически свяжет его для вас. Загляните в папку, и вы увидите исполняемый файл helloWorld.exe (обратите внимание на расширение exe).

    1. Введите ./helloWorld в окне терминала, чтобы запустить исполняемый файл.

    g ++ — стандартный компилятор Linux и отличная утилита. Он поставляется в комплекте с операционной системой.

    ПРИМЕЧАНИЕ: чтобы скомпилировать и выполнить код напрямую, запустите g ++ -o helloWorld helloWorld.cpp; ./helloWorld , поэтому, когда вам нужно скомпилировать и запустить код несколько раз, введите стрелку вверх.

    Существует несколько различных типов компиляторов. Два из перечисленных — это два, которые обычно входят в состав Windows или Linux / OSX.

    Подробнее о C ++

    Что такое компилятор кода и для чего он нужен?

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

    Что происходит при компиляции кода?

    Сложность компилятора зависит от синтаксиса языка и степени абстракции, которую обеспечивает этот язык программирования.Компилятор C намного проще, чем компилятор для C ++ или C #.

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

    При компиляции компилятор сначала считывает поток символов из файла исходного кода и генерирует поток лексических токенов. Например, код C ++:

     
     int C = (A * B) +10; 

    могут быть проанализированы как эти токены:

    • тип «int»
    • переменная «C»
    • равна
    • левая квадратная скобка
    • переменная «A»
    • умножить на
    • переменная «B»
    • правая скобка
    • плюс
    • буквальный «10»

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

    Лексический вывод поступает в синтаксический анализатор компилятора, который использует правила грамматики, чтобы решить, является ли ввод действительным или нет.Если переменные A и B не были ранее объявлены и не попали в область видимости, компилятор может сказать:

    • «A»: необъявленный идентификатор.

    Если они были объявлены, но не инициализированы. компилятор выдает предупреждение:

    • локальная переменная A используется без инициализации.

    Вы никогда не должны игнорировать предупреждения компилятора. Они могут взломать ваш код странным и неожиданным образом. Всегда исправляйте предупреждения компилятора.

    Один проход или два?

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

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

    Код генерирующей машины

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

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

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

    Создание кода затруднительно

    Автор компилятора сталкивается с проблемами при написании генератора кода.Многие процессоры ускоряют обработку, используя

    • Конвейерная обработка команд
    • Внутренние кэши.

    Если все инструкции в цикле кода могут храниться в кэше ЦП, то этот цикл выполняется намного быстрее, чем когда ЦП должен получать инструкции из основного ОЗУ. Кэш ЦП — это блок памяти, встроенный в микросхему ЦП, доступ к которому осуществляется намного быстрее, чем к данным в основной ОЗУ.

    Кеши и очереди

    У большинства ЦП есть очередь предварительной выборки, в которой ЦП считывает инструкции в кэш перед их выполнением.Если происходит условный переход, ЦП должен перезагрузить очередь. Код должен быть сгенерирован, чтобы минимизировать это.

    Многие процессоры имеют отдельные части для:

    • Целочисленная арифметика (целые числа)
    • Арифметика с плавающей запятой (дробные числа)

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

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

    Определение компилятора Merriam-Webster

    com · pil · er

    | \ kəm-pī-lər

    \

    2

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

    Понимание компиляторов — для людей | Люк I.Wilson

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

    В большинстве современных операционных систем файлы организованы в одномерные массивы байтов. Формат файла определяется его содержимым, поскольку файл является исключительно контейнером для данных, хотя на некоторых платформах формат обычно обозначается расширением имени файла, определяющим правила организации и интерпретации байтов.Например, байты простого текстового файла ( .txt, в Windows) связаны с символами ASCII или UTF-8, тогда как байты файлов изображений, видео и аудио интерпретируются иначе. (Википедия)
    (https://en.wikipedia.org/wiki/Computer_file#File_contents)

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

    Языки, удобочитаемые человеком, также называются языками высокого уровня. Компилятор, который переходит от одного языка высокого уровня к другому языку высокого уровня, называется компилятором исходного кода, транскомпилятором или транспилятором .
    (
    https://en.wikipedia.org/wiki/Source-to-source_compiler)

     int main () {
    int a = 5;
    а = а * 5;
    возврат 0;
    }

    Выше приведена программа на языке C, написанная человеком, которая выполняет следующие действия на более простом, еще более удобочитаемом языке, называемом псевдокодом :

     программа 'main' возвращает целое число 
    begin
    store the number ' 5 'в переменной' a '
    ' a 'равно' a 'умножить на' 5 '
    return' 0 '
    end

    Псевдокод — это неформальное высокоуровневое описание принципа работы компьютерной программы или другого алгоритма.(Википедия)
    (https://en.wikipedia.org/wiki/Pseudocode)

    Мы скомпилируем эту программу на C в ассемблерный код в стиле Intel, как это делает компилятор. Хотя компьютер должен быть конкретным и следовать алгоритмам, чтобы определять, что делает слова, целые числа и символы; мы можем просто использовать здравый смысл. Это, в свою очередь, делает наше устранение неоднозначности намного короче, чем для компилятора.

    Этот анализ упрощен для облегчения понимания.

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

    Наш исходный исходный код будет разделен на токены и сохранен в памяти компьютера. Я постараюсь передать память компьютера на следующей схеме производства токенизатора.

    До:

     int main () {
    int a = 5;
    а = а * 5;
    возврат 0;
    }

    После:

     [KEYWORD, «int»] [ID, «main»] [LPAREN] [RPAREN] [LBRACE] 
    [KEYWORD, «int»] [ID, «a»] [EQUALS] [ INT, «5»] [SEMICOLON]
    [ID, «a»] [EQUALS] [ID, «a»] [НЕСКОЛЬКО] [INT, «5»] [SEMICOLON]
    [KEYWORD, «return»] [INT , "0"] [SEMICOLON]
    [RBRACE]

    Схема отформатирована вручную для удобства чтения.На самом деле он не будет ни с отступом, ни с разделением по строкам.

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

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

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

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

    Эти «инструменты для создания синтаксического анализатора» называются генераторами синтаксического анализатора. Генераторы синтаксического анализатора специфичны для языков, поскольку они генерируют синтаксический анализатор в коде этого языка. Bison (C / C ++) — один из самых известных в мире генераторов парсеров.

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

    EBNF (или его диалект) обычно используется в генераторах синтаксического анализатора для определения грамматики.

     присвоение = идентификатор, равно, целое число | идентификатор; 

    Это означает, что следующие шаблоны токенов считаются назначением:

     a = 5 
    или
    a = a
    или
    b = 123456789

    Но следующие шаблоны не являются, даже если они должны быть:

     int a = 5 
    или
    a = a * 5

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

    Прочтите следующую статью в Википедии, если вам интересно, как работают парсеры. https://en.wikipedia.org/wiki/Parsing

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

    Абстрактное синтаксическое дерево нашей программы. Создано с использованием Libreoffice Draw.

    В информатике абстрактное синтаксическое дерево (AST) или просто синтаксическое дерево — это древовидное представление абстрактной синтаксической структуры исходного кода, написанного на языке программирования.(Википедия)
    (https://en.wikipedia.org/wiki/Abstract_syntax_tree)

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

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

    Генерация кода сразу после синтаксического анализа не является обычным явлением для более сложных компиляторов, поскольку они проходят несколько этапов до получения окончательного AST, такого как промежуточный, оптимизация и т. Д. Существует больше методов генерации кода.
    https://en.wikipedia.org/wiki/Code_generation_(compiler)

    Мы компилируем в сборку, потому что один ассемблер может создавать машинный код для одной или нескольких разных архитектур ЦП. Например, если бы наш компилятор сгенерировал сборку NASM, наши программы были бы совместимы с архитектурами Intel x86 (16-разрядная, 32-разрядная и 64-разрядная).Компиляция прямо в машинный код будет не столь эффективной, потому что нам нужно будет написать бэкэнд для каждой целевой архитектуры независимо. Хотя это займет довольно много времени и с меньшим выигрышем, чем при использовании стороннего ассемблера.

    С LLVM вы можете просто скомпилировать LLVM IR, а он сделает все остальное. Он компилируется в широкий спектр языков ассемблера и, таким образом, компилируется во многие другие архитектуры. Если вы слышали о LLVM раньше, то, вероятно, понимаете, почему сейчас его так ценят.
    https://en.wikipedia.org/wiki/LLVM

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

    Крайняя левая ветвь нашей последовательности операторов содержит первое присвоение новой целочисленной переменной a . Присвоенное значение — это лист, содержащий постоянное целое значение 5.Как и крайняя левая ветвь, средняя ветвь — это назначение. Он назначает двоичную операцию (bin op) умножения между на и 5, на на . Для простоты мы просто дважды ссылаемся на и с одного и того же узла, а не на два узла и .

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

    Ниже приведен выпуск компилятора GNU C (x86–64 GCC 8.1) учитывая наш исходный код без оптимизации.

    Имейте в виду, что компилятор не генерировал комментарии или пробелы.

     main: 
    push rbp
    mov rbp, rsp

    mov DWORD PTR [rbp-4], 5; крайняя левая ветка

    mov edx, DWORD PTR [rbp-4]; средняя ветвь
    mov eax, edx
    sal eax, 2
    add eax, edx
    mov DWORD PTR [rbp-4], eax

    mov eax, 0; крайняя правая ветка
    pop rbp
    ret

    Отличный инструмент; Compiler Explorer от Мэтта Годболта позволяет вам писать код и просматривать сборки компилятора в реальном времени.Попробуйте наш эксперимент на https://godbolt.org/g/Uo2Z5E.

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

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

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

    Ассемблер, который вы используете для компиляции сборки до машинного кода, также написан на языке программирования.Его можно было даже написать на собственном ассемблере. Написание компилятора на языке, который он компилирует, называется начальной загрузкой.
    https://en.wikipedia.org/wiki/Bootstrapping_(compilers)

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

    Спасибо

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

    Ресурсы

    Я коснулся только поверхности. Если вам все еще интересно, продолжайте обучение с помощью этих ресурсов.

    Определение и значение компилятора | Что такое компилятор?

    Компилятор — это программа, которая переводит исходный код в объектный код, чтобы его понимал конкретный центральный процессор (ЦП). Акт перевода исходного кода в объектный код известен как компиляция . Компиляция обычно используется для программ, которые переводят исходный код с языка программирования высокого уровня (например, C ++) на язык программирования низкого уровня (например, машинный код) для создания исполняемой программы.Аналогичным образом, когда язык низкого уровня преобразуется в язык высокого уровня, этот процесс называется декомпиляцией.

    Фазы компилятора

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

    1. Лексический анализатор

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

    2. Анализатор синтаксиса

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

    3.Семантический анализатор

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

    4. Генератор промежуточного кода

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

    5. Оптимизатор кода

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

    6. Генератор целевого кода

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

    Типы компиляторов

    Есть много типов компиляторов, например:

    • Кросс-компилятор: Скомпилированная программа запускается на компьютере с другой операционной системой или процессором, нежели тот, на котором работает компилятор.Он способен создавать код для платформы, отличной от той, на которой работает компилятор.
    • Компилятор исходного кода: Также известный как транскомпилятор, он переводит исходный код, написанный на одном языке программирования, в исходный код другого языка программирования.
    • JIT-компилятор: Компилятор, откладывающий компиляцию до времени выполнения. Этот компилятор используется для таких языков, как Python и JavaScript, и обычно работает внутри интерпретатора.

    что такое компилятор вообще? «Hisham.hm

    Teal был представлен на HN сегодня, и в одном из комментариев ставился под сомнение тот факт, что в документации говорится, что он «компилирует Teal в Lua»:

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

    Я предполагал, что он будет генерировать исполняемый машинный код, а не исходный код Lua.

    Я подумал, что на это стоит ответить, потому что это позволило развеять сразу два заблуждения.

    Во-первых, если мы хотим быть строгими в терминах информатики, называть это «интерпретируемыми или компилируемыми языками» неправильно, потому что интерпретация или компиляция — это свойство не языка, а его реализации. Были такие вещи, как интерпретатор C и опережающий компилятор для PHP, который генерирует машинный код.

    Но затем мы подошли к главному — использованию «компилятора».

    Определение компилятора никогда не предполагало генерации исполняемого машинного кода.Уже в 1970-х годах компиляторы Паскаля сгенерировали P-код (форма «байт-кода» на языке Java), который затем был интерпретирован. В 1980-х годах Turbo Pascal напрямую создавал машинный код.

    Я видел, как неологизм «транспилятор» очень не одобрялся академическим сообществом языков программирования именно потому, что компилятор есть компилятор, независимо от языка вывода — я использовал термин «компилятор» именно из-за моего академического образования.

    Я помню, как люди шутили в Твиттере Academic PL, даже в шутку называя это «словом на букву».Я просто сделал быстрый поиск в Твиттере, чтобы посмотреть, смогу ли я его найти, и нашел кучу ссылок, датируемых 2014 годом (хотя я не буду ссылаться здесь на твиты людей). Но это показывает, насколько этот пост в блоге устарел! Академия в значительной степени решила не использовать определение «компилятор против транспилятора» вообще .

    Я сам не возражаю против термина «транспилятор», если он помогает неакадемикам понять, что это компилятор «исходный код», но тогда вы не увидите людей, вызывающих компилятор Nim, который генерирует код C, а затем компилирует его в машинный код, «транспилятор», даже если это компилятор «исходный код».

    В конце концов, «компилятор» — это всеобъемлющий термин для программы, которая берет код на одном языке и производит код на другом, будь то высокоуровневый или машинный язык — и да, это означает, что в буквальном смысле ассемблер является компилятором. тоже (но мы не хотим быть педантичными, правда? ПРАВИЛЬНО? ). А поскольку мы говорим об ассемблере, большинство компиляторов C также не генерируют исполняемый машинный код: gcc производит ассемблер, который затем с помощью газа превращается в машинный код. Итак, gcc — это компилятор от исходного кода к исходному? Turbo Pascal больше похож на компилятор, чем на gcc? С таким же успехом я мог бы добавить шаг вывода в компилятор Teal для создания исполняемого файла на выходе, используя те же методы компиляторов Pascal 70-х годов.Не думаю, что это сделало бы его более или менее компилятором.

    Как видите, различие между «что такое транспилятор» сводится к «что такое исходный код» или «что такое язык высокого уровня», причем последнее особенно имеет очень расплывчатое определение, так что, в конце концов, мое социологическое наблюдение Использование термина «транспилятор» и «компилятор» сводится к предубеждениям людей относительно того, «что делает его настоящим хардкорным компилятором». Но то, что он «транспилятор» или нет, тоже ничего не говорит о «жесткости» проекта — я уверен, что компилятор TypeScript, который генерирует JavaScript, намного сложнее, чем многие другие компиляторы, генерирующие машинный код.

    .

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *