2016-03-22 2 views
2

Я пишу компилятор языка программирования для интеграции DSL и C/C++. Для этого я решил для LLVM по нескольким причинам.Тип данных для bool в LLVM IR

Существует основная программа. В этой основной программе я загружаю файлы биткода, которые были скомпилированы clang. Загружаемый файл биткода представляет собой короткую, но полную языковую среду программирования с REPL, парсером, компоновщиком и AST.

До сих пор я понял, что булевы типы данных представлены в IR как i1. Я оптимизировал свой код с -O3 и я получаю для булевой следующих ИК-коды (разборки с LLVM-ДИСОМ из сгенерированного файла) битового кода:

%"class.tl::contrib::toy::ToyREPL" = type <{ %"class.tl::contrib::toy::InitLanguage"*, i8, [7 x i8] }> 

Класс ToyREPL и используют другой класс InitLanguage. Как ни странно, логическое представление представляется i8 и массивом i8. Я действительно не понимаю.

Я определил Makefile. Сначала я скомпилирую файлы. Впоследствии я связываю их с файлом bc, затем оптимизирую и свяжу его с некоторыми другими библиотеками.

@cd $(BIN)/$(TARGET)/$(2); $(LINK) -o $(1).$(BITCODE_EXT) $(3) 

@cd $(BIN)/$(TARGET)/$(2); $(OPT) -O3 $(1).$(BITCODE_EXT) -o $(1).$(OPT_NAME).$(BITCODE_EXT) $(OPTIMIZER_FLAGS) 

@$(LINK) -o $(BIN)/$(TARGET)/$(2)/$(1).$(BITCODE_EXT) $(BIN)/$(TARGET)/$(2)/$(1).$(OPT_NAME).bc $(LINK_OPTION) $(4) 

компилятора флаги:

-v -g -emit-llvm -I$(BOOST_INC_DIR) -std=c++11 -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS 

Optimizer флаги -std-link-opts

флаг Линк -v.

Соответствующая часть класса ToyREPL здесь:

class ToyREPL { 
private: 

    InitLanguage *initLang; 

    bool runs = false; 

Теперь мой вопрос: ли мое предположение неверно BOOL должно быть скомпилированы для битового кода i1? Какой компилятор я должен рассмотреть для компиляции в i1? Дайте мне знать, если вы считаете, что мой процесс сборки в какой-то мере ошибочен. Сгенерированный файл биткода доступен для чтения, и я могу извлечь модуль и класс ToyREPL в виде StructType.

+0

Замененные цитаты с кодами - цитаты обычно лучше всего при цитировании материалов, предназначенных для людей, а не для компьютеров.;) – Yakk

ответ

2

Если я вас правильно понимаю, ваш вопрос по существу - почему C++ класс

class ToyREPL { 
    bool runs = false; 
    ... 
}; 

был Составитель Clang в type <{ i8, [7 x i8], ... }>?

Итак, прежде всего, почему Clang выбрал i8 над i1 для булева поля прост - the smallest C++ type takes one byte of memory, и если вы не используете битовые поля, что также относится и к полям в структурах. Также см. this related question about why a whole byte is used for booleans. Сам LLVM использует i1 для булевых значений, но это потому, что он примерно не зависит от платформы. На этапе понижения они могут снова стать целыми байтами.

Что касается [7 x i8], это дополнение, предназначенное для обеспечения того, чтобы каждый объект этого типа был выровнен по 64 битам и не делится своей памятью с каким-либо другим объектом - очень разумным подходом к 64-разрядной системе. В качестве альтернативы, если имеется следующее поле структуры, добавление может быть вставлено, чтобы обеспечить выравнивание поля на 64 бита.

The Wikipedia article on alignment and padding является полезной отправной точкой, если вы хотите узнать больше.

+0

Это кажется очевидным ответом ... но нет ли исключения на стороне LLVM или это большая его часть вызвана только тем, как указан C++? – VermillionAzure

+0

Спасибо. Прокладки имеют смысл, поскольку у меня 64-битная машина. Но это означает, что я не могу различить целочисленное значение и логическое значение, только если у меня есть биткод под рукой, не так ли? – repl

+0

@VermillionAzure это все происходит от Clang, насколько я знаю, из-за того, что C++ указан и по соображениям производительности. Например, другой язык может указывать на 'i1' для булевых языков, чтобы сэкономить место, но тогда на этапе понижения могут возникать смешные вещи, чтобы загружать и хранить« i1 »на машине, которая имеет только байтовую адресацию. – Oak