Board.KolibriOS.org

Official KolibriOS board
It is currently Mon Apr 22, 2019 5:34 pm

All times are UTC+03:00




Post new topic  Reply to topic  [ 110 posts ]  Go to page Previous 13 4 5 6 7 8 Next
Author Message
PostPosted: Sun Apr 15, 2018 8:44 pm 
Offline

Joined: Sun Oct 30, 2011 6:43 pm
Posts: 1499
akron1 wrote:
Не подсвечиваются шестнадцатиричные константы и вложенные комментарии. Конечное END считается ошибкой, если в процедуре нет BEGIN, а такое возможно
Некоторые вещи пофиксил.
Теперь список процедур должен отображаться правильно в выпадающем списке:
Spoiler: Show
Attachment:
drop_down_list.PNG
drop_down_list.PNG [ 60.1 KiB | Viewed 1813 times ]
Процелурные типы
Code:
TYPE ProcName = PROCEDURE...
и переменные процедурных типов
Code:
Var ProcName : PROCEDURE...
тоже попадают в этот список.
Если это лишнее — убрать не долго, нужно отредактировать секцию <LABELS>...</LABELS> в файле ob07_spec.xml — убрать ненужные <Label.../>.

Комментарии сейчас могут быть дважды вложенными, то есть, например, так:
Code:
(* 
   (*
    *
    *  (* *** *)
    *
    *)
*)
Я просто не знаю, как это правильно реализовать, сделал, как смог
Spoiler: Show
comment2 может находится в контейнере comment1, который может находится в контейнере comment:
Code:
<Style id="comment"...
  <Blocks>
    <Block open="//" close="\n"/>
    <Block open="(*" close="*)"/>
  </Blocks>
</Style>
<Style id="comment1"...
  <Containers>
    <Open id="comment"/>
    <Close id="comment"/>
  </Containers>
  <Blocks>
    <Block open="(*" close="*)"/>
  </Blocks>
</Style>
<Style id="comment2"...
  <Containers>
    <Open id="comment1"/>
    <Close id="comment1"/>
  </Containers>
  <Blocks>
    <Block open="(*" close="*)"/>
  </Blocks>
Редактор HippoEDIT позволяет настроить выполнение той или иной программы(команды, bat, и т.п.) в зависимости от расширения открытого файла.
Вполне удобно иметь возможность компилировать и запускать скомпилированный файл прямо из редактора.

Для этого выбираем меню->Tools->Manage Tools
У меня в данный момент уже открыта вкладка с файлом с расширением .ob07, поэтому в меню отображается Manage Tools(Oberon-07)
Spoiler: Show
Attachment:
menu.PNG
menu.PNG [ 22.62 KiB | Viewed 1813 times ]
После открытия диалога Manage Tools(см. скриншот под спойлером ниже) выбираем в нём нажатием мыши значок Oberon-07.
Кнопкой Add добавляем новый пункт.
Указываем название(будет отображаться в меню Tools). Я назвал Ob-07 Compiler.
Указываем путь к исполняемому файлу компилятора.
Для сборки консольного приложения под Windows компилятору нужно указать опцию 'con', пишем в аргументах:
Code:
%MainFile% con  
Указываем Initial directory:
Code:
%FileDir%
Можно определить горячую клавишу, по нажатию которой будет запускаться нужная программа(или bat-файл).

Для того, чтобы запускать скомпилированный файл, создадим ещё один пункт.
Я назвал его Run.
В поле Command нужно ввести:
Code:
%MainFileDir%\%FileNameWOExt%.exe
Spoiler: Show
Attachment:
ob07+run.PNG
ob07+run.PNG [ 65.89 KiB | Viewed 1813 times ]

Теперь когда активная вкладка будет содержать открытый файл с расширением .ob07, то в меню Tools должны появиться два пункта: Ob-07 Compiler и Run.
Attachment:
Ob07_.7z [2.53 KiB]
Downloaded 59 times


Top
   
PostPosted: Mon Apr 16, 2018 8:54 pm 
Offline

Joined: Sun Oct 27, 2013 8:13 pm
Posts: 141
0CodErr wrote:
Процедурные типы и переменные процедурных типов тоже попадают в этот список.
Если это лишнее — убрать не долго
Да, это конечно, лишнее.

0CodErr wrote:
Комментарии сейчас могут быть дважды вложенными

Нормально, на практике бОльшая глубина не требуется.

При беглом осмотре нашел только один недочет: кроме суффикса "H" (INTEGER), шестнадцатиричные константы могут иметь суффикс "X" (CHAR), последние не подсвечиваются, но должны подсвечиваться как "строки".

В остальном -- отлично!

Сейчас пишу транслятор промежуточного байт-кода в ассемблер FASM, заодно и опробую HyppoEdit.
Байт-код не сложный, но обширный -- около 180 инструкций. Пока обработано только 30. Первые результаты несколько неоднозначные.
Такой код:
Code:
PROCEDURE test (n: INTEGER);
VAR
    a: INTEGER;
BEGIN
    WHILE n > 0 DO
        a := 7FFFFFFFH;
        WHILE a > 0 DO
            a := a - 1
        END;
        n := n - 1
    END
END test;

выполняется в 3 раза быстрее, чем скомпилированный текущим (старым) компилятором, но в 6-7 раз медленнее, чем Delphi7. Но тут понятно, Delphi хорошо оптимизирует: процедура-лист, две переменные -- два регистра. Мои компиляторы честно загружают и сохраняют переменные при каждом обращении. В более сложных случаях разрыв, наверно, будет меньше. Сделать полноценное распределение регистров, конечно, сложно, но можно будет попробовать выявить в программе места, в которых распределить регистры сравнительно просто (вроде этой процедуры), и транслировать такие процедуры по особым правилам.


Top
   
PostPosted: Mon Apr 16, 2018 10:45 pm 
Offline

Joined: Sun Oct 30, 2011 6:43 pm
Posts: 1499
akron1 wrote:
выполняется в 3 раза быстрее, чем скомпилированный текущим (старым) компилятором, но в 6-7 раз медленнее, чем Delphi7
Ну прогресс ведь уже есть — это главное!
Какое, кстати, внутреннее соглашение вызова(если не указано явно [stdcall] | [winapi]| [cdecl])?
akron1 wrote:
шестнадцатиричные константы могут иметь суффикс "X" (CHAR), последние не подсвечиваются, но должны подсвечиваться как "строки".
Пробовал такой регуляркой:
Code:
<Regexp text="[0-9][0-9A-F]*X" lead="[^\w]"/>
Вот здесь:
Code:
      <Style id="char" name="Char" text="1" bold="0" italic="0" underline="0" clr="Strings" bkclr="#FFFFFFFF">
        <Blocks>
          <Block open=""" close="""/>
          <Regexp text="[0-9][0-9A-F]*X" lead="[^\w]"/>
        </Blocks>
      </Style>
Проверял её в https://regex101.com/ и она там рабочая.
Но в HippoEDIT она не заработала. Вообще у меня не самая новая версия программы, может просто ещё тег Regexp не поддерживался.
Ни в одной синтаксической схеме, поставляемой с моей версией, не присутствует ни один тег Regexp.
В то же время в файлах отсюда https://www.hippoedit.com/syntax_files.php?lang=ru такой тег присутствует во многих местах, в частности в asm_arm_spec.xml:
Code:
      <Style id="number" extend="true">
        <Blocks>
          <!--  0xFFFF -->
          <Regexp text="0x[0-9A-Fa-f]+\>" lead="[^\w]"/>
          <!-- Binary: 0b1010 -->
          <Regexp text="0b[01]+\>" lead="[^\w]"/>
          <!-- Octal: 01234567 -->
          <Regexp text="0[0-7]\>" lead="[^\w]"/>
          <!-- Decimal  are built-in -->
        </Blocks>
      </Style>

0CodErr wrote:
Вставка шаблонов кода Code templates по Ctrl+Enter.
Как оказалось, клавишу Ctrl нажимать не всегда обязательно, в большинстве случаев достаточно Enter.
Есть ещё Ctrl+Пробелautocomplete(автоподстановка по первым введённым буквам).

Забыл сказать, что если выбрать опцию 'Capture output', тогда то, что компилятор выводит обычно в консоль, будет выведено прямо в редакторе в панель Output.
Потом его ещё вроде можно регулярками распарсить(Output Pattern).
Spoiler: Show
Attachment:
capture_output_hippo_edit.PNG
capture_output_hippo_edit.PNG [ 76.13 KiB | Viewed 1767 times ]


Top
   
PostPosted: Mon Apr 16, 2018 11:58 pm 
Offline

Joined: Sun Oct 27, 2013 8:13 pm
Posts: 141
0CodErr wrote:
Какое, кстати, внутреннее соглашение вызова(если не указано явно [stdcall] | [winapi]| [cdecl])?

По умолчанию stdcall.
Есть нюансы: массивы и записи всегда передаются по ссылке, но если перед формальным параметром-записью указано VAR, то на самом деле там будет передан не один параметр, а два: тип записи и адрес:
Code:
PROCEDURE (VAR r: REC);
procedure (typeof(r), adr(r)); stdcall

Если формальный параметр -- открытый массив (VAR или нет -- не важно), то кроме адреса передаются длины по всем измерениям:
Code:
PROCEDURE (a: ARRAY OF ... );
procedure (adr(a), len(a, 0), len(a, 1)...); stdcall

В новом компиляторе я изменил порядок передачи адреса и длин:
Code:
PROCEDURE (a: ARRAY OF ... );
procedure (len(a, 0), len(a, 1)..., adr(a)); stdcall

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


Top
   
PostPosted: Tue Apr 17, 2018 10:07 am 
Offline

Joined: Tue Mar 08, 2016 11:00 pm
Posts: 431
Может лучше уж опционально транслировать в LLVM ?

В FASM-никакой выгоды, на 1й взгляд.


Top
   
PostPosted: Tue Apr 17, 2018 1:39 pm 
Offline

Joined: Sun Oct 27, 2013 8:13 pm
Posts: 141
Новый компилятор отличается от старого не только "более лучшим" качеством результирующего кода, а также исходного (в последнее время я пишу значительно лучше). Отличается архитектура: есть четкое разделение на фронт-энд (исходный код -> промежуточное представление) и бэк-энд (промежуточное представление -> целевой код). Разделение настолько четкое, что сейчас это физически две отдельные программы. Предполагается, что таких бэк-эндов будет несколько, в принципе, можно будет сделать бэк-энд LLVM. Но пока я транслирую в FASM. Часто говорят, что трансляция ЯВУ в ассемблер не имеет никаких преимуществ. Но я с этим не согласен: это позволяет легко контролировать правильность трансляции, первое время не заниматься опкодами и вычислением меток, а потом можно без проблем заменить ассемблерный код на машинный. Как это и было в первый раз. Может быть, LLVM выдаст более эффективный машинный код, но ассемблер x86 -- это единственный низкоуровневый язык который я кое-как знаю. Всё остальное мне нужно сначала прочитать, осмыслить и только потом приступать к трансляции. В общем, пока цель -- FASM, потом FASM -> машинный код, а потом посмотрим...


Top
   
PostPosted: Tue Apr 17, 2018 2:59 pm 
Offline
User avatar

Joined: Tue Jul 04, 2017 5:14 pm
Posts: 19
akron1 wrote:
Байт-код не сложный, но обширный -- около 180 инструкций.


А можно, если это не секрет, узнать, почему так много?


Top
   
PostPosted: Tue Apr 17, 2018 3:29 pm 
Offline

Joined: Sun Oct 27, 2013 8:13 pm
Posts: 141
На самом деле, многие инструкции очень похожи, отличаются знаком операции, порядком и типом операндов.
Например, операции сравнения: их шесть ">", "<", ">=", "<=", "=", "#". Вроде немного...

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

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

18*3 = 54

То же самое можно сказать про арифметические операции: "+", "-" и т. д. А еще есть встроенные в язык процедуры: INC, ODD, LSL ... Вот так и получается ~180.

Конечно, некоторые инструкции полностью совпадают:

a > 5: больше(выраж, конст)
5 < a: меньше(конст, выраж)

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


Top
   
PostPosted: Tue Apr 17, 2018 5:50 pm 
Offline
User avatar

Joined: Tue Jul 04, 2017 5:14 pm
Posts: 19
akron1 wrote:
...

Ага, теперь всё понял. Благодарю за развёрнутый ответ.


Top
   
PostPosted: Tue Apr 17, 2018 7:21 pm 
Offline

Joined: Tue Mar 08, 2016 11:00 pm
Posts: 431
akron1 wrote:
Новый компилятор отличается от старого не только "более лучшим" качеством результирующего кода, а также исходного (в последнее время я пишу значительно лучше). Отличается архитектура: есть четкое разделение на фронт-энд (исходный код -> промежуточное представление) и бэк-энд (промежуточное представление -> целевой код). Разделение настолько четкое, что сейчас это физически две отдельные программы. Предполагается, что таких бэк-эндов будет несколько, в принципе, можно будет сделать бэк-энд LLVM. Но пока я транслирую в FASM. Часто говорят, что трансляция ЯВУ в ассемблер не имеет никаких преимуществ. Но я с этим не согласен: это позволяет легко контролировать правильность трансляции, первое время не заниматься опкодами и вычислением меток, а потом можно без проблем заменить ассемблерный код на машинный. Как это и было в первый раз. Может быть, LLVM выдаст более эффективный машинный код, но ассемблер x86 -- это единственный низкоуровневый язык который я кое-как знаю. Всё остальное мне нужно сначала прочитать, осмыслить и только потом приступать к трансляции. В общем, пока цель -- FASM, потом FASM -> машинный код, а потом посмотрим...

Возможно, если почитать и осмыслить чужой байт код - не только LLVM, есть же JVM, .net bc, hhvm итп, то найдутся удачные решения и для своего ?


Top
   
PostPosted: Tue Apr 17, 2018 10:35 pm 
Offline

Joined: Sun Oct 27, 2013 8:13 pm
Posts: 141
Siemargl wrote:
Возможно, если почитать и осмыслить чужой байт код - не только LLVM, есть же JVM, .net bc, hhvm итп, то найдутся удачные решения и для своего ?

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


Top
   
PostPosted: Tue Apr 17, 2018 11:12 pm 
Offline

Joined: Sun Oct 30, 2011 6:43 pm
Posts: 1499
akron1 wrote:
0CodErr wrote:
Процедурные типы и переменные процедурных типов тоже попадают в этот список.
Если это лишнее — убрать не долго
Да, это конечно, лишнее.
Убрал процедурные типы и переменные процедурного типа из выпадающего списка.
akron1 wrote:
При беглом осмотре нашел только один недочет: кроме суффикса "H" (INTEGER), шестнадцатиричные константы могут иметь суффикс "X" (CHAR), последние не подсвечиваются, но должны подсвечиваться как "строки".
Добавил для строковых шестнадцатеричных констант
Code:
<Regexp text="[0-9][0-9A-F]*X" lead="[^\w]"/> 
может в новой версии это заработает(у меня не самая новая).
Сейчас вместо stdcall|winapi|cdecl также допустимо писать какой-нибудь my_call, то есть, так:
Code:
    PROCEDURE [my_call] MyProcedure(Param1: INTEGER);
Attachment:
Ob07_.7z [2.23 KiB]
Downloaded 59 times


Top
   
PostPosted: Tue May 01, 2018 3:57 am 
Offline

Joined: Sun Oct 27, 2013 8:13 pm
Posts: 141
Осталась необработана только одна инструкция промежуточного кода. Она довольно сложная, и сходу я не придумал, как её эффективно транслировать в ассемблер. Это новая операция, в старой версии языка её нет и в уже написанных программах естесственно тоже, поэтому пока я отложил её реализацию, но на днях, конечно сделаю. Компилятор успешно транслирует свой собственный код, а также после небольших модификаций удалось скомпилировать и Editor.
Антивирусы не ругаются на GUI-приложения и я выяснил одну из причин, почему есть такая проблема со старым компилятором. Остается еще много мелких недоработок: не доделан рантайм, нет поддержки KolibriOS, не очень информативные сообщения об ошибках компиляции, нет удаления неиспользуемых процедур, ненадежная работа с плавающей точкой, возможно, что-то еще.
Новый компилятор создает чуть более компактный код, но код при этом более разнообразный и поэтому хуже сжимается. Похоже, что размер сжатого кода будет всё же чуть больше, чем у старого компилятора. Но зато по скорости большое преимущество.

Провел ряд тестов на скорость между новым, старым компилятором и tcc.
1. задача размытия изображения (blur)
2. рекурсивное вычисление чисел Фибоначчи (fib)
3. задача о ферзях (queens)
4. сортировка "пузырьком" целочисленного массива (фиксированной длины и нефиксированной (открытый массив)) (bubble, bubbleOA)

Результат сравнения со старым компилятором (во сколько раз новый быстрее)

queens 1.85
fib 2.52
blur 5.01 (!)
bubble 2.20
bubbleOA 9.20 (!)

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

Результат сравнения с tcc

queens 1.28
fib 1.02
blur 1.01

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

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

Превзойти tcc, это, конечно не великое достижение, но в сравнении с тем, что было, весьма неплохо.


Top
   
PostPosted: Tue May 01, 2018 9:59 am 
Offline

Joined: Sun Oct 30, 2011 6:43 pm
Posts: 1499
Ну, прогресс уже есть — это здорово!
Было бы ещё интересно сравнить результаты с другими реализациями Oberon(или Modula).
akron1 wrote:
Превзойти tcc, это, конечно не великое достижение, но в сравнении с тем, что было, весьма неплохо.
Конечно, неплохо! Может можно ещё добиться скорости за счёт оптимизированных стандартных модулей? Тогда меньше пришлось бы париться из-за качества кодогенерации.


Top
   
PostPosted: Tue May 01, 2018 1:33 pm 
Offline

Joined: Sun Oct 27, 2013 8:13 pm
Posts: 141
Компилятор XDS хоть и устаревший, но оптимизирующий, с ним сравнивать неинтересно и он еще имеет настройки оптимизации, вроде отключения проверок.
Можно будет сравнить с Black Box, он похоже один из лучших среди неоптимизирующих.

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

Впрочем, не все возможности исчерпаны: можно сделать табличный CASE, счетчики FOR хранить в регистрах. Вообще, компилятор использует только регистры eax, ecx и edx для хранения промежуточных значений выражений. Регистры ebx, esi, edi не используются и можно попробовать задействовать их для хранения часто используемых переменных, но для этого надо делать второй проход и серьезно изменить промежуточное представление.

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

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


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 110 posts ]  Go to page Previous 13 4 5 6 7 8 Next

All times are UTC+03:00


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited