OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 19 Март, 2024 11:16

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 77 ]  На страницу Пред.  1, 2, 3, 4
Автор Сообщение
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Пятница, 06 Май, 2016 10:32 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Воспользовался приемом, который придумал kekc_leader и в Linux теперь текстуры для вывода шрифтов генерирую так!

Сначала избавляемся от любых данных переменной длины в аргументах, у моем случае это вызов RendBlended, а потом вычисляем (подбираем экспериментально) на сколько надо сдвинуть данные, чтобы вызов библиотечной функции попал на кратный 16 адрес...

Код:
   PROCEDURE RendBlended0 (f: Font; string: ARRAY 64 OF CHAR; c: Color): Sdl2Video.Surface;
      VAR s: Sdl2CTypes.PSurface;
   BEGIN
      s := Win.RenderUNICODE_Blended(
               f(Font).f,
               SYSTEM.VAL(Sdl2CTypes.PUint16, SYSTEM.ADR(string)),
               SYSTEM.VAL(Sdl2CTypes.PColor, SYSTEM.ADR(c)));
      RETURN Sdl2StdLin.NewSurface(s)
   END RendBlended0;
   
   PROCEDURE RendBlended1 (f: Font; string: ARRAY 64 OF CHAR; c: Color): Sdl2Video.Surface;
      VAR pad1: INTEGER; s: Sdl2CTypes.PSurface;
   BEGIN
      s := Win.RenderUNICODE_Blended(
               f(Font).f,
               SYSTEM.VAL(Sdl2CTypes.PUint16, SYSTEM.ADR(string)),
               SYSTEM.VAL(Sdl2CTypes.PColor, SYSTEM.ADR(c)));
      RETURN Sdl2StdLin.NewSurface(s)
   END RendBlended1;

   PROCEDURE RendBlended2 (f: Font; string: ARRAY 64 OF CHAR; c: Color): Sdl2Video.Surface;
      VAR pad1, pad2: INTEGER; s: Sdl2CTypes.PSurface;
   BEGIN
      s := Win.RenderUNICODE_Blended(
               f(Font).f,
               SYSTEM.VAL(Sdl2CTypes.PUint16, SYSTEM.ADR(string)),
               SYSTEM.VAL(Sdl2CTypes.PColor, SYSTEM.ADR(c)));
      RETURN Sdl2StdLin.NewSurface(s)
   END RendBlended2;
   
   PROCEDURE RendBlended3 (f: Font; string: ARRAY 64 OF CHAR; c: Color): Sdl2Video.Surface;
      VAR  pad1, pad2, pad3: INTEGER; s: Sdl2CTypes.PSurface;
   BEGIN
      s := Win.RenderUNICODE_Blended(
               f(Font).f,
               SYSTEM.VAL(Sdl2CTypes.PUint16, SYSTEM.ADR(string)),
               SYSTEM.VAL(Sdl2CTypes.PColor, SYSTEM.ADR(c)));
      RETURN Sdl2StdLin.NewSurface(s)
   END RendBlended3;
   
   PROCEDURE RendBlended (f: Font; string: ARRAY 64 OF CHAR; c: Color): Sdl2Video.Surface;
      VAR  sp: INTEGER;
   BEGIN
      CASE SYSTEM.ADR(sp) MOD 16 OF
         0: RETURN RendBlended0 (f, string$, c)
      |  4: RETURN RendBlended1 (f, string$, c)
      |  8: RETURN RendBlended2 (f, string$, c)
      | 12: RETURN RendBlended3 (f, string$, c) END
   END RendBlended;
   
   PROCEDURE (f: Font) RenderUNICODE_Blended (string: ARRAY OF CHAR; color: INTEGER): Sdl2Video.Surface;
      VAR sp: INTEGER; c: Color; s: Sdl2CTypes.PSurface;
   BEGIN
      FillColor(color, c);
      RETURN RendBlended (f, string$, c)
   END RenderUNICODE_Blended;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Пятница, 06 Май, 2016 10:46 
Аватара пользователя

Зарегистрирован: Воскресенье, 12 Апрель, 2015 18:12
Сообщения: 1134
Откуда: СССР v2.0 rc 1
Ну, лезть в System, я стараюсь от слова "никогда".
Слишком это скользкий путь.
А что касается массивов переменной длины, так это вообще мина замедленного действия.
Начиная от управления памятью, заканчивая контролем целостности. Ноль в конце в строках Си -- уродское решение.
Строки в стиле Паскаля (первый байт-два-четыре -- длина строки) мне нравится куда больше.
Числовые массивы в виде каких-либо данных (файл, поток и всё-такое) просто требуют со страшной силой какой-то абстракции уровнем глубже.
Иначе чревата полная потеря контроля.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 07 Май, 2016 02:34 
Аватара пользователя

Зарегистрирован: Среда, 22 Апрель, 2015 23:51
Сообщения: 248
Откуда: г. Рига, Латвийская ССР
Иван Денисов писал(а):
Воспользовался приемом, который придумал kekc_leader и в Linux теперь текстуры для вывода шрифтов генерирую так!
Очень рад, что моя находка пригодилась.
Кстати, статья на Хабре ведь не о выравнивании начального адреса части стека при вызове процедуры (которое производится иногда по 4, а иногда - по 16 байт), а о выравнивании элементов внутри записи. Или с этим тоже возникают проблемы несовместимости в случае работы со шрифтами?

Насчёт включения такого выравнивания в линуксовскую версию ядра Блэкбокса. Возможно, я не знаю всех подробностей, но пока что склоняюсь к тому, что линуксовский Блэкбокс всегда должен выравнивать стековые блоки при вызовах процедур по 16 байт. Потому что:
1) Когда мы пишем программу, используя какую-нибудь стороннюю библиотеку, то сталкиваемся с тем, что в документации к библиотекам как правило не указываются особенности отдельных экспортируемых процедур, связанные с выравниванием начальных адресов. Например в документации к SDL2 нигде не указано про такую особенность процедуры SDL_FillRect, а также некоторых других процедур.
2) При попытке экспериментальным путём установить, какие из процедур нуждаются в особом выравнивании, мы сталкиваемся с необходимостью тестировать каждую процедуру отдельно, а также, что более существенно, с тем, что какая-либо процедура может при определённых обстоятельствах не требовать особого выравнивания, а при других - требовать. Например, в SDL2 это зависит от режима, в котором был создан прорисовщик (SDL_Renderer): аппаратный режим или программный. Программный режим использует особые инструкции процессора, для которых и необходимо выравнивание. С другой стороны, требования той или иной процедуры могут зависеть не только от программного контекста, но и от марки процессора, на которой происходит работа программы. Таким образом, нормально разрабатывать на линуксовской версии Блэкбокса программы, использующие сторонние библиотеки, принципиально не представляется возможным. Имеется в виду разработка программ в обероновском смысле, настоящая разработка, с возможностью верификации, а не механической проверки на всех возможных компьютерах, "работает или нет".
3) Проблема, изложенная в пункте №2, в GCC на Линуксе (начиная с определённой версии, с которой сама проблема и возникает) решается следующим образом: отрезок стека для любой процедуры выравнивается по 16 байт. На Линуксе практически все сторонние библиотеки компилируются с помощью GCC, а значит Блэкбокс (в своей версии для Линукса) должен быть совместим библиотеками, скомпилированными на GCC, то есть должен использовать такое выравнивание для всех процедур.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 07 Май, 2016 02:36 
Аватара пользователя

Зарегистрирован: Среда, 22 Апрель, 2015 23:51
Сообщения: 248
Откуда: г. Рига, Латвийская ССР
prospero78 писал(а):
Ну, лезть в System, я стараюсь от слова "никогда".
Слишком это скользкий путь.
А что касается массивов переменной длины, так это вообще мина замедленного действия.
Начиная от управления памятью, заканчивая контролем целостности. Ноль в конце в строках Си -- уродское решение.
Строки в стиле Паскаля (первый байт-два-четыре -- длина строки) мне нравится куда больше.
Числовые массивы в виде каких-либо данных (файл, поток и всё-такое) просто требуют со страшной силой какой-то абстракции уровнем глубже.
Иначе чревата полная потеря контроля.
Я не понял, к чему это? Просто так или это ответ на какое-то сообщение?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 07 Май, 2016 09:02 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
kekc_leader писал(а):
Таким образом, нормально разрабатывать на линуксовской версии Блэкбокса программы, использующие сторонние библиотеки, принципиально не представляется возможным. Имеется в виду разработка программ в обероновском смысле, настоящая разработка, с возможностью верификации, а не механической проверки на всех возможных компьютерах, "работает или нет".
Отлично сказано.

kekc_leader писал(а):
Кстати, статья на Хабре ведь не о выравнивании начального адреса части стека при вызове процедуры (которое производится иногда по 4, а иногда - по 16 байт), а о выравнивании элементов внутри записи. Или с этим тоже возникают проблемы несовместимости в случае работы со шрифтами?
С хабровской статьей я похоже напутал. Подумал, что эта проблема связана в том числе с выравниванием аргументов передаваемых функциям. Собственно я думал, что и ваша проблема именно в этом. Поэтому рекомендовал разные [union] и т.п. А потом, когда сам для генератора текстур делал этот выравнивающий прием, понял что суть проблемы именно в "выравнивании начального адреса части стека при вызове процедуры".


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 07 Май, 2016 12:43 
Аватара пользователя

Зарегистрирован: Среда, 22 Апрель, 2015 23:51
Сообщения: 248
Откуда: г. Рига, Латвийская ССР
Иван Денисов писал(а):
Подумал, что эта проблема связана в том числе с выравниванием аргументов передаваемых функциям.
Кстати, насколько я пока успел заметить, ни на Линуксе, ни на Виндоусе не возникают проблемы с выравниванием полей записей. Кажется, они и в GCC, и в Блэкбоксе выравниваются по 4 байта. Точнее, не просто по 4 байта, а немного хитрее. Наверное, это происходит точно также, как описано в «Построении Компиляторов» Н. Вирта (см. здесь, стр. 43). Надо бы проверить. Или кто-то, может быть, уже знает?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 07 Май, 2016 14:22 
Аватара пользователя

Зарегистрирован: Воскресенье, 12 Апрель, 2015 18:12
Сообщения: 1134
Откуда: СССР v2.0 rc 1
В БлекБоксе, если я правильно понимаю, Вирт специально ровнял всё по 4 байта для 32битного кода. GCC через pragma может заравнять что угодно, и как угодно. Но не надо.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Воскресенье, 08 Май, 2016 23:18 
Аватара пользователя

Зарегистрирован: Среда, 22 Апрель, 2015 23:51
Сообщения: 248
Откуда: г. Рига, Латвийская ССР
prospero78 писал(а):
В БлекБоксе, если я правильно понимаю, Вирт специально ровнял всё по 4 байта для 32битного кода. GCC через pragma может заравнять что угодно, и как угодно. Но не надо.
GCC тоже по умолчанию ровняет всё по 4 байта, если я не ошибаюсь.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Пятница, 20 Май, 2016 21:28 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Еще один пример. Вот так приходится тоже делать для RenderClear.

Код:
   (* RenderClear *)
   
   PROCEDURE RenderClear0 (this: Renderer);
   BEGIN this.res := Sdl2Lin.RenderClear(this.r)
   END RenderClear0;
   
   PROCEDURE RenderClear1 (this: Renderer);
   VAR pad1: INTEGER;
   BEGIN this.res := Sdl2Lin.RenderClear(this.r)
   END RenderClear1;
   
   PROCEDURE RenderClear2 (this: Renderer);
   VAR pad1, pad2: INTEGER;
   BEGIN this.res := Sdl2Lin.RenderClear(this.r)
   END RenderClear2;
   
   PROCEDURE RenderClear3 (this: Renderer);
   VAR pad1, pad2, pad3: INTEGER;
   BEGIN this.res := Sdl2Lin.RenderClear(this.r)
   END RenderClear3;
   
   PROCEDURE (this: Renderer) RenderClear ();
   VAR  sp: INTEGER;
   BEGIN
      CASE SYSTEM.ADR(sp) MOD 16 OF
         0: RenderClear0(this)
      |  4: RenderClear1(this)
      |  8: RenderClear2(this)
      | 12: RenderClear3(this) END
   END RenderClear;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 21 Май, 2016 00:14 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Удалось тут заменить на
Код:
   PROCEDURE (this: Renderer) RenderClear ();
   VAR  sp: INTEGER;
   BEGIN
      SYSTEM.GETREG(4, sp);
      SYSTEM.PUTREG(4, sp DIV 16 * 16 + 4);
      this.res := Sdl2Lin.RenderClear(this.r)
   END RenderClear;


Системы пока не понял, но теперь буду искать закономерность.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 21 Май, 2016 10:10 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Александр меня поправил, что так корректнее.
Код:
  PROCEDURE (this: Renderer) RenderClear ();
   VAR  sp: INTEGER;
   BEGIN
      SYSTEM.GETREG(4, sp);
      SYSTEM.PUTREG(4, sp DIV 16 * 16 - 12);
      this.res := Sdl2Lin.RenderClear(this.r)
   END RenderClear;

Так работает с этой процедурой. А вот со второй не хочет, там другое число переменных в функции и любое число 0,4,8,12 не помогает пока. Разбираюсь дальше.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 21 Май, 2016 10:19 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Код:
   PROCEDURE (this: Renderer) RenderClear ();
   VAR  sp: INTEGER;
   BEGIN
      SYSTEM.GETREG(4, sp);
      Log.String("SP: "); Log.Int(sp);  Log.Int(sp MOD 16); Log.Ln;
      SYSTEM.GETREG(5, sp);
      Log.String("FP: "); Log.Int(sp); Log.Int(sp MOD 16); Log.Ln;
      SYSTEM.GETREG(4, sp);
      SYSTEM.PUTREG(4, sp DIV 16 * 16 - 12);
      this.res := Sdl2Lin.RenderClear(this.r)
   END RenderClear;


FP тоже не выровнен по 16.

SP: -3332748 4
FP: -3332744 8


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 21 Май, 2016 15:34 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Подобрал для шрифтов тоже константу N, тут она не 12, а 4.

Код:
   PROCEDURE (f: Font) RenderUNICODE_Blended (string: ARRAY OF CHAR; color: INTEGER): Sdl2Video.Surface;
      VAR sp: INTEGER; c: Color;  s: Sdl2CTypes.PSurface;
   BEGIN
      FillColor(color, c);
      SYSTEM.GETREG(4, sp);
      SYSTEM.PUTREG(4, sp DIV 16 * 16 - 4);
      s := Win.RenderUNICODE_Blended(
               f(Font).f,
               SYSTEM.VAL(Sdl2CTypes.PUint16, SYSTEM.ADR(string)),
               SYSTEM.VAL(Sdl2CTypes.PColor, SYSTEM.ADR(c)));
      RETURN Sdl2StdLin.NewSurface(s)
   END RenderUNICODE_Blended;


Закономерность пока установить сложно. Все мои попытки поменять Kernel.Call пока не привели к успеху. Важно видимо какой у функции задается адрес (adr) при вызове в Meta, а также как то задается FP (frame pointer), а это происходит до вызова Kernel.Call, если я правильно понимаю. Пробовал в Meta ставить этот сдвиг стека перед Kernel.Call, тоже не годится. Frame Pointer пробовал менять в Kernel.Call тоже, но это ни к чему хорошему тоже не привело. Пока буду так пользоваться, подбирая параметр N.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 21 Май, 2016 21:44 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Еще две функции пролечил таком образом и теперь вроде все работает.

Код:
   PROCEDURE (this: Renderer) RenderFillRect (IN r: Sdl2Video.Rect);
   BEGIN
      SYSTEM.GETREG(4, sp);
      SYSTEM.PUTREG(4, sp DIV 16 * 16 - 8);
      this.res := Sdl2Lin.RenderFillRect(this.r, SYSTEM.VAL(Sdl2CTypes.PRect, SYSTEM.ADR(r)))
   END RenderFillRect;

   PROCEDURE (this: Renderer) RenderFillRects (IN r: ARRAY OF Sdl2Video.Rect; count: INTEGER);
   BEGIN
      SYSTEM.GETREG(4, sp);
      SYSTEM.PUTREG(4, sp DIV 16 * 16 - 4);
      this.res := Sdl2Lin.RenderFillRects(this.r, SYSTEM.VAL(Sdl2CTypes.PRect, SYSTEM.ADR(r)), count)
   END RenderFillRects;


Опубликовал результаты тут:
http://gitlab.molpit.org/bindings/sdl2


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Пятница, 11 Август, 2017 18:06 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3774
Проблема решена путем модификации компилятора. За доработку компилятора искренне благодарю luowy! Он добавил поддержку флага [ccall16], который обеспечивает выравнивание стека по 16-байтной границе, как того требуют библиотеки откомпилированные GCC версии больше 4.5 (https://en.wikipedia.org/wiki/X86_calli ... ions#cdecl).
Вложение:
Dev.zip [43.59 КБ]
Скачиваний: 367


Исправление внесено в хранилище Freenix, так что новая функциональность доступна в сборках на сайте ОберТон:
https://blackbox.obertone.ru/download

В итоге я заменил все [ccall] в сборке Sdl2 на [ccall16], и "хаки" с ручным выравниванием стека удалил.
http://comp.molpit.org/bindings/sdl2.txt
Мои модели нормально компилируются и работают с новым исправлением. Александр Ширяев тоже поглядел код, предложенный Luowy, и был исправлен недочет в одном месте. Так что мы решили включить это усовершенствование компилятора в основное хранилище и сборку.

Все это сильно облегчает дальнейшее развитие Блэкбокса в сторону использования SDL2 и других "выровненных" стороннних библиотек.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 10 Ноябрь, 2018 18:51 
Аватара пользователя

Зарегистрирован: Среда, 22 Апрель, 2015 23:51
Сообщения: 248
Откуда: г. Рига, Латвийская ССР
Дополнительная информация для интересующихся данным вопросом.


Тут написано, что GCC на x86 автоматически вставляет код в начало функции main, который подравнивает стек. (Человек спрашивает, что это такое и как это убрать.)

Код:
main:
leal    4(%esp), %ecx
andl    $-16, %esp
pushl   -4(%ecx)


Пояснение: «LEA is part of GCC's very clunky code to align esp by 16. It does this only in main in 32-bit code».

$-16 — это 0FFFFFFF0X, соответственно
Код:
andl $-16, %esp
снимает 4 наименее значимых бита у ESP, то есть обеспечивает истинность ESP MOD 16 = 0. А так как стек «растёт вниз», то это не приводит к потере данных.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NEW для структур без метки (untagged)
СообщениеДобавлено: Суббота, 10 Ноябрь, 2018 18:53 
Аватара пользователя

Зарегистрирован: Среда, 22 Апрель, 2015 23:51
Сообщения: 248
Откуда: г. Рига, Латвийская ССР
Вот как проблема решена в Блекбоксе (см. рис.). Голубым цветом выделены изменения, внесённые т. Луо.


Вложения:
diff.jpg
diff.jpg [ 157.87 КБ | Просмотров: 7561 ]
Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 77 ]  На страницу Пред.  1, 2, 3, 4

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB