OberonCore https://forum.oberoncore.ru/ |
|
NEW для структур без метки (untagged) https://forum.oberoncore.ru/viewtopic.php?f=29&t=5664 |
Страница 3 из 4 |
Автор: | Иван Денисов [ Понедельник, 11 Апрель, 2016 21:30 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Ну не зря же вот тут авторы порта первого SDL использовали [union] в некоторых записевых типах и выделили это красным. Стоит учесть опыт. https://sourceforge.net/projects/sdl-for-oberon/ Там же поглядите хороший пример по условной компиляции с использованием селекторов. Это делает удобным кросс-разработку и в целом такие тесты. |
Автор: | prospero78 [ Понедельник, 11 Апрель, 2016 21:32 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
ох, ох, ох... Кекс сейчас ты задал сложный вопрос)) Компилятор лопатить это не дело. Если у тебя есть исходники SDL и gcc -- проще видоизменить вызов в этом исходники и чагой-та накомпилять, чем лезть во внутрь ББ/КП. Но, я тут, на самом деле не спец. Может Ваня что-то потолковее придумает))) |
Автор: | Alexander Shiryaev [ Понедельник, 11 Апрель, 2016 22:08 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Код: CONST SP = 4; (* register number of stack pointer *)
VAR sp: INTEGER; ... SYSTEM.GETREG(SP, sp); StdLog.String("SP MOD 16 = "); StdLog.Int(sp MOD 16); StdLog.Ln; |
Автор: | Alexander Shiryaev [ Понедельник, 11 Апрель, 2016 22:16 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Код: SYSTEM.GETREG(SP, sp);
SYSTEM.PUTREG(SP, sp DIV 16 * 16); |
Автор: | kekc_leader [ Вторник, 12 Апрель, 2016 00:18 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Иван Денисов писал(а): Ну не зря же вот тут авторы порта первого SDL использовали [union] в некоторых записевых типах и выделили это красным. Это делается в типе SDL_Event, но я вместо этого использую SYSTEM.VAL(SDL.KeyboardEvent, SYSTEM.ADR(event)). event у меня имеет тип SDL.Event - это запись, а KeyboardEvent - это указатель на запись. В OO2C тоже всё так работало. Да и в Блэкбоксе работает! Вырубается программа до того, как Event'ы вообще начинают использоваться.Я думаю, что если этот модуль скачать, там то же самое будет в Линуксе (на Винде же всё работает, т. к. там нет выравнивания по 16 байтов). В общем, надо попробовать. prospero78 писал(а): Если у тебя есть исходники SDL и gcc -- проще видоизменить вызов в этом исходники и чагой-та накомпилять, чем лезть во внутрь ББ/КП. Это, к сожалению, не вполне годится, т. к. получившаяся программа должна работать на произвольном Линуксе с предустановленым libSDL2-dev. Там GCC можно дать какой-то ключ, чтоб он не использовал инструкции SSE (и выравнивание по 16 байт), но тогда программу придётся поставлять вместе с перекомпилированным SDL2, а это плохо.Alexander Shiryaev писал(а): Код: SYSTEM.GETREG(SP, sp); SYSTEM.PUTREG(SP, sp DIV 16 * 16); |
Автор: | Alexander Shiryaev [ Вторник, 12 Апрель, 2016 00:51 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
kekc_leader писал(а): Alexander Shiryaev писал(а): Код: SYSTEM.GETREG(SP, sp); SYSTEM.PUTREG(SP, sp DIV 16 * 16); Точно не уверен, но думаю, что не надо, потому что наверное доступ к локальным переменным осуществляется относительно frame pointer. Но если заработает, то правильно лучше всё равно делать не так -- а использовать обёртку типа Lib.RectFill А frame pointer вроде бы всегда выровнен по 16 байт (но это тоже нужно проверить), поэтому если в Lib.RectFill размер локальных переменных кратен 16 байтам (FP - SP), то и SP менять не нужно. Код: SP = 4; (* register number of stack pointer *)
FP = 5; (* register number of frame pointer *) |
Автор: | Alexander Shiryaev [ Вторник, 12 Апрель, 2016 00:54 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Вообще можно сделать изменение в Kernel.Call, но ради SDL2 это делать неправильно. Лучше Kernel не трогать. |
Автор: | Alexander Shiryaev [ Вторник, 12 Апрель, 2016 01:05 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
kekc_leader писал(а): Иван Денисов писал(а): Ну не зря же вот тут авторы порта первого SDL использовали [union] в некоторых записевых типах и выделили это красным. Это делается в типе SDL_Event, но я вместо этого использую SYSTEM.VAL(SDL.KeyboardEvent, SYSTEM.ADR(event)). event у меня имеет тип SDL.Event - это запись, а KeyboardEvent - это указатель на запись.С [union] более правильно Вообще надо как можно меньше пользоваться SYSTEM. Например, в GraphLib можно вообще обойтись без SYSTEM. |
Автор: | kekc_leader [ Вторник, 12 Апрель, 2016 02:49 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Alexander Shiryaev писал(а): С [union] более правильно Да, пожалуй, стоит попробовать. Я исходил из того, что [union] не имеет аналогов во некоторых компиляторах Оберона. Хочется, чтобы программы без особых переписываний компилировались под разные компиляторы Оберона.Alexander Shiryaev писал(а): Вообще можно сделать изменение в Kernel.Call, но ради SDL2 это делать неправильно. Лучше Kernel не трогать. Я так понимаю, что не только SDL2 не будет работать, а чуть ли не любая библиотека, скомпилированная с помощью GCC под Линуксом. Если так, то мне представляется более правильным исправить эту несовместимость Линуксовской версии Блэкбокса с Линуксом.Alexander Shiryaev писал(а): Но если заработает, то правильно лучше всё равно делать не так -- а использовать обёртку типа Lib.RectFill Тоже думал об этом, но я не в курсе, как работают эти Stack Pointer и Frame Pointer (столкнулся с ними впервые), поэтому думал, что это ничего не изменит. Проверю и доложу результаты.
А frame pointer вроде бы всегда выровнен по 16 байт (но это тоже нужно проверить), поэтому если в Lib.RectFill размер локальных переменных кратен 16 байтам (FP - SP), то и SP менять не нужно. |
Автор: | Alexander Shiryaev [ Вторник, 12 Апрель, 2016 03:01 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
kekc_leader писал(а): Alexander Shiryaev писал(а): С [union] более правильно Да, пожалуй, стоит попробовать. Я исходил из того, что [union] не имеет аналогов во некоторых компиляторах Оберона. Хочется, чтобы программы без особых переписываний компилировались под разные компиляторы Оберона.Понятно. kekc_leader писал(а): Alexander Shiryaev писал(а): Вообще можно сделать изменение в Kernel.Call, но ради SDL2 это делать неправильно. Лучше Kernel не трогать. Я так понимаю, что не только SDL2 не будет работать, а чуть ли не любая библиотека, скомпилированная с помощью GCC под Линуксом. Если так, то мне представляется более правильным исправить эту несовместимость Линуксовской версии Блэкбокса с Линуксом.Нет, это скорее всего как-то связано с SSE. С другими библиотеками всё нормально -- и с libc, и с Gtk2. И не только в Linux, но и в OpenBSD. Ну и в Windows тоже -- а компилятор одинаковый, и эта часть Kernel тоже. |
Автор: | Alexander Shiryaev [ Вторник, 12 Апрель, 2016 03:14 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
kekc_leader писал(а): Alexander Shiryaev писал(а): Но если заработает, то правильно лучше всё равно делать не так -- а использовать обёртку типа Lib.RectFill Тоже думал об этом, но я не в курсе, как работают эти Stack Pointer и Frame Pointer (столкнулся с ними впервые), поэтому думал, что это ничего не изменит. Проверю и доложу результаты.А frame pointer вроде бы всегда выровнен по 16 байт (но это тоже нужно проверить), поэтому если в Lib.RectFill размер локальных переменных кратен 16 байтам (FP - SP), то и SP менять не нужно. https://en.wikipedia.org/wiki/Call_stack#Stack_and_frame_pointers |
Автор: | prospero78 [ Вторник, 12 Апрель, 2016 10:42 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Alexander Shiryaev писал(а): Вообще можно сделать изменение в Kernel.Call, но ради SDL2 это делать неправильно. Лучше Kernel не трогать. Я вот про это и писал. |
Автор: | kekc_leader [ Среда, 13 Апрель, 2016 01:17 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Alexander Shiryaev писал(а): Код: SYSTEM.GETREG(SP, sp); SYSTEM.PUTREG(SP, sp DIV 16 * 16); Alexander Shiryaev писал(а): А frame pointer вроде бы всегда выровнен по 16 байт (но это тоже нужно проверить), поэтому если в Lib.RectFill размер локальных переменных кратен 16 байтам (FP - SP), то и SP менять не нужно. Не уверен, что я правильно понял, что вы имели в виду, но я попробовал объявить в модуле GraphLib две процедуры:Код: PROCEDURE FillRect(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); Вторая нужна, чтобы не использовать метку [nil] в VAR-параметре rect, но это мелочи. Обе процедуры используются в самом этом модуле вместо вызововBEGIN IF SDL.FillRect(surface, rect, color) = 0 THEN END END FillRect; PROCEDURE FillAll(surface: SDL.Surface; color: INTEGER); BEGIN IF SDL.FillRect(surface, NIL, color) = 0 THEN END END FillAll; Код: SDL.FillRect(surface, rect, color) Но это не помогает. Всё равно в эти процедуры надо вписывать VAR x, y, z: INTEGER, причём количество INTEGER'ов зависит от того, откуда вызывается GraphLib.FillRect, а не от самой GraphLib.FillRect.Я попытался отрегулировать SP, но это не помогает. Пробовал по-разному. Код: PROCEDURE FillRect(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); В конце я восстанавливаю SP. Не знаю, надо это или нет, но программа дотуда всё равно не доходит.
CONST SP = 4; (* Register number of stack pointer *) FP = 5; (* Register number of frame pointer *) VAR sp, nsp: INTEGER; BEGIN StdLog.String('Enter G.FillRect'); StdLog.Ln; SYSTEM.GETREG(SP, sp); StdLog.String('SP ='); StdLog.Int(sp); StdLog.String('; SP MOD 16 ='); StdLog.Int(sp MOD 16); StdLog.Ln; nsp := (sp + 15) DIV 16 * 16; StdLog.String('New SP ='); StdLog.Int(nsp); StdLog.String('; New SP MOD 16 ='); StdLog.Int(nsp MOD 16); StdLog.Ln; SYSTEM.PUTREG(SP, nsp); StdLog.String('Call FillRect'); StdLog.Ln; IF SDL.FillRect(surface, rect, color) = 0 THEN END; StdLog.String('Restore register SP'); StdLog.Ln; SYSTEM.PUTREG(SP, sp); StdLog.String('End G.FillRect'); StdLog.Ln; END FillRect; |
Автор: | Alexander Shiryaev [ Среда, 13 Апрель, 2016 04:23 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
kekc_leader писал(а): Alexander Shiryaev писал(а): Код: SYSTEM.GETREG(SP, sp); SYSTEM.PUTREG(SP, sp DIV 16 * 16); Его и надо уменьшать. Правильно "sp DIV 16 * 16" kekc_leader писал(а): Alexander Shiryaev писал(а): А frame pointer вроде бы всегда выровнен по 16 байт (но это тоже нужно проверить), поэтому если в Lib.RectFill размер локальных переменных кратен 16 байтам (FP - SP), то и SP менять не нужно. Не уверен, что я правильно понял, что вы имели в виду, но я попробовал объявить в модуле GraphLib две процедуры:Код: PROCEDURE FillRect(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); Вторая нужна, чтобы не использовать метку [nil] в VAR-параметре rect, но это мелочи. Обе процедуры используются в самом этом модуле вместо вызововBEGIN IF SDL.FillRect(surface, rect, color) = 0 THEN END END FillRect; PROCEDURE FillAll(surface: SDL.Surface; color: INTEGER); BEGIN IF SDL.FillRect(surface, NIL, color) = 0 THEN END END FillAll; Код: SDL.FillRect(surface, rect, color) Но это не помогает. Всё равно в эти процедуры надо вписывать VAR x, y, z: INTEGER, причём количество INTEGER'ов зависит от того, откуда вызывается GraphLib.FillRect, а не от самой GraphLib.FillRect.Ну значит надо пробовать изменять SP. kekc_leader писал(а): Я попытался отрегулировать SP, но это не помогает. Пробовал по-разному. Код: PROCEDURE FillRect(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); В конце я восстанавливаю SP. Не знаю, надо это или нет, но программа дотуда всё равно не доходит.CONST SP = 4; (* Register number of stack pointer *) FP = 5; (* Register number of frame pointer *) VAR sp, nsp: INTEGER; BEGIN StdLog.String('Enter G.FillRect'); StdLog.Ln; SYSTEM.GETREG(SP, sp); StdLog.String('SP ='); StdLog.Int(sp); StdLog.String('; SP MOD 16 ='); StdLog.Int(sp MOD 16); StdLog.Ln; nsp := (sp + 15) DIV 16 * 16; StdLog.String('New SP ='); StdLog.Int(nsp); StdLog.String('; New SP MOD 16 ='); StdLog.Int(nsp MOD 16); StdLog.Ln; SYSTEM.PUTREG(SP, nsp); StdLog.String('Call FillRect'); StdLog.Ln; IF SDL.FillRect(surface, rect, color) = 0 THEN END; StdLog.String('Restore register SP'); StdLog.Ln; SYSTEM.PUTREG(SP, sp); StdLog.String('End G.FillRect'); StdLog.Ln; END FillRect; Надо так: "sp DIV 16 * 16" И ещё лучше вывести в лог fp MOD 16. |
Автор: | Alexander Shiryaev [ Среда, 13 Апрель, 2016 05:30 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Но так тоже работать не будет. Буду думать, что надо сделать... |
Автор: | kekc_leader [ Среда, 13 Апрель, 2016 10:03 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Есть предложение сделать так (это ужасно, но может быть, будет работать?): Код: (* Процедуры FillRect0, FillRect1, FillRect2 и FillRect3 отличаются только количеством переменных-пустышек *) Или даже можно брать не регистр, а адрес какой-нибудь переменной через SYSTEM.ADR(...).
PROCEDURE FillRect0(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); BEGIN SDL.FillRect(surface, rect, color) END FillRect0; PROCEDURE FillRect1(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); VAR pad1: INTEGER; BEGIN SDL.FillRect(surface, rect, color) END FillRect0; PROCEDURE FillRect2(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); VAR pad1, pad2: INTEGER; BEGIN SDL.FillRect(surface, rect, color) END FillRect0; PROCEDURE FillRect3(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); VAR pad1, pad2, pad3: INTEGER; BEGIN SDL.FillRect(surface, rect, color) END FillRect0; PROCEDURE FillRect(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); CONST SP = 4; (* Register number of stack pointer *) VAR sp: INTEGER; BEGIN SYSTEM.GETREG(SP, sp); CASE sp MOD 16 OF | 1: FillRect1(surface, rect, color) | 2: FillRect2(surface, rect, color) | 3: FillRect3(surface, rect, color) ELSE FillRect0(surface, rect, color) END (* Или в другом порядке, надо подобрать *) END FillRect; |
Автор: | Alexander Shiryaev [ Четверг, 14 Апрель, 2016 01:25 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
kekc_leader, так должно заработать: Код: PROCEDURE FillRect (surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER): INTEGER; CONST SP = 4; (* register number of stack pointer *) N = 12; (* 0 | 4 | 8 | 12 *) VAR sp: INTEGER; BEGIN SYSTEM.GETREG(SP, sp); SYSTEM.PUTREG(SP, sp DIV 16 * 16 - N); RETURN SDL.FillRect(surface, rect, color) END FillRect; Константу N надо подобрать опытным путём (4 варианта) Только потом не надо добавлять локальные переменные в FillRect |
Автор: | kekc_leader [ Четверг, 14 Апрель, 2016 01:37 ] | |||
Заголовок сообщения: | Re: NEW для структур без метки (untagged) | |||
Alexander Shiryaev писал(а): kekc_leader, так должно заработать: Я как-то так пробовал, но вроде ошибся с тем, что думал, что SP растёт в другую сторону, поэтому попробую ещё раз! А пока «решил» проблему так:Код: PROCEDURE FillRect (surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER): INTEGER; CONST SP = 4; (* register number of stack pointer *) N = 12; (* 0 | 4 | 8 | 12 *) VAR sp: INTEGER; BEGIN SYSTEM.GETREG(SP, sp); SYSTEM.PUTREG(SP, sp DIV 16 * 16 - N); RETURN SDL.FillRect(surface, rect, color) END FillRect; Константу N надо подобрать опытным путём (4 варианта) Код: PROCEDURE FillRect0(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); Сейчас работает и на Линуксовом Блэкбоксе, и на Виндоусовом. Пока тестировал, оказалось, что не SDL_FillRect может глючить (а может случайно и не заглючить) на Линуксе всегда, а SDL_RenderClear может глючить только в том случае, если при создании прорисовщика (SDL_Renderer) был выбран режим SDL_RENDERER_SOFTWARE. То есть если SDL_RENDERER_ACCELERATED, то очистка экрана идёт за счёт ГПУ, а если SOFTWARE, то за счёт того же SDL_FillRect:BEGIN IF SDL.FillRect(surface, rect, color) = 0 THEN END END FillRect0; PROCEDURE FillRect1(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); VAR pad1: INTEGER; BEGIN IF SDL.FillRect(surface, rect, color) = 0 THEN END END FillRect1; PROCEDURE FillRect2(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); VAR pad1, pad2: INTEGER; BEGIN IF SDL.FillRect(surface, rect, color) = 0 THEN END END FillRect2; PROCEDURE FillRect3(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); VAR pad1, pad2, pad3: INTEGER; BEGIN IF SDL.FillRect(surface, rect, color) = 0 THEN END END FillRect3; PROCEDURE FillRect(surface: SDL.Surface; VAR rect: SDL.Rect; color: INTEGER); CONST SP = 4; (* Register number of stack pointer *) VAR sp: INTEGER; BEGIN CASE SYSTEM.ADR(sp) MOD 16 OF 0: FillRect0(surface, rect, color) | 4: FillRect1(surface, rect, color) | 8: FillRect2(surface, rect, color) ELSE FillRect3(surface, rect, color) END END FillRect; PROCEDURE FillAll(surface: SDL.Surface; color: INTEGER); VAR r: SDL.Rect; BEGIN (* Equivalent to SDL.FillRect(surface, NIL, color) *) r.x := 0; r.y := 0; r.w := surface.w; r.h := surface.h; FillRect(surface, r, color) END FillAll; PROCEDURE RenderClear0(renderer: SDL.Renderer); BEGIN IF SDL.RenderClear(renderer) = 0 THEN END END RenderClear0; PROCEDURE RenderClear1(renderer: SDL.Renderer); VAR pad1: INTEGER; BEGIN IF SDL.RenderClear(renderer) = 0 THEN END END RenderClear1; PROCEDURE RenderClear2(renderer: SDL.Renderer); VAR pad1, pad2: INTEGER; BEGIN IF SDL.RenderClear(renderer) = 0 THEN END END RenderClear2; PROCEDURE RenderClear3(renderer: SDL.Renderer); VAR pad1, pad2, pad3: INTEGER; BEGIN IF SDL.RenderClear(renderer) = 0 THEN END END RenderClear3; PROCEDURE RenderClear(renderer: SDL.Renderer); VAR sp: INTEGER; BEGIN CASE SYSTEM.ADR(sp) MOD 16 OF 0: RenderClear0(renderer) | 4: RenderClear1(renderer) | 8: RenderClear2(renderer) ELSE RenderClear3(renderer) END END RenderClear; Код: /* Файл "src/render/software/SDL_render_sw.c" */
static int SW_RenderClear(SDL_Renderer * renderer) { SDL_Surface *surface = SW_ActivateRenderer(renderer); Uint32 color; SDL_Rect clip_rect; if (!surface) { return -1; } color = SDL_MapRGBA(surface->format, renderer->r, renderer->g, renderer->b, renderer->a); /* By definition the clear ignores the clip rect */ clip_rect = surface->clip_rect; SDL_SetClipRect(surface, NULL); SDL_FillRect(surface, NULL, color); SDL_SetClipRect(surface, &clip_rect); return 0; }
|
Автор: | Иван Денисов [ Пятница, 06 Май, 2016 07:22 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Сейчас сам плотно возобновил работу с SDL2 и столкнулся с этой проблемой. Я раньше не мог понять, почему нестабильно шрифты работают в SDL_ttf. Теперь благодаря вашему исследованию проверил и убедился в том, что проблема точно такая же! Когда Иван Кузьмицкий сделал BlackBox SDL я попытался его практически сразу запустить на Linux, но столкнулся с тем, что шрифты падают. Думал, что дело может быть в отличиях драйверов или что-то вроде того, но дело точно в выравнивании. Alexander Shiryaev писал(а): Вообще можно сделать изменение в Kernel.Call, но ради SDL2 это делать неправильно. Лучше Kernel не трогать. Александр, давай поправим компилятор в плане выравнивания? Я могу чем-то помочь тебе в этом? |
Автор: | Иван Денисов [ Пятница, 06 Май, 2016 08:22 ] |
Заголовок сообщения: | Re: NEW для структур без метки (untagged) |
Чтобы сохранить совместимость формата кодовых файлов надо видимо добавить отдельный ключ, например [3], который будет означать, что аргументы и переменные процедуры надо выровнять. UPD. Почитал вот эту статью: https://habrahabr.ru/post/142662/ В С++ такая проблема бы решалась такой командой: #pragma pack(push, 16) |
Страница 3 из 4 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |