OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Суббота, 14 Июнь, 2025 16:33

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




Начать новую тему Ответить на тему  [ Сообщений: 332 ]  На страницу 1, 2, 3, 4, 5 ... 17  След.
Автор Сообщение
 Заголовок сообщения: Oberon/Ur
СообщениеДобавлено: Суббота, 29 Июнь, 2024 15:11 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
для тестирования приватного форка Nanojit понадобилось сделать к нему какой-то язык. и я подумал: а почему бы этому языку не быть обероном? на проект пока потрачено три дня, сейчас может скомпилировать и запустить примерно такое:
Код:
MODULE n0test_00;

IMPORT Log;

TYPE
  INT = INTEGER;

  MyRec = RECORD
    a: INT;
    b: REAL;
  END;

VAR
  a0: INT;
  r0: MyRec;

BEGIN
  r0.a := 666_69;
  r0.b := 666.999;
  Log.String("HI"+"!");
  Log.Ln;
  Log.String("r0.a=");
  Log.Int(r0.a);
  Log.Ln;
  Log.String("r0.b=");
  Log.Real(r0.b);
  Log.Ln;
  a0 := 69;
  Log.String("a0=");
  Log.Int(a0);
  Log.Ln;
  Log.Real(66.9);
  Log.Ln;
  Log.String("a0(real)=");
  Log.Real(a0);
  Log.Ln;
  Log.Real(6.69);
  Log.Ln;
  Log.Int(660 + 9);
  (*Log.Int("BOO!");*)
  Log.Ln;
  Log.Int(29AH);
  Log.Ln;
  Log.Int(16%29A);
  Log.Ln();
  Log.Int($29A);
  Log.Ln();
END n0test_00.

на самом деле это сильно больше чем может показаться: почти полный компилятор. вся внутренняя механика типов, переменных, процедур (они есть, их только объявлять пока нельзя ;-), модулей — на месте. компилятор многопроходный: source → ast → ast-materialized → lir → native code.

теоретически Nanojit поддерживает x86, x86_64 и arm (32), но практически мне весь этот зоопарк тупо нечем собирать. под шинду и 32-бит x86 пинус, однако, собирается. и даже работает.

это так, early announce. доведение до полноценной реализации (с Kernel, написаном на самом NanoOberon) возможно, но не гарантируется.

исходные тексты компилятора я, может, выложу в итоге. правда, они во-первых, на крестах, а во-вторых, совершенно бесполезны без моего форка Nanojit, который выложен не будет. но чисто посмотреть — почему бы и да.

с Nanojit есть некоторые проблемы (он в целом не особо предназначен для подобного рода издевательств), но тем не менее держится вполне неплохо. дополнительное SSA-представление я не делал как раз затем, чтобы посмотреть, на что способен Nanojit при вот таком тупом использовании «в лоб».

а. если вдруг из текста не очень ясно. NanoOberon не умеет делать бинарники, и уметь не будет. только взлетать с нуля из исходных текстов на обероне. ну, сам компилятор — бинарник, на крестах (потому что Nanojit на крестах), а остальное всё из обероновских исходников на лету. я бы и компилятор на обероне сделал, но тогда взлетать нечем. ;-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Суббота, 29 Июнь, 2024 22:06 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
ещё скажу, что на «построение компиляторов» я забил большой и тяжёлый; внутри компилятор состоит из огромной кучи специализированых AST-нод. причём на первом этапе текст парзится в ноды типа `NodeId`, `NodeDot`, без уточнений. и только когда всё отпарзилось — по всему дереву запускается `Node.resolve()`. резолвер возвращает новую ноду (или самого себя, если так подходит). те же `NodeId` превращаются в `NodeGlobalVar` или `NodeLocalVar`, точечки — в `NodeField`, и так далее. и на третьем этапе у нас уже гарантировано валидное дерево, где у каждой ноды указан правильный тип, так что спокойно делаем `Node.emitLIR()`.

конечно, это значительно медленней, чем простой однопроходный компилятор. зато независимые части чётко отделены друг от дружки, и в том же парзере не путается под ногами код для построения и проверки таблиц символов, например. равно как и `emitLIR()` никакими символами уже не интересуется: там все адреса и смещения уже решены.

`emitLIR()` тут легко заменяется на что угодно другое, хоть на `emitSSA()` (SSA потом, правда, придётся канонизировать, но это мелочи). и некоторые оптимизации можно делать прямо по дереву (хоть и не очень удобно).

собственно, и CP2 надо было бы переписать таким образом, но: «работает — не трогай!»

одно из достоинств/недостатков подобного подхода — никакие forward declarations больше не нужны. я пока не решил, энфорсить правило «всё должно быть объявлено заранее» или нет. с одной стороны мне правило нравится, а с другой — это рудимент однопроходности же.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Воскресенье, 30 Июнь, 2024 08:18 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
я опять в тягостных раздумьях. по специфике компилятора получается забавное: вычислять константы и актуализировать типы можно лениво. но нужно ли?

то есть: если у нас есть `CONST SomethingSomething = AnotherSomething * 69;`, а само `AnotherSomething` отсутствует — то компилятор вычислит константу только в момент её использования. а если нигде не используется — то и не станет, ему не надо.

то же самое с `MyPtr = POINTER TO YetUnknownStruct`: если нигде переменная типа `MyPtr` не объявлена — то и `YetUnknownStruct` может не быть — кому не всё равно?

чтобы этого избежать — надо предпринимать специальные меры. необходимость которых у меня под большим вопросом. с одной стороны — ну да: код типа должен быть корректным. а с другой — не всё ли равно, корректен ли код, который нигде никогда не используется?

та же фигня, кстати, и с процедурами выходит: ежели процедура никем не вызывается и не экспортируется — то её и не резолвят. синтаксически она парзится, но вполне может не пройти проверку типов.


если кто-то кроме роботов таки читает, то как думаете: делать лишние телодвижения, или ну его нафиг? в принципе, с учётом того, что язык вообще больше на скриптовый похож (ибо по сути напрямую выполняет обероновские исходники) — хрен бы с ним, с неисполняемым. а с другой стороны — попахивает.

сделать опцию «проверяй всё» плохой вариант: это как раз проявление дурацкого «фичеризма» — когда автор не может сам решить, как надо делать, и сваливает решение на пользователя, отмазываясь «предоставлением выбора». это плохой, ненужный выбор. псевдовыбор.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Воскресенье, 30 Июнь, 2024 20:48 

Зарегистрирован: Пятница, 13 Март, 2015 16:40
Сообщения: 619
arisu писал(а):
... как думаете: делать лишние телодвижения, или ну его нафиг?...

"Никаких поцелуев!!! Мочии-и-и!!!" (C) CelebrityDeathMatch, MTV


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Воскресенье, 30 Июнь, 2024 23:35 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
ну, я в итоге да: сделал ленивое, потому что так проще. сайд-эффект:
Код:
CONST
  Love = Base + 69;
  Hell = Base + 666;
  Base = 10000;

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

а теперь всё это надо переделывать, потому что Nanojit поддерживает максимум восемь аргументов. минус один на потенциальный `self`, минус один на непрямой вызов (потому что так там сделано: если надо непрямой вызов, то адрес передаётся последним аргументом). осталось шесть. маловато будет! один открытый массив два съедает. придётся делать логику заворачивания в скрытую структуру на стеке. собственно, avm+ и tamarin так и делали.

в принципе — этот контекст всяко полезен, потому что он и для вложеных процедур нужен.

вот сижу и думаю: если сделать полноценную поддержку Component Pascal — можно BBCB из исходников при старте поднимать. совершенно бесполезно, жутко неэффективно, но забавно. только LONGINT придётся даблом эмулить, с ограничением на 51 бит. делать такое, конечно, лень, но.

на всякий случай напомню, что я всё ещё обкатываю Nanojit, а не просто пилю очередной бесполезный компилятор оберона. ;-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 00:22 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
запилил процедуры, локальные переменные, рекурсию, `IF` и `WHILE`.

с рекурсией не всё так просто: у Nanojit нет инструкции: «вызови то, не знаю что, потом пропатчим». адрес вызова должен быть известен на момент компиляции инструкции. так что рекурсия сделана через косвенные вызовы по указателю, который суют в область констант. компилятор достаточно умён чтобы делать это только когда надо, вне зависимости от порядка объявления процедур.

также у Nanojit есть ещё один квирк: аргументы функций изменять нельзя. вообще. никак. нет таких инструкций. можно только читать. оно, конечно, красиво и правильно, но в обероне-то можно! пришлось сделать в компилере хак: если он обнаруживает присваивание аргументу, то генерит пролог с копированием оного аргумента в стековый локал, и потом при генерации кода прозрачно работает с этим локалом. ну, кривовато. зато it works.

заодно бампнул максимальное количество аргументов в Nanojit с восьми до шестидесяти трёх. на самом деле самая большая проблема с этим в том, что нано паковал типы аргументов и результата в `uint32_t` — отсюда и ограничение на восемь. эту часть пришлось переделать на битовый массив.

в общем, теперь умеем в вот такое:
Код:
MODULE n0test_00;

IMPORT Log;

TYPE
  INT = INTEGER;

  MyRec = RECORD
    a: INT;
    b: FLOAT;
    r: RECORD
      d: INT;
    END
  END;

  MyRec1 = RECORD
    ival: INT;
  END;

  MyRec3Ptr = POINTER TO MyRec3;
  MyRec4Ptr = POINTER TO MyRec4;

  MyRec2 = RECORD
    r: MyRec1;
    a: INT;
    (*pp: MyRec3Ptr;*)
    b: FLOAT;
  END;

  MyRec3 = RECORD
    x: DOUBLE;
    y: MyRec4Ptr;
  END;

CONST
  Love = Base + 69;
  Hell = Base + 666;
  Base = 10000;

VAR
  a0: INT;
  r0: MyRec;
  r2: MyRec2;


PROCEDURE Proc (arg: INTEGER);
BEGIN
  Log.String("IN `Proc`: arg="):Int(arg):Ln;
  Proc1(arg + 3);
END Proc;

PROCEDURE Proc1 (a: INTEGER);
BEGIN
  Log.String("IN `Proc1`: arg="):Int(a):Ln;
  IF a = 666 THEN Log.String("***HELL**"):Ln
  ELSIF a = 669 THEN Log.String("***LOVE**"):Ln
  END IF;
END Proc1;


PROCEDURE Recurse (a: INTEGER);
BEGIN
  Log.String("R-ENTER: a="):Int(a):Ln;
  IF a > 0 THEN Recurse(a - 1) END IF;
  Log.String("R-EXIT: a="):Int(a):Ln;
END Recurse;


PROCEDURE ProcWhile (a: INT);
VAR cnt: INT;
BEGIN
  Log.String("ProcWhile: start: a="):Int(a):Ln;
  cnt := a;
  WHILE cnt # 0 DO
    Log.String("  PWW: cnt="):Int(cnt):Ln;
    (*a := a - 1;*)
    DEC(cnt);
  END WHILE;
  Log.String("ProcWhile: end: a="):Int(a):Ln;
END ProcWhile;


PROCEDURE ProcWhile1 (a: INT);
BEGIN
  Log.String("ProcWhile1: start: a="):Int(a):Ln;
  WHILE a # 0 DO
    Log.String("  PWW: a="):Int(a):Ln;
    (*a := a - 1;*)
    DEC(a);
  END WHILE;
  Log.String("ProcWhile1: end: a="):Int(a):Ln;
END ProcWhile1;


PROCEDURE ProcWhile2 (a: INT);
BEGIN
  Log.String("ProcWhile2: start: a="):Int(a):Ln;
  WHILE a # 0 DO
    Log.String("  PWW: a="):Int(a):Ln;
    a := a - 1;
  END WHILE;
  Log.String("ProcWhile2: end: a="):Int(a):Ln;
END ProcWhile2;


BEGIN
  Log.String("HI"+"!"):Ln;
  r0.a := 666_69;
  r0.r.d := Love;
  r0.b := 666.999;
  Log.String("r0.a="):Int(r0.a):Ln;
  Log.String("r0.b="):Float(r0.b):Ln;
  Log.String("r0.r.d="):Int(r0.r.d):Ln;

  r2.a := 666_69;
  r2.b := 666.999;
  r2.r.ival := Hell;
  Log.String("r2.a="):Int(r2.a):Ln;
  Log.String("r2.b="):Float(r2.b):Ln;
  Log.String("r2.r.ival="):Int(r2.r.ival):Ln;

  a0 := 69;
  Log.String("a0="):Int(a0):Ln;

  Log.Float(66.9):Ln;
  Log.String("a0(real)="):Float(a0):Ln;

  Log.Float(6.69):Ln;
  Log.Int(660 + 9):Ln;
  Log.Int(29AH); Log.Ln;
  Log.Int(16%29A):Ln();
  Log.Int($29A); Log.Ln();

  Proc($290 + 10);

  Recurse(4);

  a0 := 3;
  WHILE a0 # 0 DO
    Log.String("W: a0="):Int(a0):Ln;
    (*a0 := a0 - 1;*)
    DEC(a0);
  END WHILE;

  ProcWhile(5);
  ProcWhile1(5);
  ProcWhile2(5);
END n0test_00.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 01:08 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
p.s.: компилятор, кстати, дубовый и адово рекурсивный. даже `IF/ELSIF` через рекурсию парзится. так проще, удобней, и меня вполне устраивает сегфолт, если стек закончился.

алсо, тайпкасты будут. но через `CAST(typename)(expr)`. AO-шное `typename(expr)` мне не нравится: грепнуть все касты сложнее. ;-)

и `LSH` не нравится. будет для легаси кода, но рядом будут и `SHL`, `SHR`, `SAR`.

надо пилить массивы, открытые массивы, и аттачить ко всему type tag'и. тогда можно будет приступать к GC.

p.p.s.: у Nanojit есть опкоды для арифметики с проверкой переполнения, кстати. использовать их, правда, не очень удобно. я пока не решил, нужна ли эта проверка вообще.

пуристы мне скажут, что конечно нужна. это Правильно и Хорошо. на что я им отвечу, что оберон даже локалы не инитит, так что прен-цен-дент наплевательства есть. `INTEGER` — это прибитое гвоздями знаковое 32-битное целое, и на это можно полагаться в ручных проверках переполнения. и я вам скажу, что намного более чаще чем нет эти проверки не нужны. так что я склоняюсь к тому, чтобы их если и делать, то опциональными. не опцией компилятора, а встроеной функцией или новым оператором.

как я уже где-то писал, надёжность оберона не в том, что он магически защищает программиста от алгоритмических ошибок программиста, а в том, что он не позволит сделать самые неприятные штуки — типа выхода за пределы массива и порубания хипа на лапшу. это всё ещё не освобождает от ручной проверки диапазонов, NIL и прочего. точно так же и переполнение интов надо проверять (если надо). в отличие от той же сишечки — переполнение индекса массива поймает range checker, например.

ещё никак не могу решить, нужен ли мне дурацкий юникод по-умолчанию. склоняюсь к мысли, что нафиг не нужен, и CHAR следует делать восьмибитовым целым без знака. разбазаривать четыре байта на ерунду — это перебор. в два байта юникод давно не влазит. и все нормальные API всё равно заточены на utf-8. так что эксперимент с большими CHAR-ами я считаю провалившимся. надо — будет LONGCHAR.

ах, да. FOR не будет. ну не нужно оно. и LOOP не будет: тоже не нужно. лучше попробую изобрести красивый синтаксис для итераторов Парнаса. WITH будет. и CASE будет как в CP, а не как в O7.

и RETURN прибивать гвоздями не буду, скорее всего. это — опять таки — идеологически правильно, но я довольно часто пишу код типа:
Код:
PROCEDURE Smth;
BEGIN
  IF wasDone THEN RETURN; END;
  <do-something>
  wasDone := TRUE;
END Smth;

нувыпонели. да, это криво с точки зрения Чистого Структурного. но лишний отступ, как по мне, читается намного хуже.

также подумываю над тем, чтобы повысить точку с запятой до терминатора. она сейчас опциональна (как в CP), но камон. я считаю, что её «сепараторность» — тяжёлое наследие паскаля. там это имело смысл для `if smth then smth else smth;`. в оберонах это смысла не имеет, и навсегда закроет холивар «ставите ли вы точку с запятой после последнего statement-а?»

а `TRUE` и `FALSE` повышены до ключевых слов. потому что тоже камон.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 02:22 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
и чтобы тупо доказать, что Оно Живое: текущая рабочая версия, под шинду 32 бита.

не стоит сильно стараться её поломать: у вас определённо получится. куча всего ещё не реализована. фактически, нормально работает только то, что в прилагаемом примере. ;-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 06:41 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
и о GC. я тут подумал, что можно обойтись без сканирования стека, запилив вместо этого полностью precise GC. на входе в процедуру с указателями создавать скрытый массивчик с указателями на все локалы, которые временные корни, и регистрировать этот массивчик. при выходе — дерегистрировать. тащемта, оверхэд — несколько mov да два быстрых call. ерунда. благо, у нас нет никаких дурацких исключений и `longjmp()`. а кто попробует — тот сам виноват.

и ещё подумал, что имеет смысл добавить тип STRING — строка типа дельфийской: динамического размера, refcounted, cow. и удобно, и технику rc/cow с Nanojit обкатать можно.

тем временем сделал short-circuit bools и функции (то есть, процедуры, которые что-то возвращают).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 06:47 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
кстати, не очень понимаю, почему `&` и `OR` не имеют отдельного уровня приоритетов. это чисто чтобы заэнфорсить более читабельные условия, что ли? `IF (a # b) & (c # d)` vs `IF a # b & c # d`. ну… в принципе, да. ладно, пусть будет. а то знаю я этих погромистов: если по рукам не бить — то и будут писать портянки без скобочек.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 06:48 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
а, блин! `SET` забыл впилить!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 12:04 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 485
Откуда: KZ
arisu писал(а):
также у Nanojit есть ещё один квирк: аргументы функций изменять нельзя. вообще. никак. нет таких инструкций. можно только читать. оно, конечно, красиво и правильно, но в обероне-то можно! пришлось сделать в компилере хак: если он обнаруживает присваивание аргументу, то генерит пролог с копированием оного аргумента в стековый локал, и потом при генерации кода прозрачно работает с этим локалом. ну, кривовато. зато it works.

load/store?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 13:10 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 485
Откуда: KZ
arisu писал(а):
пуристы мне скажут, что конечно нужна. это Правильно и Хорошо. на что я им отвечу, что оберон даже локалы не инитит, так что прен-цен-дент наплевательства есть. `INTEGER` — это прибитое гвоздями знаковое 32-битное целое, и на это можно полагаться в ручных проверках переполнения. и я вам скажу, что намного более чаще чем нет эти проверки не нужны. так что я склоняюсь к тому, чтобы их если и делать, то опциональными. не опцией компилятора, а встроеной функцией или новым оператором.

как я уже где-то писал, надёжность оберона не в том, что он магически защищает программиста от алгоритмических ошибок программиста, а в том, что он не позволит сделать самые неприятные штуки — типа выхода за пределы массива и порубания хипа на лапшу. это всё ещё не освобождает от ручной проверки диапазонов, NIL и прочего. точно так же и переполнение интов надо проверять (если надо). в отличие от той же сишечки — переполнение индекса массива поймает range checker, например.

Хорошо то, что вот это компилируется:
Код:
MODULE M;

  CONST C = 0E0000000H;

  VAR x: INTEGER;

BEGIN
  x := C
END M.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 18:44 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
Alexander Shiryaev писал(а):
load/store?
э… не совсем понял вопрос. если про Nanojit — то там есть только инструкция «получить значение параметра», и всё. implicit load, то бишь. обратной отчего-то нет. а я пока не настолько хорошо понимаю код нано чтобы сказать: её нет потому что какая-то архитектурная закавыка, или просто автору не понадобилось.

Alexander Shiryaev писал(а):
Хорошо то, что вот это компилируется:
Код:
MODULE M;

  CONST C = 0E0000000H;

  VAR x: INTEGER;

BEGIN
  x := C
END M.
я не очень понял, подколка ли это или нет. ;-) вообще, у меня переполнение не проверяется в том числе и парзером, и сворачивалкой констант (потому что это делается тем же `resolveExpr()` что и весь остальной код).

впрочем, даже если я и добавлю эти проверки, то подобное всё равно будет разрешено. по той логике, что INTEGER — это 32-bit 2-complement signed. мы это знаем, компилятор это знает, CPU это знает — и нет смысла притворяться, что оно не так. соответственно, нет и смысла отвергать альтернативные формы записи этих битов.

а в CP2 хексы вообще парзятся в LONGINT, без вариантов. диапазон проверяется только при присваивании, и — насколько помню — [MININT…MAXUINT]. как раз чтобы подобное работало.

я б, может, тоже проверял, но в языке у меня лонгинтов нет в принципе, а в крестах нормально проверить переполнение нельзя. я, конечно, использую "-fwrapv", но городить проверки ручками мне лень.


из свежих новостей: намедни впилил `&` и `OR`. и вспомнил, что забыл сделать VAR-аргументы. вот теперь сижу и думаю: то ли просто флагом обойтись, то ли завести полноценный тип `reference` (который как pointer, но не pointer). тип красивей, а флаг проще.


Последний раз редактировалось arisu Вторник, 02 Июль, 2024 18:57, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 18:53 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
и если кому испугаться, то текущие исходники компилера. чисто для непрактического интересу. автор особо дизайном не утруждался: что выросло — то выросло.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 19:09 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 485
Откуда: KZ
arisu писал(а):
Alexander Shiryaev писал(а):
load/store?
э… не совсем понял вопрос. если про Nanojit — то там есть только инструкция «получить значение параметра», и всё. implicit load, то бишь. обратной отчего-то нет. а я пока не настолько хорошо понимаю код нано чтобы сказать: её нет потому что какая-то архитектурная закавыка, или просто автору не понадобилось.

Ну в LLVM это было бы так:
Код:
void p (int *x) {
  *x = 5;
}

Код:
clang -O3 -c -emit-llvm -S test.c

Код:
define void @p(ptr  %0) {
  store i32 5, ptr %0
  ret void
}

Код:
clang -c test.ll
objdump -d test.o

Код:
test.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <p>:
   0:   c7 07 05 00 00 00       movl   $0x5,(%rdi)
   6:   c3                      ret


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 19:26 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 485
Откуда: KZ
arisu писал(а):
Alexander Shiryaev писал(а):
Хорошо то, что вот это компилируется:
Код:
MODULE M;

  CONST C = 0E0000000H;

  VAR x: INTEGER;

BEGIN
  x := C
END M.
я не очень понял, подколка ли это или нет. ;-) вообще, у меня переполнение не проверяется в том числе и парзером, и сворачивалкой констант (потому что это делается тем же `resolveExpr()` что и весь остальной код).

впрочем, даже если я и добавлю эти проверки, то подобное всё равно будет разрешено. по той логике, что INTEGER — это 32-bit 2-complement signed. мы это знаем, компилятор это знает, CPU это знает — и нет смысла притворяться, что оно не так. соответственно, нет и смысла отвергать альтернативные формы записи этих битов.

а в CP2 хексы вообще парзятся в LONGINT, без вариантов. диапазон проверяется только при присваивании, и — насколько помню — [MININT…MAXUINT]. как раз чтобы подобное работало.

я б, может, тоже проверял, но в языке у меня лонгинтов нет в принципе, а в крестах нормально проверить переполнение нельзя. я, конечно, использую "-fwrapv", но городить проверки ручками мне лень.

В BlackBox и в Project Oberon это компилируется, но если заменить 0E0000000H на 3758096384, то уже нет.
В voc/ofront — не компилируется.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 19:52 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
Alexander Shiryaev писал(а):
В BlackBox и в Project Oberon это компилируется, но если заменить 0E0000000H на 3758096384, то уже нет.
В voc/ofront — не компилируется.
а, понял. как минимум в CP2 это сделано вполне сознательно, да. в смысле, что с хексами так можно. унаследовано от OP2, я полагаю, а в OP2 из оригинального компилятора. то есть, это Вирт себе изначально сделал чтобы жизнь облегчить, видимо. ;-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 21:17 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 485
Откуда: KZ
Alexander Shiryaev писал(а):
arisu писал(а):
также у Nanojit есть ещё один квирк: аргументы функций изменять нельзя. вообще. никак. нет таких инструкций. можно только читать. оно, конечно, красиво и правильно, но в обероне-то можно! пришлось сделать в компилере хак: если он обнаруживает присваивание аргументу, то генерит пролог с копированием оного аргумента в стековый локал, и потом при генерации кода прозрачно работает с этим локалом. ну, кривовато. зато it works.

load/store?

Я неправильно понял.
В LLVM IR тоже нельзя, т. к. оно основано на SSA-форме.
Но можно выделить память на стеке через alloca, скопировать его (аргумент) туда и потом уже менять. То есть так же, как в Nanojit.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: NanoOberon/OberonJIT
СообщениеДобавлено: Вторник, 02 Июль, 2024 21:38 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1556
это и там тоже нелогично: технически аргументы — это те же самые локалы. никакое SSA не запрещает менять локалы, иначе оно бесполезно же.

просто у Nanojit изначально была заточка под житование javascript'а (или actionscript'а, что почти одно и то же). там в любом случае передают указатели на объекты, так что особого смысла в инструкции присваивания аргументу нет. вот и не сделали.

там, например, и понятия «функция возвращает ничего» нет — в js так не бывает. можно, конечно, обойти, возвращая тупо нолик, но я добавил `retv` (void, в смысле).

забавно, что Nanojit почти SSA… но почему-то этот последний шаг делать не стали. хотя там внутри даже попытки сэмулировать фита-ноды есть. к сожалению, консервативно, явно их создавать нельзя.

я бы, конечно, и с нуля кодоген на SSA сделал, но у Nanojit есть бэкэнды к x86_64 и ARM. на них у меня ушло бы слишком много усилий — в связи с отсутствием такого же опыта, как с x86.

а LLVM мне неинтересен в связи с монструозностью. Nanojit я могу просто кинуть в проект и всё, там даже STL не используется. есть ещё libJIT, она даже местами лучше (и SSA, и на чистом си), но её тоже не выйдет «просто кинуть и забыть».

на самом деле (я, вроде бы, писал уже) весь этот проект — это я пытаюсь оценить, насколько имеет смысл плотно возиться с Nanojit. то бишь, насколько трудоёмко будет использовать нано для AOT-компиляции реального языка. я в курсе, что JIT-ы придуманы не для этого, но почему бы и да? ;-) меня устраивает посредственный код, но быстро и в рантайме.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 332 ]  На страницу 1, 2, 3, 4, 5 ... 17  След.

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


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

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


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

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