Только лучше собирать в отдельной директории. Если при сборке будут ошибки, то пишите сюда, исправлю.Код:./configure --enable-targets=z80
Сам я использую CMake для сборки, поэтому в configure скриптах не всегда успеваю все править во время.
Только лучше собирать в отдельной директории. Если при сборке будут ошибки, то пишите сюда, исправлю.Код:./configure --enable-targets=z80
Сам я использую CMake для сборки, поэтому в configure скриптах не всегда успеваю все править во время.
Автор, не теряйся! Как успехи?
Работаю потихоньку. Писал письмо Peter'у Hanzel'у, который также занимался разработкой backend'а для Z80, но он мне так и не ответил.
Также понял, что немного придется подправить clang для хорошей генерации llvm кода. Если точнее, то нужно добавить CodeGenTargetInfo ABIInfo и еще пару классов. В целом не очень сложно. Хорошо бы конечно пообщаться с кем-нибудь кто тоже разбирался с работой llvm, т.к. некоторые вопросы все же имеются и самому доходить до всего получается дольше. Но проект не забрасываю. Как будут первые более менее рабочие результаты пригодные для использования, то обязательно поделюсь
Дык есть же мейлинг-лист разработчиков, можно общаться со всеми сразу http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
mastermind, я в курсе про мейлинг лист. Что ж, попробую туда написать по интересующим вопросам.
Есть вопрос по поводу преобразования типов в вычислениях в языке Си. Нашел список правил, по которому осуществляется преобразование:
1. Операнды типа float преобразуются к типу double.
2. Если один операнд long double, то второй преобразуется к этому же типу.
3. Если один операнд double, то второй также преобразуется к типу double.
4. Любые операнды типа char и short преобразуются к типу int.
5. Любые операнды unsigned char или unsigned short преобразуются к типу unsigned int.
6. Если один операнд типа unsigned long, то второй преобразуется к типу unsigned long.
7. Если один операнд типа long, то второй преобразуется к типу long.
8. Если один операнд типа unsigned int, то второй операнд преобразуется к этому же типу.
Таким образом если у нас есть программа:
Операнды бинарной операции "сложения" должны будут преобразованы к типу int (по правилу 4), затем выполняется сама операция и результат преобразуется к типу char.Код:char add(char a, char b) { return a+b; }
Компилятор clang именно так и делает, но при этом генерирует цепочку команд примерно такого вида:
В результате llvm кодогенератор начинает все эти действия честно переводить в код z80, т.е. сложение получается медленное и мучительное - с расширением в 16 битный регистр и сложением через ADD HL,RR))Код:define i8 test(i8 %a, i8 b) { %ext_a = sext i8 %a to i16 ; знаковое расширение типа %ext_b = sext i8 %b to i16 ; знаковое расширение типа %add = add i16 a, b %trunc = trunc i16 %add to i8 ; усечение типа ret i8 %trunc }
Конечно это лишь пример и данный код оптимизатор сворачивают в одну 8-битную команду сложения, но есть примеры которые можно в ручную свести к 8-битной арифметике, но оптимизатор этого не делает. Пока встречал это в конструкциях с условиями.
Интересно следуют ли имеющиеся компиляторы Си всем вышеперечисленным правилам преобразования типов.
Также интересно вот что:
Т.к. Z80 8-битный процессор, то int должен иметь размер 1 байт или я не прав? Или быть может Z80 какой-то промежуточный вариант, т.к. в наборе команд есть операции и для работы с 16 битными данными (напр. ADD HL,HL)?Размер переменной типа int в стандарте языка Си не определен. В большинстве систем программирования размер переменной типа int соответствует размеру целого машинного слова. Например, в компиляторах для 16-разрядных процессоров переменная типа int имеет размер 2 байта. В этом случае знаковые значения этой переменной могут лежать в диапазоне от -32768 до 32767.
По крайней мере в современном стандарте, насколько я понимаю, есть требования к минимальным диапазонам значений целочисленных типов:
http://www.open-std.org/JTC1/SC22/WG...docs/n1256.pdf
стр. 21, 22:
Т.е. значения этих лимитов (абсолютные) могут быть либо равны указанным либо м.б. больше (но не меньше). Иначе говоря, int, unsigned int, а также short-типы д.б. не менее 16 бит.5.2.4.2.1 Sizes of integer types <limits.h>
The values given below shall be replaced by constant expressions suitable for use in #if
preprocessing directives. Moreover, except for CHAR_BIT and MB_LEN_MAX, the
following shall be replaced by expressions that have the same type as would an
expression that is an object of the corresponding type converted according to the integer
promotions. Their implementation-defined values shall be equal or greater in magnitude
(absolute value) to those shown, with the same sign.
...
— minimum value for an object of type short int
SHRT_MIN -32767 // −(2^15 − 1)
— maximum value for an object of type short int
SHRT_MAX +32767 // 2^15 − 1
— maximum value for an object of type unsigned short int
USHRT_MAX 65535 // 2^16 − 1
— minimum value for an object of type int
INT_MIN -32767 // −(2^15 − 1)
— maximum value for an object of type int
INT_MAX +32767 // 2^15 − 1
— maximum value for an object of type unsigned int
UINT_MAX 65535 // 2^16 − 1
(про остальные типы см. там же)
---------- Post added at 19:37 ---------- Previous post was at 19:28 ----------
Путем допиливания оптимизатора (в будущем) эту проблему может можно будет решить? (путем реализации какого-нить кастомного pass-а, llvm в этом плане очень гибок, насколько я понимаю)
Согласен. Например можно написать код на llvm с использованием 8-битной арифметики и код для z80 будет соответствующим.
mastermind, спасибо за ссылку) Как-то интуитивно тоже полагал что int не может быть меньше 16 бит. Значит оставлю пока все как есть.
Да. Либо pass к llvm, либо к clang. Пока точно не разобрался как правильнее и проще будет сделать. Но это реально)
PS. Если кому-то интересно то, что уже реализовано, что планируется и какие спорные вопросы сейчас решаются, то можете спрашивать в этой теме. Могу просто освещать новые реализованные возможностями с примерами для общего анализа и получения лучшего результата.
Последний раз редактировалось EARL; 19.10.2012 в 20:50.
Конечно, интересно все Тема очень интересная.
---------- Post added at 20:12 ---------- Previous post was at 19:59 ----------
Бегло просмотрел насчет преобразования типов операндов (в вышеупомянутом стандарте со стр. 42), вроде как совсем не обязательно char и т.п. преобразовывать "вверх" до int, сказано только о том что на месте int и unsigned int могут использоваться типы с меньшим "conversion rank", и в этих случаях они преобразовываются в int или unsigned int.
Т.е. если все операнды, скажем, восьмибитные и результат тоже, то по идее ничего никуда преобразоывать не нужно. (или я чего-то не дочитал) Так что возможно, вышеописанное преобразование всего до int не более чем особенность реализации clang, а не стандарт.
mastermind, судя по комментариям в исходниках clang преобразование к типу int сделано совместимо с gcc. Но сейчас это не так важно, т.к. сперва нужно допилить backend к llvm, а после уже можно будет разобраться с clang.
Это я просто как-то решил добавить в clang возможность генерировать llvm код для процессора Z80 и заметил такие "странности" в расширением/усечением типов. Сейчас вернулся к дальнейшей работе над backend'ом.
Последний раз редактировалось EARL; 19.10.2012 в 21:48.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)