Как clang способен управлять оптимизацией кода C/С++?

Мне сказали, что clang - это драйвер, который работает как gcc, чтобы выполнить предварительную обработку, компиляцию и работу с привязкой. Во время компиляции и связи, насколько я знаю, на самом деле это делает оптимизацию ("-O1", "-O2", "-O3", "-Os", "-flto").

Но я просто не могу понять , как задействован llvm.

Кажется, что для компиляции исходного кода даже не нужна статическая библиотека, такая как libLLVMCore.a, а для пакетов debian clang зависит от другого пакета с именем libllvm-3.4 (версия clang - 3.4), которая содержит libLLVM-3.4.so(.1), делает clang использует эту общую библиотеку для оптимизации?

Я некоторое время проверял исходный код clang и обнаружил, что include/clang/Driver/Options.td содержит связанные параметры, но, к сожалению, я не смог найти исходные файлы, которые включают этот файл, поэтому я до сих пор не знаю о механизме.

Я надеюсь, что кто-то может дать мне несколько советов.

Ответ 1

(TL; DontWannaRead - перейдите к концу этого ответа)

Чтобы правильно ответить на ваш вопрос, вам сначала нужно понять разницу между компилятором front-end и back-end (особенно первый).

Clang - это компилятор front-end (http://en.wikipedia.org/wiki/Clang) для C, С++, Objective C и Objective Языки С++.

Учет клана следующий:

enter image description here

то есть. перевод с исходного кода С++ (или C, или Objective C и т.д.) на LLVM IR, текстовое представление нижнего уровня того, что должно код делаю. Для этого Clang использует несколько подмодулей, описания которых вы можете найти в любой достойной строительной книге компилятора: lexer, parser + семантический анализатор (Sema) и т.д.

LLVM - это набор библиотек, основной задачей которых является следующее: предположим, что у нас есть LLVM IR-представление следующей функции С++

int double_this_number(int num) {
    int result = 0;
    result = num;
    result = result * 2;
    return result;
}

ядро ​​пропуска LLVM должно оптимизировать код LLVM IR:

enter image description here

Что делать с оптимизированным IR-кодом LLVM полностью зависит от вас: вы можете перевести его на исполняемый код x86_64 или изменить его, а затем выплюнуть его как исполняемый код ARM или исполняемый код графического процессора. Это зависит от цели вашего проекта.

Термин "back-end" часто вводит в заблуждение, так как существует множество документов, которые определяли бы библиотеки LLVM "средним концом" в цепочке компилятора и определяли "задний конец" как окончательный модуль, который генерирует код ( LLVM IR на исполняемый код или что-то еще, которое больше не нуждается в обработке компилятором). Другие источники относятся к LLVM как к концу Clang. В любом случае их роль понятна, и они предлагают мощный механизм: независимо от того, на каком языке вы нацеливаетесь (С++, C, Objective C, Python и т.д.), Если у вас есть интерфейс, который переводит его в LLVM IR, вы может использовать один и тот же набор библиотек LLVM для его оптимизации и, если у вас есть фоновый сервер для вашей целевой архитектуры, вы можете создать оптимизированный исполняемый код.

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

В связи с тем, что Clang считается "компилятором": Clang управляет интерпретацией параметров командной строки (описания и многие объявления TableGen 'd, и они могут потребовать немного больше, чем простой grep, чтобы плавать через источники), решает, какие Jobs и фазы должны быть выполнены, настройте CodeGenOptions в соответствии с желаемой/возможной оптимизацией и уровни трансформации и вызывает соответствующие модули (clangCodeGen in BackendUtil.cpp - это тот, который заполняет диспетчер модулей с применяемыми оптимизациями) и инструменты (например, компоновщик Windows ld). Он управляет процессом компиляции с самого начала и до конца.

Наконец, я бы предложил прочитать документацию Clang и LLVM, они довольно объяснительны, и большинство ваших вопросов должны искать ответ там, в первую очередь.

Ответ 2

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

Компилятор LLVM является компилятором для одного конкретного языка LLVM. Что делает Clang, это компилировать код С++ для LLVM без оптимизации. Затем Clang может вызвать компилятор LLVM для компиляции кода LLVM для оптимизации сборки.