OberonCore
https://forum.oberoncore.ru/

XDS 2.6 beta release
https://forum.oberoncore.ru/viewtopic.php?f=30&t=3739
Страница 4 из 6

Автор:  Александр Ильин [ Пятница, 06 Январь, 2012 11:57 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Евгений Темиргалеев писал(а):
Александр Ильин писал(а):
Вот, кстати, есть дополнительная польза от оптимизации. : )
Наверное, тут будет точнее --- есть дополнительная польза от мотивации Александра Ильина пользоваться компилятором XDS :)
Я имел в виду то, что оптимизатор берётся переинтерпретировать текст, написанный программистом, без потери смысла, и тем самым обнаруживает смысловые лакуны в первоисточнике.

Автор:  igor [ Пятница, 06 Январь, 2012 11:59 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Ещё из отличий новой версии XDS. Раньше, вроде, никогда не всплывало сообщение:
Код:
* [*** 0.00 F193]
* generation of new symbol file not allowed
По всей видимости это связано с проверкой согласованности импорта. Интересно, а раньше это не проверялось? Или проверялось и по тихому перекомпилировались все модули, которые импортируют этот?

Автор:  Александр Ильин [ Пятница, 06 Январь, 2012 12:03 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

igor писал(а):
Ещё из отличий новой версии XDS. Раньше, вроде, никогда не всплывало сообщение:
Код:
* [*** 0.00 F193]
* generation of new symbol file not allowed
Не, это всегда было. Надо включить опцию CHANGESYM (см. в xc.hlp).

Её выключают, чтобы запретить компилятору менять интерфейс модулей. Интерфейс может быть зафиксирован в связи с тем, что определения (definition modules) отдали заказчику, или наоборот, если определения получены от третьих лиц.

Автор:  igor [ Пятница, 06 Январь, 2012 12:40 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Александр Ильин писал(а):
igor писал(а):
Ещё из отличий новой версии XDS. Раньше, вроде, никогда не всплывало сообщение: ...
Не, это всегда было. Надо включить опцию CHANGESYM (см. в xc.hlp).
Посмотрел. Действительно, эта опция по умолчанию отключена, и в старой и в новой версии.
Включил у себя эту опцию :)

Автор:  GameHunter [ Пятница, 06 Январь, 2012 13:54 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Да, Вы нашли мою смысловую ошибку.
Интересно, а много ещё возможно ошибок, не вылезающих в отладочном режиме? В дельфях я такого вроде бы не встречал...

С меня чай, как и обещано :)

Автор:  Александр Ильин [ Пятница, 06 Январь, 2012 14:10 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

GameHunter писал(а):
В дельфях я такого вроде бы не встречал...
В Delphi неинициализированные стековые переменные работают точно так же, и точно так же могут давать псевдослучайные сбои. А вот при выделении под объект динамической памяти там обязательно затирается нулями весь блок.

Автор:  Александр Ильин [ Пятница, 06 Январь, 2012 15:12 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Александр Ильин писал(а):
Чтобы исправить ошибку, нужно в строке 165 модуля GeneralParticle заменить "PassedDistance:=0;" на "r.PassedDistance:=0;".
Alexey Veselovsky обратил внимание на то, что локальную переменную PassedDistance тоже надо инициализировать, так как она далее используется в выражении PassedDistance:=PassedDistance+...
Поэтому строку "r.PassedDistance:=0;" надо добавить рядом с "PassedDistance:=0;", а не заменить одно на другое, как я написал ранее.

Спасибо Alexey Veselovsky за внимательность!

Автор:  Александр Ильин [ Пятница, 06 Январь, 2012 19:33 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Что-то я разошёлся! Давно не работал с дизассемблером, так даже понравилось. Удалось надёжно воспроизвести ещё одну ошибку, о которую я встречал ранее, да ещё и в минимальном проекте. Вот код:
Код:
<* GENPTRINIT+ *> (* Make sure local pointers are initialized, including RECORD fields. *)
<* PROCINLINE+ *> (* Allow procedure inlining. *)
<* CHANGESYM+ *>
<* MAIN+ *>
MODULE Main;

(* ------------------------------------------------------------------------
 * (C) 2012 by Alexander Iljin
 * ------------------------------------------------------------------------ *)

IMPORT
   Out;

TYPE
   (* A stack-based RECORD type with a POINTER field. *)
   Writer = RECORD
      ptr: POINTER TO ARRAY OF CHAR; (* any pointer type will do *)
   END;

PROCEDURE InitModule; (* This procedure will be inlined. *)
VAR
   wr: Writer;
BEGIN
   (* Since GENPTRINIT is ON, the field wr.ptr must be set NIL, but that
    * does not happen if the procedure is inlined. The compiler simply does
    * not generate the initialization code (typically that would be a "push 0"
    * instruction), and whatever is in the stack is left in the pointer field.
    * In real-life programs this leads to random 'invalid location' traps. *)
   IF wr.ptr # NIL THEN
      Out.String('Error!');
   ELSE
      Out.String('Test passed.');
   END;
END InitModule;

BEGIN
   InitModule;
END Main.
Для компиляции выполнить: xc =make Main.ob2
Для запуска: main.exe
Выдаст "Error!" для XDS 2.50, 2.51, 2.60 beta.

Суть в том, что при включенной опции GENPTRINIT должны зануляться все локальные указатели, в том числе находящиеся внутри стековых RECORD'ов. И это происходит, но только в том случае, если процедура не заинлайнена. Если процедура инлайнится, то локальная инициализация не происходит, и на месте указателей имеем случайный стековый мусор.

Автор:  Александр Ильин [ Пятница, 06 Январь, 2012 19:47 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Вот ещё баг, полученный упрощением предыдущего:
Код:
<* GENPTRINIT+ *> (* Make sure local pointers are initialized, including RECORD fields. *)
<* PROCINLINE+ *> (* Allow procedure inlining. *)
<* CHANGESYM+ *>
<* MAIN+ *>
MODULE Main;

(* ------------------------------------------------------------------------
 * (C) 2012 by Alexander Iljin
 * ------------------------------------------------------------------------ *)

IMPORT
   Out;

PROCEDURE InitModule; (* This procedure will be inlined. *)
VAR
   ptr: POINTER TO ARRAY OF CHAR;
BEGIN
   (* Since GENPTRINIT is ON, the field wr.ptr must be set NIL, but that
    * does not happen if the procedure is inlined. The compiler simply does
    * not generate the initialization code (typically that would be a "push 0"
    * instruction), and whatever is in the stack is left in the pointer field.
    * In real-life programs this leads to random 'invalid location' traps. *)
   IF ptr # NIL THEN
      Out.String('Error!');
   ELSE
      Out.String('Test passed.');
   END;
END InitModule;

BEGIN
   InitModule;
END Main.
Здесь вместо стекового RECORD имеем обычную локальную переменную-указатель. При включенном GENPTRINIT её значение должно быть однозначно определено: NIL. Однако, XDS 2.50, 2.51 и 2.60 beta при запуске показывают совершенно неожиданный результат: "#RTS: unhandled exception #3: invalid location".
Оказывается, компилятор, не долго думая, просто заменяет код процедуры на пару инструкций:
Код:
push 3
call X2C_TRAP_F
По его мнению, тут однозначно будет трап, так что даже нет смысла генерировать код. А ведь код вполне осмысленный. Более того, нет даже попытки разыменования указателя ptr, идёт только лишь сравнение его с NIL. Трапу просто неоткуда взяться.

Интересно, что XDS 2.50 и 2.51 выдают при компиляции предупреждение
Код:
* [Main.ob2 30.07 W304]
* possibly used before definition "ptr"
   IF $ptr # NIL THEN
Это вполне справедливо, хотя при включенном GENPTRINIT этого предупреждения тоже быть не должно.

А XDS 2.60 beta уже дополнительно предупреждает о том нехорошем действии, что он задумал:
Код:
* [Main.ob2 30.11 W915]
* invalidLocation exception will be raised here
   IF ptr $# NIL THEN
Да, он собирается поднять там исключение. Почему? Зачем? Разыменования указателя как не было, так и нет.

PS: 2.50 и 2.51 тоже выдают предупреждение о том, что будет исключение, но только если отключить PROCINLINE.

Автор:  igor [ Воскресенье, 15 Январь, 2012 13:40 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Код:
PROCEDURE GetChar (): CHAR;
BEGIN RETURN CHR(65);  (* "A" *)
END GetChar;

PROCEDURE Do*;
VAR x: LONGINT; ch: CHAR;
BEGIN ch := CHR(65);
   x := 505 * ORD(ch);  (* ok *)
   x := 505 * ORD(GetChar());  (* whole overflow *)
END Do;
Почему в первой строчке всё OK, а во второй whole overflow? Какая компилятору разница? (XDS v2.60 beta)

На практике решил пролемку так:
Код:
   x := LONG(505) * ORD(GetChar());  (* ok *)

Автор:  Comdiv [ Понедельник, 16 Январь, 2012 12:17 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Если INTEGER и CHAR одинаковой разрядности, то понятно. В 1-м присваивании компилятор знает что значение ch - мало, и переполнения быть не может. Во 2-м присваивании значение 2-го множителя ему неизвестно, поскольку для процедуры Do считает функцию GetChar чёрным ящиком.

И Вместо LONG(505) 505L не подойдёт?

Автор:  igor [ Понедельник, 16 Январь, 2012 13:04 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Comdiv писал(а):
Если INTEGER и CHAR одинаковой разрядности, то понятно.
В данном контексте тип INTEGER 16-битный, а тип CHAR 8-битный (т. е. они разной разрядности).

Comdiv писал(а):
В 1-м присваивании компилятор знает что значение ch - мало, и переполнения быть не может. Во 2-м присваивании значение 2-го множителя ему неизвестно, поскольку для процедуры Do считает функцию GetChar чёрным ящиком.
И переменная ch, и функция GetChar() имеют одинаковый тип CHAR, известный уже на этапе компиляции. И даже если бы это было не так, то всё-равно, в обоих случаях функция ORD() возвращает результат типа INTEGER, и никакой другой.

Comdiv писал(а):
И Вместо LONG(505) 505L не подойдёт?
Нет, 505 - это десятичное число. Тогда, уж, лучше было бы записать 1F9L. Но это в Компонентном Паскале, а XDS не поддерживает КП.

Автор:  igor [ Понедельник, 16 Январь, 2012 13:10 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Кстати, константу 505 я для примера выбрал не случайно. Если значение этой константы уменьшить хотя бы на единицу, то произведение (504 * 65) будет меньше MAX(INTEGER), и переполнение не наступает в обоих случаях.

Собственно, вопрос даже не в том, "почему наступает" или "почему не наступает", а в том, почему по разному себя ведёт.

Автор:  Евгений Темиргалеев [ Понедельник, 16 Январь, 2012 13:19 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Предположение:
1) В первой строчке компилятор оптимизирует, не выполняя умножение.
2) Во второй выполняет, и, соответсвенно, ругается, что INTEGER*INTEGER->INTEGER даёт переполнение.

Попробуйте дизассемблировать первую строчку. Может там будет просто x := 32825

Автор:  igor [ Понедельник, 16 Январь, 2012 13:29 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

"Оптимизация-шмоптимизация" (С) Info21 :D

Евгений Темиргалеев писал(а):
Попробуйте дизассемблировать первую строчку. Может там будет просто x := 32825
Сворачивание констант? Да, надо будет посмотреть на досуге.

Автор:  Info21 [ Понедельник, 16 Январь, 2012 14:43 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

igor писал(а):
... а XDS не поддерживает КП
пока.

Автор:  Александр Ильин [ Понедельник, 16 Январь, 2012 17:04 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Евгений Темиргалеев писал(а):
Предположение:
1) В первой строчке компилятор оптимизирует, не выполняя умножение.
2) Во второй выполняет, и, соответсвенно, ругается, что INTEGER*INTEGER->INTEGER даёт переполнение.

Попробуйте дизассемблировать первую строчку. Может там будет просто x := 32825
Совершенно верное предположение. Это видно и без дизассемблера, достаточно добавить вывод x (Out.Int) и почитать предупреждения компилятора:
Код:
* [Test.ob2 15.04 W900]
* redundant code eliminated
   $ch := CHR(65);

* [Test.ob2 16.04 W900]
* redundant code eliminated
   $x := 505 * ORD(ch);  (* ok *)

* [Test.ob2 16.19 W314]
* variable "ch" has compile time defined value here
   x := 505 * ORD($ch);  (* ok *)

* [Test.ob2 17.12 W314]
* variable "x" has compile time defined value here
   Out.Int($x, 0);

Автор:  Comdiv [ Понедельник, 16 Январь, 2012 17:36 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Info21 писал(а):
igor писал(а):
... а XDS не поддерживает КП
пока.
Есть информация, что разработчики XDS собираются его поддерживать?

Автор:  igor [ Понедельник, 16 Январь, 2012 19:21 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Александр Ильин писал(а):
Евгений Темиргалеев писал(а):
Попробуйте дизассемблировать первую строчку. Может там будет просто x := 32825
Совершенно верное предположение. Это видно и без дизассемблера:
Код:
* [Test.ob2 16.04 W900]
* redundant code eliminated
   $x := 505 * ORD(ch);  (* ok *)

* [Test.ob2 16.19 W314]
* variable "ch" has compile time defined value here
   x := 505 * ORD($ch);  (* ok *)

* [Test.ob2 17.12 W314]
* variable "x" has compile time defined value here
   Out.Int($x, 0);

Из отчёта, предоставленного Александром, следует, что не только первая строчка вычисляется на этапе компиляции, но и вторая тоже. Получается, что различия не связаны с CompileTime или RunTime. То есть, в обоих случаях значение переменной "x" has compiler time defined. Формула INTEGER*INTEGER->INTEGER для обоих случаев одна и та же. Тем не менее, результат обработки этих двух строк компилятором различный.

Очевидное различие в обработке заключается в том, что в первом случае результат произведения неявно преобразуется к типу LONGINT, а во втором случае нет. Двойные стандарты, какбЭ :)

Автор:  Info21 [ Понедельник, 16 Январь, 2012 19:37 ]
Заголовок сообщения:  Re: XDS 2.6 beta release

Comdiv писал(а):
Info21 писал(а):
igor писал(а):
... а XDS не поддерживает КП
пока.
Есть информация, что разработчики XDS собираются его поддерживать?
Есть информация, что они могут это сделать достаточно быстро, как только почувствуют, что ситуация созрела.

Страница 4 из 6 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/