БЕСМ6 компилятор, генерация кода /*code generation*/

122 views
Skip to first unread message

Alex Loktionoff

unread,
Mar 2, 2025, 7:57:42 AMMar 2
to БЭСМ-6
Решил открыть отдельную тему по кодогенерации для нового оптимизирующего компилятора. Тема по формату вызовов https://groups.google.com/g/besm6/c/LJ91waEdhzE/m/USweH2PIAgAJ так и остается, там будем обсуждать только соглашения о вызовах какие были и какие будут, чтоб не захламлять.

Сразу задам вопрос, кто-нибудь знает толковую книжку с хорошей теорией генерации кода из SSA?
Что-то я с наскока не нашел, вот даже по компиляторам AST, SSA преобразования и оптимизации циклов есть хорошие теории, а по оптимальной кодогенерации не вижу.
У меня вообще складывается впечатление, что кодогенерация обычно делается "чтоб не глючило" и в продакшн, то что есть open-source.

У нас весьма специфическая архитектура - аккумулятор со стеком, с одной стороны очень просто все перевести RPN и генерируй ассемблер инструкция за инструкцией. Но есть индексные регистры и хотелось бы их задействовать по максимуму для целочисленной арифметики, но их сохранение восстановление тормозит не только конвейер но и операции с аккумулятором :( Да еще и просто так не вычтешь/умножишь надо накладывать порядок 064 :((
Потом еще переключение режимов нормализации АЛУ тоже наверно занимает время. Общем модель процессора получается весьма специфическая, нужна хорошая теория под это, кто знает?
Соглашение о вызовах тоже влияет на кодогерерацию и оптимизацию, но это большая тема и я хотел бы все обсуждения относительно аллокации регистров, scheduling и кодогенерации вести здесь. 

Leo Broukhis

unread,
Mar 2, 2025, 6:29:26 PMMar 2
to be...@googlegroups.com
On Sun, Mar 2, 2025 at 4:57 AM Alex Loktionoff <oxy...@gmail.com> wrote:

Сразу задам вопрос, кто-нибудь знает толковую книжку с хорошей теорией генерации кода из SSA?

Лично не знаю. ChatGPT предложил

'Engineering a Compiler'
Авторы: Keith Cooper и Linda Torczon. Эта книга предоставляет глубокий анализ различных аспектов компиляторов, включая представление SSA и методы генерации машинного кода.

'Advanced Compiler Design and Implementation'
Автор: Steven Muchnick. Издание охватывает широкий спектр тем, связанных с дизайном и реализацией компиляторов, с акцентом на оптимизацию и использование SSA.

'Modern Compiler Implementation'

Автор: Andrew Appel. Серия книг, посвящённых современным методам реализации компиляторов, где рассматриваются вопросы использования SSA в процессе генерации кода.  

Потом еще переключение режимов нормализации АЛУ тоже наверно занимает время. Общем модель процессора получается весьма специфическая, нужна хорошая теория под это, кто знает?

Переключение режимов АЛУ - это совершенная мелочь. Если ИПМ РАН - приличное место, то у них могло что-то сохраниться про разработку компилятора FOREX, который, насколько мне известно, считался наиболее продвинутым в части оптимизации. Как они это делали - применением какого-то общего алгоритма с или чисто распознаванием часто используемых паттернов - неизвестно. Я бы предложил экспериментировать с компиляцией интересующих конструкций FOREX-ом, который, в отличие от других компиляторов, неплохо выносит переменные циклов на регистры.
 
Соглашение о вызовах тоже влияет на кодогерерацию и оптимизацию, но это большая тема и я хотел бы все обсуждения относительно аллокации регистров, scheduling и кодогенерации вести здесь. 

На первых порах я бы считал существующее в МС "Дубна" соглашение годным для использования (НЯМС, регистры 1-7 обязуется сохранять/восстанавливать вызываемая процедура; регистры 8-12,14 можно использовать свободно, и если они нужны вызывающей процедуре, то сохранять/восстанавливать их должна она). 

Реально, если хотеть получить какие-то практические результаты наиболее эффективным по трудозатратам образом, то имеет смысл разобраться в существующем коде Паскаль-компилятора - хоть на Паскале, хоть на С++ -  чтобы понять, как устроено промежуточное представление выражений (там пока понято не до конца), и как строится код для flow control, и отделить парсер Паскаля от кодогенератора. После этого можно будет взять какой-нибудь парсер С и прикрутить его к кодогенератору, получив рудиментарный, но функциональный компилятор С для БЭСМ-6.
Поначалу можно обойтись без оптимизации работы с char *, и считать их просто индексами в packed array [0..32768*6-1] of char, благо библиотечные процедуры для работы с упакованными массивами в Паскале уже есть.

И только после этого, и после того, как компилятор будет проходить тесты, будет иметь смысл начинать оптимизацию регистровых указателей, модифицировать представление char *, и т. п.

Leo

Serge Vakulenko

unread,
Mar 3, 2025, 12:51:15 AMMar 3
to БЭСМ-6
On Sunday, March 2, 2025 at 4:57:42 AM UTC-8 oxy...@gmail.com wrote:
Сразу задам вопрос, кто-нибудь знает толковую книжку с хорошей теорией генерации кода из SSA?

Я озадачивался этим вопросом в 1987 году, когда начинал возиться с Си-компилятором для БЭСМ. Опытные товарищи указывали на книжку Ахо-Ульмана. Тогдашнее издание было слишком теоретичное. Современное получше вроде. 

  
В результате я изучал кодогенерацию по исходникам компилятора PCC и статье Стива Джонсона:


С тех пор мне встречалось много литературы по компиляторам. Но вот так чтобы прочитать умную книжку, всё понять, сесть и написать кодогенератор - таких книг нету, увы. Есть Си-компиляторы, исходники которых могут служить неплохим пособием. К примеру: https://github.com/alexfru/SmallerC

--Сергей

Michael Yaroslavtsev

unread,
Mar 3, 2025, 2:38:34 AMMar 3
to be...@googlegroups.com
On Sun, Mar 2, 2025 at 9:51 PM Serge Vakulenko <serge.v...@gmail.com> wrote:
On Sunday, March 2, 2025 at 4:57:42 AM UTC-8 oxy...@gmail.com wrote:
Сразу задам вопрос, кто-нибудь знает толковую книжку с хорошей теорией генерации кода из SSA?

Я озадачивался этим вопросом в 1987 году, когда начинал возиться с Си-компилятором для БЭСМ. Опытные товарищи указывали на книжку Ахо-Ульмана. Тогдашнее издание было слишком теоретичное. Современное получше вроде. 
Я-то предполагал, что The Dragon Book - настольная книга каждого компиляторщика по умолчанию, так что её рекомендовать не стал. Но я её давно читал и не помню, есть ли там что-то именно про генерацию кода из SSA. 

  
В результате я изучал кодогенерацию по исходникам компилятора PCC и статье Стива Джонсона:


С тех пор мне встречалось много литературы по компиляторам. Но вот так чтобы прочитать умную книжку, всё понять, сесть и написать кодогенератор - таких книг нету, увы. Есть Си-компиляторы, исходники которых могут служить неплохим пособием. К примеру: https://github.com/alexfru/SmallerC

--Сергей

--
Данное сообщение отправлено Вам, как участнику группы "БЭСМ-6":
http://groups.google.com/group/besm6/topics
---
Вы получили это сообщение, поскольку подписаны на группу "БЭСМ-6".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес besm6+un...@googlegroups.com.
Чтобы посмотреть обсуждение, перейдите по ссылке https://groups.google.com/d/msgid/besm6/bc6e7892-22d0-4fbe-9eac-a022e6f34aa0n%40googlegroups.com.


--
Thanks,
-- Michael

Serge Vakulenko

unread,
Mar 3, 2025, 3:51:07 AMMar 3
to БЭСМ-6
On Sunday, March 2, 2025 at 11:38:34 PM UTC-8 BOPOHOK wrote:
Я-то предполагал, что The Dragon Book - настольная книга каждого компиляторщика по умолчанию, так что её рекомендовать не стал. Но я её давно читал и не помню, есть ли там что-то именно про генерацию кода из SSA. 

Первое издание Ахо-Ульмана вышло в 1977-м (русский перевод в 1985-м).
SSA придумали позже, во второй половине 80-х.

 --Сергей

Serge Vakulenko

unread,
Mar 3, 2025, 4:06:47 AMMar 3
to БЭСМ-6
Я спросил у grok.com про литературу по SSA трансляции.

Here’s a curated list of resources and literature on translating SSA (Static Single Assignment) form to CPU instruction sets, parameterized compilers, and related topics. These range from foundational papers to practical guides used in modern compiler design.

Foundational Papers on SSA
  1. "Efficiently Computing Static Single Assignment Form and the Control Dependence Graph" by Ron Cytron et al. (1991)
    • Where it all started. This seminal paper introduces SSA, its construction, and its benefits for optimization. It’s a must-read for understanding the theory.
    • Published in: ACM Transactions on Programming Languages and Systems (TOPLAS)
    • Find it: Check academic databases like ACM Digital Library or Google Scholar.
  2. "Engineering a Compiler" by Keith D. Cooper and Linda Torczon (2nd Edition, 2011)
    • Chapter 9 dives into SSA, its use in optimization, and how it’s lowered to machine code. It’s a practical-accurate, readable textbook that bridges theory and practice.
    • Available: Widely available in libraries or online bookstores.
SSA in Practice (Optimization and Translation)
  1. "The SSA Book: Static Single Assignment Form and Its Applications" by Rastislav Bodík and Sadun K. Anik (Draft, ~2000s)
    • A detailed exploration of SSA’s role in compilers, including lowering to machine-specific representations. It’s a bit dated but still valuable.
    • Find it: Sometimes available via university websites or research archives.
  2. "A Survey of Compiler Backend Techniques" by Norman Ramsey (1990s)
    • Covers instruction selection, register allocation, and code generation—key steps in translating SSA to machine code. Not SSA-specific but highly relevant.
    • Find it: ResearchGate or academic repositories.
Parameterized Compilers and Backends
  1. "LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation" by Chris Lattner and Vikram Adve (2004)
    • The original LLVM paper. Explains how LLVM’s SSA-based IR and modular backends enable targeting multiple architectures.
    • Find it: LLVM’s official site or conference proceedings (CodeGen ‘04).
  2. "Retargetable Compilers: A Practical Approach" by Cristina Cifuentes and Norman Ramsey (1998)
    • Discusses techniques for making compilers portable across instruction sets, with insights applicable to SSA translation.
    • Find it: IEEE or ACM archives.
Modern Compiler Documentation
  1. LLVM Documentation: Writing an LLVM Backend
  2. GCC Internals Manual
    • Details GCC’s machine descriptions and how they translate IR (including SSA-influenced forms) to target architectures.
    • Available: gcc.gnu.org/onlinedocs/gccint/
Bonus: Online Resources
  • "The Dragon Book" (Compilers: Principles, Techniques, and Tools) by Aho, Sethi, Ullman, and Lam
    • The classic compiler text. Chapter 6 (Intermediate-Code Generation) and Chapter 9 (Machine-Independent Optimizations) touch on SSA and code generation.
    • Widely available in print or PDF.
  • Stanford CS343: Advanced Topics in Compilers (Lecture Notes)
    • Free online notes from Stanford covering SSA, optimization, and backend design. Search for “CS343 SSA” online.
  • Blog Posts and Talks: Look for Chris Lattner’s talks on LLVM or posts on sites like Eli Bendersky’s blog (eli.thegreenplace.net) for practical SSA-to-machine-code insights.
Getting Access
  • Academic Databases: Use JSTOR, ACM, or IEEE Xplore if you have access (e.g., via a university).
  • Google Scholar: Search the titles—many have free PDFs floating around.
  • Library: “Engineering a Compiler” and “The Dragon Book” are staples in tech libraries.

These should give you a solid mix of theory, practice, and modern implementation details.

Alex Loktionoff

unread,
Mar 3, 2025, 2:01:27 PMMar 3
to БЭСМ-6
Сергей, тут возникло непонимание, вот я употребил в своем посте ключевое слово SSA...
Тут эффект гугла возникает, книг и статей по SSA туча, и Гугл конечно их выдает целый мешок, но в SSA нет ничего интересного для меня сейчас.
Мне же важна хорошая статья и книжка по _оптимальной_ генерации машинного кода.
Вот представим что у back- end уже есть идеальное представление программы чистый сок SSA /*опять употребил это кликбейтное слово, но представьте что нет этих трех букв*/, ничего лишнего. Как из него сгенерировать идеальный машинный код?
Вот, как я и предполагал, что западных теорий практически нет, мои сети вытащили несколько статей про числа Ершова.
Я конечно в компиляторах ничего не знаю, но взглянув на них у меня сложилось впечатление /*прошу по голове не бить, но все же  направить на путь истинный комментариями */, что он гарантирует генерацию оптимального машинного кода при условиях:
- имеем базовый блок без переходов
- все машинные команды исполняются за одинаковое время

Теория хороша - гарантирует оптимум. Но вот применить ее к программе для БЭСМ6 уже невозможно, все команды исполняются за разное время, при этом блокируя или не блокируя исполнение других команд, про то, что у нас до перехода в среднем 5-20 инструкций я уже молчу. Во всех книжках, что я смотрел 90% места уделяется AST и SSA /*опять употребил это сбивающее с толку слово*/ как бы выжмем самый сок из программы и это залог, а back-end уж сам с генерирует оптимальные инструкции.
Ну или чуть больше, так как наш SSA 'оптимален' то регистр аллигатор по нему пробежиться вычислит сколько и куда каких регистров потом на каждую операцию SSA backend подставит пару соответствующих команд, а sheduler только перетасует маленько команды, чтоб overlaping был побольше, ведь типа никуда не деться оригинальное представление и так "идеально" то каждая команда нужна и смысл ее менять нету.

Мне же интересен только вопрос генерации гарантированного оптимального машинного кода, конкретно для БЕСМ6/СВС-1.
По хорошему scheduling мог бы переставлять команды изменяя время жизни переменных, соответсвенно меняя аллокацию регистров, а некоторые команды при этом могли бы быть изменены или вообще выкинуты.
Можно пойти по пути эвристик - в backend заготовить куски ассемблерных команд для паттернов. В ревью на GitHub каждый мог бы добавить свои, но и по дизассеблеру смотреть во время эксплуатации где генератор мышей не ловит, добавлять ему "мудрости" для каждого конкретного паттерна. Вроде это тоже перспективный путь - в СССР например в шахматных программах использовались хитрые эвристики, благодаря которым держался паритет с более мощными ЭВМ но с более общими алгоритмами.
Но тоже возникает вопрос а как померять и убедится или хотяб прикинуть на сколько это будет отставать от оптимума?

Если вот такие конкретные статьи есть, буду премного благодарен, чтоб не продираться сквозь воду разных трехбуквенных технологий middle-end. 

понедельник, 3 марта 2025 г. в 10:06:47 UTC+1, serge.v...@gmail.com:

Leo B.

unread,
Mar 7, 2025, 11:12:47 AMMar 7
to БЭСМ-6
Существует реализация кодогенератора GCC для 36-битной словной машины PDP-10: http://pdp10.nocrew.org/gcc/download/gcc-pdp10-20030606.tar.bz2

Возможно, удастся почерпнуть оттуда идеи для попытки реализации на GCC.

Leo


Alex Loktionoff

unread,
Mar 15, 2025, 10:38:21 AMMar 15
to БЭСМ-6
Что-то глянул, и оказалось не по зубам. GCC компилятор это целый стог сена, кодогенерация через GIMPEL это просто мрак. С кода для PDP-10 я с налета не нашел, вот это бы могло помочь найти какие-то идеи.
Моя идея проста - typedef __attribute__(packed, aligned(8)) long char; sizeof(char) == 1; CHAR_BIT == 48;
Для этого нужен и фронт--енд и бэк-енд. Фронт-енд надо будет взято простецкий а-ля из tcc, чтоб соответствовал С99 стандарту сам был написан на стандартном С, еще по-проще  без выкрутасов /*может даже не использовать switch/case */ чтоб гарантировано сам собой компилировался  и использовал LLVM . Я пишу оптимизирующий бек-енд, что то меня несет в сторону MISRA, без рекурсии, без VLA. Но я нашел доки по алгоритмам Ершова, для начала это достаточно, а потом эвристические преобразования графа можно добавлять, ну и под конец уже накрутить уже совсем тяжелую артиллерию в виде гиперграфа с выбором оптимального маршрута с помощью модели симуляции процессора, ну это уже после того как модельку процессора напишу. План более-менее ясен на ближайшие лет 10 :)
Только все должно быть написано на самом простом С.
Пишу конечно в новом стиле "все в памяти", и для БЭСМ6 это наверно не влезет. Но если использовать несколько страниц и разбить на проходы, то может и будет возможно, но это уже дело 10-е. Я ориентируюсь на Э1КБ, но команды конечно буду использовать только БЭСМ6.

пятница, 7 марта 2025 г. в 17:12:47 UTC+1, Leo B.:

Alex Loktionoff

unread,
Mar 15, 2025, 11:11:05 AMMar 15
to БЭСМ-6
Просмотрел список, и было очень грустно, пока не нашел оригинальную статью ECM Ершова от 58г.

Для меня эти книжки выглядят как тупик:
- LLVM IR неплох, но писать бекенд для БЭСМ6 это куча потраченного времени на сражение с TableGen-ом, и в конце получить C++ монстр, для кросс-компиляции ок, но для self-hosting очень слабые перспективы. Я вообще С++, я его изучал когда еще небыли ни одного компилятора С++, а писал на нем когда еще небыли ни одного стандарта, в конторе впервые использовал С++ для встроенных систем, да и сейчас использую свежий стандарт, не смотря что поддерживаю linux драйвера на чистом С, хотя можно было бы и Rust прикручивать. Но вот такой момент, написать С++ компилятор, чтоб он поддерживал все новые и старые фичи это уже не по-зубам никакому индивидууму на земле, да еще и в каждой строчке С++ кода я вижу UB на UB и UB погоняет. Мне кажется, что вот любой ярый сторонник С++ приутихнет, при условии что будет писать код на том компиляторе, что сам написал...
- GCC - монолитный мрак, с его генерацией через GIMPEL, это по сути генерация ассемблера через промежуточный LISP. 

Сам же подход который подается в классических и по сути устаревших книжках из SSA, для меня выглядит как - сгенерируем SSA потом простым сканированием определим регистры и быстренько перемелим SSA в DAG для кодогенерации. Ну конечно память у нас резиновая а гигагерцев не мерно, а DAG создается так пару команд в ассемблере и DAG у нас в L1 Кеше, /* I wana run my Cray XMP - gigaherz for nothing, gigabit for free ! */извиняюсь за сарказм. Да и ненаучно это как-то. 

У Ершова все просто и логично, и дает сразу неплохой результат. А потом можно добавлять преобразования графа и прочие оптимизации. 

понедельник, 3 марта 2025 г. в 10:06:47 UTC+1, serge.v...@gmail.com:
Я спросил у grok.com про литературу по SSA трансляции.

Leo B.

unread,
Mar 15, 2025, 12:02:16 PMMar 15
to БЭСМ-6
GCC для PDP-10 здесь: http://pdp10.nocrew.org/gcc/download/

CHAR_BIT == 48 сделать несложно, но это будет игрушечная реализация (32К получившихся "байтов" - не для реальной работы). 

При таком подходе сляпать самый простой самокомпилирующийся компилятор можно и из https://github.com/rswier/c4/
Вместо байткода будет шитый код, а некоторые операции даже нативно в две команды поместятся.

Leo

Евгений Халуев

unread,
Mar 15, 2025, 12:03:15 PMMar 15
to БЭСМ-6
С учетом выше изложенного, кажется, что изготовление Сишного фронтенда к уже имеющемуся компилятору паскаля (переиспользовав его кодогенератор) позволит получить рабочий компилятор Си за конечное время. Конечно, получаемый машинный код будет не очень оптимален, зато шанс получить self-hosted компилятор языка си будет ненулевой с учетом всех ограничений по памяти БЭСМ-6. Выбрасывание switch/case особо не сэкономит памяти. 

суббота, 15 марта 2025 г. в 22:11:05 UTC+7, oxy...@gmail.com:

Alex Loktionoff

unread,
Mar 17, 2025, 1:39:08 PMMar 17
to БЭСМ-6
суббота, 15 марта 2025 г. в 17:02:16 UTC+1, Leo B.: 
GCC для PDP-10 здесь: http://pdp10.nocrew.org/gcc/download/

Я не нашел текстов С программ, которые бы компилировались этим GCC для PDP10. На сколько они портабельно выглядят. Вот тексты порисованных под PDP10 программ на С  дали бы какие-то идеи. 

CHAR_BIT == 48 сделать несложно, но это будет игрушечная реализация (32К получившихся "байтов" - не для реальной работы). 

Но не CHAR_BIT == 48 единым... __attribute__(packedaligned(8)) char, компилятор бы упаковывал бы до 6-и ASCII символов в слово, детали можно скрыть в puts() и printf() - реализовать можно как в ФОРТРАНе и ПАСКАЛе. Но для этого нужен свой фронтенд написать, править clang для меня не вариант и по времени и хотяб потому что это С++.
 
При таком подходе сляпать самый простой самокомпилирующийся компилятор можно и из https://github.com/rswier/c4/
Вместо байткода будет шитый код, а некоторые операции даже нативно в две команды поместятся
Вот интересная ссылочка! это прям черновик для фронтенда, который можно перевести на LLVM бекенд чуть не за выходные.
Только вас не смущает лицензия GPL 2.0? и dispak и dubna  выпущены под MIT лицензией?
Если я возьму С4 за основу, никаких частей из них я не буду иметь права брать :(
Можете перерелизить dispak под войной GPL2.0 или MIT? 

Leo B.

unread,
Mar 17, 2025, 9:36:35 PMMar 17
to БЭСМ-6
On Monday, March 17, 2025 at 10:39:08 AM UTC-7 oxy...@gmail.com wrote:
суббота, 15 марта 2025 г. в 17:02:16 UTC+1, Leo B.: 
GCC для PDP-10 здесь: http://pdp10.nocrew.org/gcc/download/

Я не нашел текстов С программ, которые бы компилировались этим GCC для PDP10. На сколько они портабельно выглядят. Вот тексты порисованных под PDP10 программ на С  дали бы какие-то идеи. 

Чего не знаю, того не знаю. Я сам даже в тот порт GCC  не смотрел.
 

CHAR_BIT == 48 сделать несложно, но это будет игрушечная реализация (32К получившихся "байтов" - не для реальной работы). 

Но не CHAR_BIT == 48 единым... __attribute__(packedaligned(8)) char, компилятор бы упаковывал бы до 6-и ASCII символов в слово, детали можно скрыть в puts() и printf() - реализовать можно как в ФОРТРАНе и ПАСКАЛе. Но для этого нужен свой фронтенд написать, править clang для меня не вариант и по времени и хотяб потому что это С++.

Ну так Паскаль уже ровно так и делает, если  объявить packed array of char, тем и ценен. По умолчанию unpacked array of char держат по одному символу в слове для скорости.

 
При таком подходе сляпать самый простой самокомпилирующийся компилятор можно и из https://github.com/rswier/c4/
Вместо байткода будет шитый код, а некоторые операции даже нативно в две команды поместятся
Вот интересная ссылочка! это прям черновик для фронтенда, который можно перевести на LLVM бекенд чуть не за выходные.
Только вас не смущает лицензия GPL 2.0? и dispak и dubna  выпущены под MIT лицензией? 
Если я возьму С4 за основу, никаких частей из них я не буду иметь права брать :(

Как раз имеете (впрочем, не то чтобы в компиляторе была нужда в коде из dispak или dubna). 

MIT - более свободная лицензия, чем GPL.  Это наоборот, если что-то GPL взять и использовать в изначально MIT-лицензированном софте,
это его заражает GPL-лицензией. 

 Leo

Василий Долматов

unread,
Mar 17, 2025, 10:55:29 PMMar 17
to 'Кирилл Кобелев' via БЭСМ-6


.
Только вас не смущает лицензия GPL 2.0? и dispak и dubna  выпущены под MIT лицензией? 
Если я возьму С4 за основу, никаких частей из них я не буду иметь права брать :(

Как раз имеете (впрочем, не то чтобы в компиляторе была нужда в коде из dispak или dubna). 

MIT - более свободная лицензия, чем GPL.  Это наоборот, если что-то GPL взять и использовать в изначально MIT-лицензированном софте,
это его заражает GPL-лицензией. 

причем заражает его неизлечимо… 

GPL - это хуже СПИДа… :(

 Leo

Serge Vakulenko

unread,
Mar 19, 2025, 4:33:46 PMMar 19
to be...@googlegroups.com
On Mon, Mar 17, 2025 at 10:39 AM Alex Loktionoff <oxy...@gmail.com> wrote:
суббота, 15 марта 2025 г. в 17:02:16 UTC+1, Leo B.: 
GCC для PDP-10 здесь: http://pdp10.nocrew.org/gcc/download/
Я не нашел текстов С программ, которые бы компилировались этим GCC для PDP10. На сколько они портабельно выглядят. Вот тексты порисованных под PDP10 программ на С  дали бы какие-то идеи.

Удалось ли собрать gcc для pdp-10? Мне удалось по вот этой инструкции.

Вот пример программы на Си:

При компиляции образуется boot.s - файл прилагается.

--Сергей
boot.s

Alex Loktionoff

unread,
Mar 21, 2025, 4:59:40 PMMar 21
to БЭСМ-6


CHAR_BIT == 48 сделать несложно, но это будет игрушечная реализация (32К получившихся "байтов" - не для реальной работы). 

Но не CHAR_BIT == 48 единым... __attribute__(packedaligned(8)) char, компилятор бы упаковывал бы до 6-и ASCII символов в слово, детали можно скрыть в puts() и printf() - реализовать можно как в ФОРТРАНе и ПАСКАЛе. Но для этого нужен свой фронтенд написать, править clang для меня не вариант и по времени и хотяб потому что это С++.

Ну так Паскаль уже ровно так и делает, если  объявить packed array of char, тем и ценен. По умолчанию unpacked array of char держат по одному символу в слове для скорости.
Вот это пеня и подкупает, общем есть в С стандартные возможности, которые можно применить "нестандартно". Но для этого надо и свой фронт-енд иметь. Просто подправить какойнибудь tcc или даже c4. 
Только вот как быть с лицензиями. 
 
 
При таком подходе сляпать самый простой самокомпилирующийся компилятор можно и из https://github.com/rswier/c4/
Вместо байткода будет шитый код, а некоторые операции даже нативно в две команды поместятся
Вот интересная ссылочка! это прям черновик для фронтенда, который можно перевести на LLVM бекенд чуть не за выходные.
Только вас не смущает лицензия GPL 2.0? и dispak и dubna  выпущены под MIT лицензией? 
Если я возьму С4 за основу, никаких частей из них я не буду иметь права брать :(

Как раз имеете (впрочем, не то чтобы в компиляторе была нужда в коде из dispak или dubna). 

MIT - более свободная лицензия, чем GPL.  Это наоборот, если что-то GPL взять и использовать в изначально MIT-лицензированном софте,
это его заражает GPL-лицензией. 
Тоесть Вы не возражаете, если кто-то, или я, возмет надергает структур из dispack для бекенда, и распространит это как GPL???
Ну конечно, заголовки с авторством сохраняются и ка-бы требования MIT удовлетворены.
Но дальше все будут _обязаны_ публиковать исходники если что-то там поменяли, и тут адвокаты MIT не захотят ли на этом заработать? У меня в голове не укладывается, если "так можно было" то почему Линукс не возмет пол ядра от BSD и багов будет в 2 раза меньше :) 
 
 Leo

Alex Loktionoff

unread,
Mar 21, 2025, 5:08:51 PMMar 21
to БЭСМ-6
Спасибо большое, надо почитать. Интересно это они без __attribute__(packed, aligned 4.5) объявляют указатели и массивы char.
Я надеюсь, что обращений по индексу в коде можно избегать. А если сильно надо, но можно и aligned массивчик делать небольшой как исключение. Ведь char уже давно не 8бит, в современных языках по сути нет произвольного доступа к символу, в основном делают итераторы.

static void puts (char *s)
{
  int c;

  if ((c = *s) == 0)
    return;

  do
    putchar (c);
  while ((c = *++s) != 0);
}


среда, 19 марта 2025 г. в 21:33:46 UTC+1, serge.v...@gmail.com:

Alex Loktionoff

unread,
Mar 21, 2025, 5:10:22 PMMar 21
to БЭСМ-6
Ну и получается два вопроса, реально можно ли быстро состряпать GPL "солянку" и а это нам надо?

вторник, 18 марта 2025 г. в 03:55:29 UTC+1, ReedCat:

Alex Loktionoff

unread,
Mar 21, 2025, 5:13:10 PMMar 21
to БЭСМ-6
CHAR_BIT == 48 сделать несложно, но это будет игрушечная реализация (32К получившихся "байтов" - не для реальной работы). 

Но не CHAR_BIT == 48 единым... __attribute__(packedaligned(8)) char, компилятор бы упаковывал бы до 6-и ASCII символов в слово, детали можно скрыть в puts() и printf() - реализовать можно как в ФОРТРАНе и ПАСКАЛе. Но для этого нужен свой фронтенд написать, править clang для меня не вариант и по времени и хотяб потому что это С++.

Ну так Паскаль уже ровно так и делает, если  объявить packed array of char, тем и ценен. По умолчанию unpacked array of char держат по одному символу в слове для скорости.
Вполне рабочее решение было, и заодно будет совместимость С с Паскалем.
Да и фортрану больше ничего не надо, у него небыло возможности строки парсить. Только выровненные указатели на упакованные char. 

 Leo

Alex Loktionoff

unread,
Mar 21, 2025, 5:39:26 PMMar 21
to БЭСМ-6
У меня есть небольшой прогресс, хотя при правках AST каждый раз разваливается, но мало-мальски заработал Constant-propagaton.
И вот возник вопрос как писать циклы. Я почти всегда писал так:
for (int i = ARRAY_SIZE(ary); i--;)
        ary[i] = i;

но для БЭСМ6 это негодиться:
 1 - VLM команда с автоинкрементом
 2 - I-- это "неправильная" команда для цикла, вводящая в заблуждение компилятор, поясню:
в цикле будет проверяться равно ли I нулю и сразу делать переход. Но i-- еще обязывает компилятор делать декремент, даже после того, как цикл закончится. Конечно если i потом нигде не используется, то последнее i-- компилятор может выкинуть /ну или оставить в зависимости от архитектуры*/ Но это весьма нетривиальные приседания для компилятора, в смысле самописного!

Вопрос, как "понятней" всего писать для БЭСМ6?
Мне нравятся do {} while(), для них можно обойтись всего одним базовым блоком для тела, еще один до и один после - минимум.
можно написать так
ptr = &ary[ARRAY_SIZE(ary) - 1];
I = ARRAY_SIZE(ary);
do {
        ptr[i] = i;
} while(i++);

Но VLM хитрый, если  0 он не только не прыгает в начало, но и не инкрементирует регистр, оставляя его в 0.
Получается надо или определять какой-то нестандартный builtin с насыщением в 0 или учить компилятор добавлять в блок после цикла  --i и его удалять если i не используется.
Пока писал, cкланяюсь, что фейковый i-- для удаления при кодогенерации лучшее решение.  

воскресенье, 2 марта 2025 г. в 13:57:42 UTC+1, Alex Loktionoff:

Leo B.

unread,
Mar 21, 2025, 6:18:38 PMMar 21
to БЭСМ-6
On Friday, March 21, 2025 at 1:59:40 PM UTC-7 oxy...@gmail.com wrote:

Ну так Паскаль уже ровно так и делает, если  объявить packed array of char, тем и ценен. По умолчанию unpacked array of char держат по одному символу в слове для скорости.
Вот это пеня и подкупает, общем есть в С стандартные возможности, которые можно применить "нестандартно". Но для этого надо и свой фронт-енд иметь. Просто подправить какойнибудь tcc или даже c4. 
Только вот как быть с лицензиями. 
 

Насчет лицензий, как говорится, мы перейдем через этот мост, когда подойдём к нему. После того, как будет написан работающий Си-компилятор для БЭСМ-6 Скорее всего, никакого буквального кода из этих проектов не останется.


MIT - более свободная лицензия, чем GPL.  Это наоборот, если что-то GPL взять и использовать в изначально MIT-лицензированном софте,
это его заражает GPL-лицензией. 
Тоесть Вы не возражаете, если кто-то, или я, возмет надергает структур из dispack для бекенда, и распространит это как GPL???

Конечно, нет. 
 
Ну конечно, заголовки с авторством сохраняются и ка-бы требования MIT удовлетворены.
Но дальше все будут _обязаны_ публиковать исходники если что-то там поменяли, и тут адвокаты MIT не захотят ли на этом заработать?

Я не вижу проблемы. Проект же просто будет публиковаться в исходных текстах. 

У меня в голове не укладывается, если "так можно было" то почему Линукс не возмет пол ядра от BSD и багов будет в 2 раза меньше :) 
 
Потому что одим из трех достоинств программиста, кроме лени (laziness) и нетерпения (impatience), является спесь (hubris).

Leo

Leo B.

unread,
Mar 21, 2025, 7:21:28 PMMar 21
to БЭСМ-6
On Friday, March 21, 2025 at 2:39:26 PM UTC-7 oxy...@gmail.com wrote:
У меня есть небольшой прогресс, хотя при правках AST каждый раз разваливается, но мало-мальски заработал Constant-propagaton.
И вот возник вопрос как писать циклы. Я почти всегда писал так:
for (int i = ARRAY_SIZE(ary); i--;)
        ary[i] = i;

На первых порах пишите как угодно. Кстати говоря, Паскаль-компилятор не порождает команду VLM в принципе.
По сравнению с парой UTM/VZM или UTM/V1M основная польза от VLM не от экономии нескольких тактов УУ (которые при вычислениях с плавающей точкой все равно маскируются занятостью АУ), а от экономии одной команды, что для коротких математических циклов было существенно, чтобы  максимальная длина цикла, помещающегося в Буферный Регистр Слов (I-cache) была на одну полезную арифметическую команду больше. Это было важно, чтобы максимизировать пропускную способность памяти для обращений к данным. 

При реализации на современной элементной базе эта разница между способами организации циклов становится непринципиальна.


Вопрос, как "понятней" всего писать для БЭСМ6?

Главное - в направлении увеличения переменной-индекса цикла. Остальное - мелкие детали.

Кстати говоря, хвалёный Форекс хоть и использовал команду VLM для итерации (а число итераций, если цикл был с шагом, не равным 1, всегда вычислял делением на шаг;  команда ДEЛ =-.100000E 01 выглядит как недоработка) всё равно держал отдельные индекс-регистры для обращения к массивам, даже если все массивы, использованные в цикле, были векторами, а индексное выражение было без масштабирования. Т. е. реальная польза от команды VLM , предусмотренная разработчиками, была только при программировании на ассемблере. 

При реализации компилятора для БЭСМ-6 в первую очередь надо заботиться об оптимизации переключения режимов АУ. Кстати о Форексе,
цикл 
      INTEGER A(100)
      DO 10 I = 1,100
   10 A(I) = A(I) + 1 

компилируется как
 00001   /0001/   CЧ    =     1
                  ЗП    I
 00002            YИA   ′77635′(′14′)
                  MOД   I
 00003            YИA   (′13′)
                  YИИ   ′00012′(′13′)
 00004            CЛИA  A     (′12′)
                  PЖA   ′00002′
 00005   /0004/   HOП
 00005   10   :   PЖA   ′00003′
                  CЧ    ′77777′(′12′)
 00006            CЛ    =     1
                  ЗП    ′77777′(′12′)
 00007            CЛИA  ′00001′(′12′)
                  PЖA   ′00022′
 00010            ЦИKЛ  /0004/(′14′)


Переключать режимы нормализации в цикле совершенно избыточно. 

Leo

Alex Loktionoff

unread,
Apr 4, 2025, 3:31:32 PMApr 4
to БЭСМ-6
В теме "БЭСМ6 программирование на Паскале" всплыли интересные нюансы в генерации объектных файлов.
Что все глобальные переменные программы на паскале попадают в COMMON блок P/1D. COMMON блок это не просто сегмент куда линковщик/загрузчик добавляет данные из всех линкуемых модулей. Это секция в памяти как-бы проецируемая во все модули, которые на нее ссылаются и соответсвенно разделяют все данные от начала и до конца. Главное отличие, что все данные/сруктуры объявленный в COMMON блок должны совпадать, иначе будет каша при изменениях.
Мне кажется это вытекает из того, что в формате объектного файла БЭСМ6 можно экспортировать всего 19 сущностей, было-бы больше - можно было бы каждую переменную экспортировать под отдельным именем и загрузчик все ссылки правильно настроил.
Еще есть особенность Паскаля - вложенные функции, что существенно облегчает ситуацию, конечно возможны и другие варианты, но с моей точки зрения именно вложенные функции позволяют проблему с наложением/согласованием глобальных данных в COMMON блоке P/1D решать кардинально - вообще не объявлять глобальных переменных в PROGRAMM, а объявлять их только во вложенных функциях.

Свой компилятор С мне хотелось бы реализовать как компилятор для системы, и считаю, что вложенные функции так должноы поддерживаться как расширение GCC, они позволяют писать более компактный код и быстрее вызывать вложенные функции не "пропихивая" через стек все нужные переменные. Но это отхождение от стандарта, и хотелось бы дать пользователям по умолчанию компилировать код обычных POSIX утилит с глобальными переменными и избегать проблем с конфликтом в P/1D.

Я сторонник стандартов, есть желание сделать код сгенерированный С 100% совместимый с Паскалем и Фортраном.
Не прочь использовать даже библиотечные функции Паскаля, если предполагается 100% совместимость, то код будет часто работать совместно, есть смысл использовать те-же функции и константы в P/1D - экономия памяти. Кстати как Вы считаете их эффективность? Я полагаю очень хороший, а если что то можно и оптимизировать где-это, от этого выиграют оба языка.    

Но нехотелось бы ограничивать пользователей С в плане глобальных переменных.

Есть готовое решение проблемы глобальных переменных в С, поделитесь?

воскресенье, 2 марта 2025 г. в 13:57:42 UTC+1, Alex Loktionoff:
Решил открыть отдельную тему по кодогенерации для нового оптимизирующего компилятора. Тема по формату вызовов https://groups.google.com/g/besm6/c/LJ91waEdhzE/m/USweH2PIAgAJ так и остается, там будем обсуждать только соглашения о вызовах какие были и какие будут, чтоб не захламлять.

Leo B.

unread,
Apr 4, 2025, 4:17:19 PMApr 4
to БЭСМ-6
On Friday, April 4, 2025 at 12:31:32 PM UTC-7 oxy...@gmail.com wrote:
В теме "БЭСМ6 программирование на Паскале" всплыли интересные нюансы в генерации объектных файлов.
Что все глобальные переменные программы на паскале попадают в COMMON блок P/1D. COMMON блок это не просто сегмент куда линковщик/загрузчик добавляет данные из всех линкуемых модулей. Это секция в памяти как-бы проецируемая во все модули, которые на нее ссылаются и соответсвенно разделяют все данные от начала и до конца. Главное отличие, что все данные/сруктуры объявленный в COMMON блок должны совпадать, иначе будет каша при изменениях.
Мне кажется это вытекает из того, что в формате объектного файла БЭСМ6 можно экспортировать всего 19 сущностей, было-бы больше - можно было бы каждую переменную экспортировать под отдельным именем и загрузчик все ссылки правильно настроил.

Нет, экспортируемыми считаются только входы в процедуры. Коммон-блоки, как и вызываемые внешние процедуры - "импортируемые", их могло быть много. Проблема в том, что адрес каждого отдельного коммон-блока мог быть произвольным, поэтому
в отсутствие оптимизаций или глобального базирования все обращения к нему должны были делаться через UTC. А адрес P/1D  как ставился на регистр 1 в начале программы, так на него всегда можно было рассчитывать.
 
Еще есть особенность Паскаля - вложенные функции, что существенно облегчает ситуацию, конечно возможны и другие варианты, но с моей точки зрения именно вложенные функции позволяют проблему с наложением/согласованием глобальных данных в COMMON блоке P/1D решать кардинально - вообще не объявлять глобальных переменных в PROGRAMM, а объявлять их только во вложенных функциях.

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

Свой компилятор С мне хотелось бы реализовать как компилятор для системы, и считаю, что вложенные функции так должноы поддерживаться как расширение GCC, они позволяют писать более компактный код и быстрее вызывать вложенные функции не "пропихивая" через стек все нужные переменные. Но это отхождение от стандарта, и хотелось бы дать пользователям по умолчанию компилировать код обычных POSIX утилит с глобальными переменными и избегать проблем с конфликтом в P/1D.

Каждую глобальную переменную, скомпилированную с "external linkage" придется иметь в отдельном блоке. Все static переменные, объявленные в файле, можно держать в одном блоке, адрес которого в начале всех процедур файла можно ставить на регистр.
В компиляторе, который я медленно и постепенно делаю из Паскаля, я склоняюсь к отказу от вложенных функций ради упрощения компилятора. Если реализовать регистровые указатели в качестве формальных параметров процедур, это будет практически эквивалентно по эффективности, но более общо.


Я сторонник стандартов, есть желание сделать код сгенерированный С 100% совместимый с Паскалем и Фортраном.
Не прочь использовать даже библиотечные функции Паскаля, если предполагается 100% совместимость, то код будет часто работать совместно, есть смысл использовать те-же функции и константы в P/1D - экономия памяти. Кстати как Вы считаете их эффективность? Я полагаю очень хороший, а если что то можно и оптимизировать где-это, от этого выиграют оба языка.    

Безусловно, если желаемая функциональность уже есть, почему бы не использовать. Насчет качества исполнения, правда, есть сомнения, судя по тому же  P/WI, который был написан некомпетентно. 

Но нехотелось бы ограничивать пользователей С в плане глобальных переменных.

Есть готовое решение проблемы глобальных переменных в С, поделитесь?

Более или менее готовое решение, которое позволит иметь каждую глобальную переменную в отдельном коммон-блоке без затрат на  UTC - глобальное базирование. Даже если делать вложенные процедуры, то достаточно будет ограничить глубину вложенности не 6, как сейчас в Паскале, а 3 или 4, и регистров должно хватить. 

Leo

Alex Loktionoff

unread,
Apr 5, 2025, 3:38:06 AMApr 5
to БЭСМ-6


пятница, 4 апреля 2025 г. в 22:17:19 UTC+2, Leo B.:
On Friday, April 4, 2025 at 12:31:32 PM UTC-7 oxy...@gmail.com wrote:
В теме "БЭСМ6 программирование на Паскале" всплыли интересные нюансы в генерации объектных файлов.
Что все глобальные переменные программы на паскале попадают в COMMON блок P/1D. COMMON блок это не просто сегмент куда линковщик/загрузчик добавляет данные из всех линкуемых модулей. Это секция в памяти как-бы проецируемая во все модули, которые на нее ссылаются и соответсвенно разделяют все данные от начала и до конца. Главное отличие, что все данные/сруктуры объявленный в COMMON блок должны совпадать, иначе будет каша при изменениях.
Мне кажется это вытекает из того, что в формате объектного файла БЭСМ6 можно экспортировать всего 19 сущностей, было-бы больше - можно было бы каждую переменную экспортировать под отдельным именем и загрузчик все ссылки правильно настроил.

Нет, экспортируемыми считаются только входы в процедуры. Коммон-блоки, как и вызываемые внешние процедуры - "импортируемые", их могло быть много. Проблема в том, что адрес каждого отдельного коммон-блока мог быть произвольным, поэтому
в отсутствие оптимизаций или глобального базирования все обращения к нему должны были делаться через UTC. А адрес P/1D  как ставился на регистр 1 в начале программы, так на него всегда можно было рассчитывать.
Похоже мне 1-вый регистр тоже зарезервировать, там хорошие константы есть, и спокойно все библиотеки паскаля доступны. Наверно надо в тему по соглашению вызовов написать...
 
Еще есть особенность Паскаля - вложенные функции, что существенно облегчает ситуацию, конечно возможны и другие варианты, но с моей точки зрения именно вложенные функции позволяют проблему с наложением/согласованием глобальных данных в COMMON блоке P/1D решать кардинально - вообще не объявлять глобальных переменных в PROGRAMM, а объявлять их только во вложенных функциях.

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

Свой компилятор С мне хотелось бы реализовать как компилятор для системы, и считаю, что вложенные функции так должноы поддерживаться как расширение GCC, они позволяют писать более компактный код и быстрее вызывать вложенные функции не "пропихивая" через стек все нужные переменные. Но это отхождение от стандарта, и хотелось бы дать пользователям по умолчанию компилировать код обычных POSIX утилит с глобальными переменными и избегать проблем с конфликтом в P/1D.

Каждую глобальную переменную, скомпилированную с "external linkage" придется иметь в отдельном блоке. Все static переменные, объявленные в файле, можно держать в одном блоке, адрес которого в начале всех процедур файла можно ставить на регистр.
В компиляторе, который я медленно и постепенно делаю из Паскаля, я склоняюсь к отказу от вложенных функций ради упрощения компилятора. Если реализовать регистровые указатели в качестве формальных параметров процедур, это будет практически эквивалентно по эффективности, но более общо.
Вот ночью пришла мысль, что если посмотреть с другой стороны, то-есть вывернуть на изнанку, то проблема не с конфликтом глобальных переменных в С, а наоборот в ограниченном количестве возможных экспортов. Но для этого БЕСМ6 С компиляторе можно принять флаг по умолчанию -fvisibility=hidden . А в программах для экспортируемых структур явно писать __attribute__((visibility("default")). Для портирования С библиотек со множеством экспортируемых функций можно применить подход Amiga, там на всю библиотеку достаточно экспортировать только базу. В целом портабелльно. 
 


Я сторонник стандартов, есть желание сделать код сгенерированный С 100% совместимый с Паскалем и Фортраном.
Не прочь использовать даже библиотечные функции Паскаля, если предполагается 100% совместимость, то код будет часто работать совместно, есть смысл использовать те-же функции и константы в P/1D - экономия памяти. Кстати как Вы считаете их эффективность? Я полагаю очень хороший, а если что то можно и оптимизировать где-это, от этого выиграют оба языка.    

Безусловно, если желаемая функциональность уже есть, почему бы не использовать. Насчет качества исполнения, правда, есть сомнения, судя по тому же  P/WI, который был написан некомпетентно. 
Скажите как эксперт, это лечиться? В смысле можно  P/WI переписать, или сама архитектура/интерфейс плохой?


Но нехотелось бы ограничивать пользователей С в плане глобальных переменных.

Есть готовое решение проблемы глобальных переменных в С, поделитесь?

Более или менее готовое решение, которое позволит иметь каждую глобальную переменную в отдельном коммон-блоке без затрат на  UTC - глобальное базирование. Даже если делать вложенные процедуры, то достаточно будет ограничить глубину вложенности не 6, как сейчас в Паскале, а 3 или 4, и регистров должно хватить. 

Полагаю вложенность 3 хватит всем  :) А для вызовов библиотек можно пере-использовать один зарезервированный регистр. Это тоже стоит занести в тему о соглашениях вызовов.
Перед вызовом библиотеки устанавливался 7-ой регистр на базу. DLL в Амиге - просто таблица указателей на функции, за ними можно данные хранить, так что одной базы хватало. Косвенные вызовы, да но зато никаких беганий и выискиваний символьных ссылок - загрузка молниеносна. 

Leo

Alex Loktionoff

unread,
Apr 12, 2025, 5:19:34 AMApr 12
to БЭСМ-6
Вызывает интерес и такой еще разрез: NULL/NIL.
Очень хотелось бы сохранить для С NULL == 0, но и не потерять совместимости с Паскалем.
Интересно зачем в Паскале приняли тако странный NIL? С С-шным NULL библиотечные P/xx функции работать не будут и придется писать свои?

(*=p-,t-,s8,y+*)

program exPointers(output);

var

   number: integer;

   iptr: @integer;

   y: @integer;


begin

   iptr := nil;

   y := ref(iptr);

   

   writeln('the vaule of iptr is ', iptr, y^);

end.


...


ТНЕ VАULЕ ОF IРТR IS  0000000000074000     30720

 КОНЕЦ ЗАДАЧИ

 00411: 00 074 0000 *74

Alex Loktionoff

unread,
Apr 12, 2025, 6:57:18 AMApr 12
to БЭСМ-6
Пишу я значит свой back-end, примем начал основательно с нижней части middle-end.
У меня уже мало-мальски формируется AST, если точнее это не AST, а более приземленное /* возможно циклическое*/ графовое представление с зависимостями и basic-block-ами - нечто среднее между LLVM IR и LLVM MIR. И вот как раз на подходе к back-end впал я в ступор.

Принимаю решение реализовывать кодогенерацию a-la GlobalISel а не SelectionDAG так как SelectionDAG уже показало что ни чем не лучше  GlobalISel по качеству генерируемого кода, а по скорости уступает раза в 2, еще  SelectionDAG подразумевает создание кучи дополнительных структур и форматов, что неэффективно а для БЭСМ6 вообще некрасиво до невозможности.
Еще GlobalISel можно реализовывать постепенно, что весьма немаловажно для любительской реализации, а с  SelectionDAG похоже, чтоб что-то заработало надо написать ~%80. - Ok

Но все-равно вопрос, нужно ли создавать еще MIR представление /*отдельные структуры и функции по работе с ними*/??? Очень не хотелось бы! Что бросается в глаза это разница в оформлении параметров функции ну и что в MIR MachineInstr G_ADD например явно указывается регистр результата, в IR Value сама инструкция это уже 'виртуальный' регистр. Первое - а почему-бы кодогенератор при lowering не взять и сгенерировать нужные команды LLVMGetParam().
MachineInstr и так занимает 40-100 байт, у меня me_ast_node занимает 16, хотелось бы запихнуть.

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

Тоже возник вопрос, сначала виделся план, что по IR построить гиперграф - т.е. избыточный граф со всевозможными реализациями IR инструкций, а потом исходя из модели CPU выбрать оптимальный путь. А сейчас конкретно реализация какая должна быть структуры для гиперграфа? Ведь если инструкция lowered то она должна быть удалена из графа, получается гиперграф должен строиться из других структур и все-равно нужно еще одно представление :-/  

В LLVM принято постепенное lowering MIR  инструкций, для максимальной оптимизации это необходимость? Или это артефакт педализации.

Alex Loktionoff

unread,
Apr 12, 2025, 6:16:50 PMApr 12
to БЭСМ-6
Пришла беда, откуда не ждали, ubsan ругается на for (unsigned int i = -count; i++; ) {

runtime error: negation of 1 cannot be represented in type 'unsigned int'


Это для меня выглядит странно, потому как если я говорю i = 0 - count; То я хочу получить такое i, чтоб i + count == 0.
Пока пришлось заменить все на int, но при это теряется половина диапазона цикла.
Что делать? По моему ubsan неправ с "Unsigned integer overflow" и надо просто его отключить?

Василий Долматов

unread,
Apr 13, 2025, 2:50:49 AMApr 13
to be...@googlegroups.com


12 апр. 2025 г., в 12:19, Alex Loktionoff <oxy...@gmail.com> написал(а):

Вызывает интерес и такой еще разрез: NULL/NIL.
Очень хотелось бы сохранить для С NULL == 0, но и не потерять совместимости с Паскалем.
Интересно зачем в Паскале приняли тако странный NIL?

а причем тут «Паскаль»?

это Пиринский эксцесс… :) 
и в те времена на БЭСМ-6 никаких С не наблюдалось, поэтому совместимость с ним никому даже в голову не приходила.

а само значение - вроде как это «край» дубненского стека, не?

С С-шным NULL библиотечные P/xx функции работать не будут и придется писать свои?

(*=p-,t-,s8,y+*)
program exPointers(output);
var
   number: integer;
   iptr: @integer;
   y: @integer;

begin
   iptr := nil;
   y := ref(iptr);

   

   writeln('the vaule of iptr is ', iptr, y^);
end.

...

ТНЕ VАULЕ ОF IРТR IS  0000000000074000     30720
 КОНЕЦ ЗАДАЧИ
 00411: 00 074 0000 *74

воскресенье, 2 марта 2025 г. в 13:57:42 UTC+1, Alex Loktionoff:
Решил открыть отдельную тему по кодогенерации для нового оптимизирующего компилятора. Тема по формату вызовов https://groups.google.com/g/besm6/c/LJ91waEdhzE/m/USweH2PIAgAJ так и остается, там будем обсуждать только соглашения о вызовах какие были и какие будут, чтоб не захламлять.


--
Данное сообщение отправлено Вам, как участнику группы "БЭСМ-6":
http://groups.google.com/group/besm6/topics
---
Вы получили это сообщение, поскольку подписаны на группу "БЭСМ-6".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес besm6+un...@googlegroups.com.
Чтобы посмотреть обсуждение, перейдите по ссылке https://groups.google.com/d/msgid/besm6/217a92cb-20ee-4435-85a8-addcc3b53831n%40googlegroups.com.

Василий Долматов

unread,
Apr 13, 2025, 3:00:03 AMApr 13
to be...@googlegroups.com


13 апр. 2025 г., в 01:16, Alex Loktionoff <oxy...@gmail.com> написал(а):

Пришла беда, откуда не ждали, ubsan ругается на for (unsigned int i = -count; i++; ) {

runtime error: negation of 1 cannot be represented in type 'unsigned int'

Это для меня выглядит странно, потому как если я говорю i = 0 - count; То я хочу получить такое i, чтоб i + count == 0.

и какое же i в диапазоне unsigned int (!) сложении (!) с count даст 0 ?
или подразумевается, что count принципиально отрицательное?

автоматическое преобразование int в unsigned int и обратно хотелось?
я б на месте компилятора озадачился, это не всегда можно делать без искажения смысла.

Пока пришлось заменить все на int, но при это теряется половина диапазона цикла.
Что делать? По моему ubsan неправ с "Unsigned integer overflow" и надо просто его отключить?

я - на его стороне. 

он не зря требует, чтобы извращение было описано явно.

for (unsigned int i = (unsigned int) (-count); i++) {


--
Данное сообщение отправлено Вам, как участнику группы "БЭСМ-6":
http://groups.google.com/group/besm6/topics
---
Вы получили это сообщение, поскольку подписаны на группу "БЭСМ-6".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес besm6+un...@googlegroups.com.
Чтобы посмотреть обсуждение, перейдите по ссылке https://groups.google.com/d/msgid/besm6/48898ab6-4b29-4fb2-8d5b-a13e03ac62d6n%40googlegroups.com.

Leo Broukhis

unread,
Apr 13, 2025, 4:29:36 AMApr 13
to БЭСМ-6
Как дети маленькие, право. "Отрицание" числа без знака пишется как ~count+1u

Чтобы посмотреть обсуждение, перейдите по ссылке https://groups.google.com/d/msgid/besm6/D575907C-F46B-480E-AAE6-FAE18345C202%40gmail.com.

Alex Loktionoff

unread,
Apr 13, 2025, 5:38:26 AMApr 13
to БЭСМ-6
Компиляторы тоже выросли, Леонид, и генерируемый код для 0U - count и 1U + ~count один и тот-же и ubsan а нем взрывается.  

воскресенье, 13 апреля 2025 г. в 10:29:36 UTC+2, Леонид Брухис:

Alex Loktionoff

unread,
Apr 13, 2025, 6:33:46 AMApr 13
to БЭСМ-6


воскресенье, 13 апреля 2025 г. в 09:00:03 UTC+2, ReedCat:


13 апр. 2025 г., в 01:16, Alex Loktionoff <oxy...@gmail.com> написал(а):

Пришла беда, откуда не ждали, ubsan ругается на for (unsigned int i = -count; i++; ) {

runtime error: negation of 1 cannot be represented in type 'unsigned int'

Это для меня выглядит странно, потому как если я говорю i = 0 - count; То я хочу получить такое i, чтоб i + count == 0.

и какое же i в диапазоне unsigned int (!) сложении (!) с count даст 0 ?
или подразумевается, что count принципиально отрицательное?

автоматическое преобразование int в unsigned int и обратно хотелось?
я б на месте компилятора озадачился, это не всегда можно делать без искажения смысла.

Пока пришлось заменить все на int, но при это теряется половина диапазона цикла.
Что делать? По моему ubsan неправ с "Unsigned integer overflow" и надо просто его отключить?

я - на его стороне.  
Как же обрабатывать массивы свыше 16К на С?
вот код который мне кажется я где-то видел:  
         3, VTM , -(SIZ-1)
 LOOP  : 3, ATX , ARY + (SIZ-1)
         3, VLM , LOOP
и теоретически может, а как такое написать на С?


он не зря требует, чтобы извращение было описано явно.

for (unsigned int i = (unsigned int) (-count); i++) {
Та-же ерунда, поскольку взрыв ubsan происходит не при. компиляции, а при _исполнении_ команд. А сгенерированные команды процессора не зависят от этих дополнительных скобочек:

(lldb) r

Process 86552 launched: '/Users/oxy/myprojects/C/forwat/forwat.exe' (x86_64)

Process 86552 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = Unsigned integer overflow

    frame #0: 0x00000001003555d0 libclang_rt.ubsan_osx_dynamic.dylib`__ubsan_on_report

libclang_rt.ubsan_osx_dynamic.dylib`__ubsan_on_report:

->  0x1003555d0 <+0>: pushq  %rbp

    0x1003555d1 <+1>: movq   %rsp, %rbp

    0x1003555d4 <+4>: popq   %rbp

    0x1003555d5 <+5>: retq   

(lldb) bt 

* thread #1, queue = 'com.apple.main-thread', stop reason = Unsigned integer overflow

  * frame #0: 0x00000001003555d0 libclang_rt.ubsan_osx_dynamic.dylib`__ubsan_on_report

    frame #1: 0x000000010034f9cd libclang_rt.ubsan_osx_dynamic.dylib`__ubsan::Diag::~Diag() + 237

    frame #2: 0x000000010035219a libclang_rt.ubsan_osx_dynamic.dylib`handleNegateOverflowImpl(__ubsan::OverflowData*, unsigned long, __ubsan::ReportOptions) + 602

    frame #3: 0x0000000100351f34 libclang_rt.ubsan_osx_dynamic.dylib`__ubsan_handle_negate_overflow + 52

    frame #4: 0x0000000100005d2e forwat.exe`me_cod_unop_create_load(ptr=0x0000000100da0340, typr=0x0000000100da0320, token=0x00000001000163e8) at me_ast.h:1328:21

    frame #5: 0x0000000100008413 forwat.exe`main at main.c:108:26

    frame #6: 0x000000010002552e dyld`start + 462

(lldb) f 4

frame #4: 0x0000000100005d2e forwat.exe`me_cod_unop_create_load(ptr=0x0000000100da0340, typr=0x0000000100da0320, token=0x00000001000163e8) at me_ast.h:1328:21

   1325 me_bld *bld = me_ctx_cur.bld;

   1326 me_ast_node_kv *p = bld->var_hash;

   1327

-> 1328 for (uint i = (uint)-bld->var_count; i++; ++p)

   1329 if (p->k == ptr) {

Leo Broukhis

unread,
Apr 13, 2025, 9:31:54 AMApr 13
to БЭСМ-6
Вот именно, что компиляторы выросли, а ubsan - не очень, и видит UB там, где его в помине нет. Сложение двух unsigned - по определению по модулю степени двойки.

Leo

Чтобы посмотреть обсуждение, перейдите по ссылке https://groups.google.com/d/msgid/besm6/8d4b5a0a-1bc7-4ae4-88cb-0a75312416ccn%40googlegroups.com.

Leo B.

unread,
Apr 13, 2025, 9:22:22 PMApr 13
to БЭСМ-6
On Sunday, April 13, 2025 at 5:33:46 PM UTC+7 oxy...@gmail.com wrote:
Как же обрабатывать массивы свыше 16К на С?
вот код который мне кажется я где-то видел:  
         3, VTM , -(SIZ-1)
 LOOP  : 3, ATX , ARY + (SIZ-1)
         3, VLM , LOOP
и теоретически может, а как такое написать на С?

Для удобства можно предусмотреть в компиляторе тип __register, и объявленные таким образом переменные назначать на регистры, разрешая с этими переменными только те операции, которые поддержаны в системе команд БЭСМ-6: сложение с константой, сложение с другим регистром, условный переход по нулю/не нулю.

Leo

Alex Loktionoff

unread,
Apr 14, 2025, 11:42:34 AMApr 14
to БЭСМ-6


воскресенье, 13 апреля 2025 г. в 15:31:54 UTC+2, Леонид Брухис:
Вот именно, что компиляторы выросли, а ubsan - не очень, и видит UB там, где его в помине нет. Сложение двух unsigned - по определению по модулю степени двойки.
Что-то не помню в каком-то новом стандарте то ли С++ то ли С признали стандартом дополнение до 2 и wrapping unsigned, или это мои галлюцинации? 
Вот я так и подумал, что ubsan для unsigned это просто зло, и по просту не включать его?
С другой стороны он бы помог отловить некоторые глюки с переполнением в адресной арифметике иногда :-/
//Я тут со всеми санитайзерами в кои-то веки нарвался на баг в компиляторе clang 19, сейчас обновляю до 20.1 :D  

Alex Loktionoff

unread,
Apr 14, 2025, 11:49:53 AMApr 14
to БЭСМ-6


понедельник, 14 апреля 2025 г. в 03:22:22 UTC+2, Leo B.:
Да это можно и со стандартным register сделать, только неужели надо писать еще одно слово во всех циклах?
а портирование чужих программ :-/
Велик и могуч С, а тут просто стена. 

 
Leo

Alex Loktionoff

unread,
Apr 14, 2025, 12:03:07 PMApr 14
to БЭСМ-6


суббота, 12 апреля 2025 г. в 12:57:18 UTC+2, Alex Loktionoff:
Пишу я значит свой back-end, примем начал основательно с нижней части middle-end.
У меня уже мало-мальски формируется AST, если точнее это не AST, а более приземленное /* возможно циклическое*/ графовое представление с зависимостями и basic-block-ами - нечто среднее между LLVM IR и LLVM MIR. И вот как раз на подходе к back-end впал я в ступор.

Принимаю решение реализовывать кодогенерацию a-la GlobalISel а не SelectionDAG так как SelectionDAG уже показало что ни чем не лучше  GlobalISel по качеству генерируемого кода, а по скорости уступает раза в 2, еще  SelectionDAG подразумевает создание кучи дополнительных структур и форматов, что неэффективно а для БЭСМ6 вообще некрасиво до невозможности.
Еще GlobalISel можно реализовывать постепенно, что весьма немаловажно для любительской реализации, а с  SelectionDAG похоже, чтоб что-то заработало надо написать ~%80. - Ok

Но все-равно вопрос, нужно ли создавать еще MIR представление /*отдельные структуры и функции по работе с ними*/??? Очень не хотелось бы! Что бросается в глаза это разница в оформлении параметров функции ну и что в MIR MachineInstr G_ADD например явно указывается регистр результата, в IR Value сама инструкция это уже 'виртуальный' регистр. Первое - а почему-бы кодогенератор при lowering не взять и сгенерировать нужные команды LLVMGetParam().
MachineInstr и так занимает 40-100 байт, у меня me_ast_node занимает 16, хотелось бы запихнуть
На сколько вижу, надо мне двигаться в сторону MIR, и подкрутить свое "дерево", чтоб оно соответствовало всем требованиям MIR.
Требования MIR не совсем понятны, пока вижу, что результат каждой MIR команды может сразу писаться или в виртуальный или физический регистр ЦП.
Для себя заметил, что middle-end генерируя MIR должен вызывать call-back  соответсвующего back-end Target, например для оформления пролога/эпилога для передачи параметров.  
 
В LLVM принято постепенное lowering MIR  инструкций, для максимальной оптимизации это необходимость? Или это артефакт педализации.
Похоже это не артефакт, а так задумано. MIR узлы должны уметь представлять от generic инструкции с виртуальными регистрами до весьма конкретных инструкций целевого процессора с конкретными регистрами процессора. И это не прихоть, а необходимость - для постепенного code-morfing/lowering, унификации входных/выходных данный для каждой стадии конвейера back-end. Чтоб можно было свободно управлять количеством и качеством стадий оптимизации. Без этого сложно управлять скоростью компиляции, а также достичь максимальной оптимизации со временем дописывая стадии оптимизации.

Alex Loktionoff

unread,
Apr 17, 2025, 5:09:48 PMApr 17
to БЭСМ-6
Наступил я на какие-то UB грабли в С. Прошу помощи зала!
Для компилятора написал компактный двусвязный список, который вместо полноразмерных указателей использует короткие относительные индексы. И... все работает только до уровни оптимизации -O2 и в gcc и в clang /*tcc естественно работает всегда*/
Причем вывод одинаковый и в gcc и clang, что кабы намекает что это не баг а какая-то фича :-/
Это меня тормозит в написании back-end ну и понять хочу тоже, чего я до сих пор не понимаю в С,  если немого написать двусвязный список :( 


tdd-test % make clean debug run 

rm -rf *.dSYM

rm -f *.ll *.o *.exe *.map *.dsk a.out

gcc -Wno-language-extension-token -Wall -Wextra -Werror -pedantic -ffunction-sections -fvisibility=hidden -I ../include -DDEBUG -O1 -ggdb -fsanitize=signed-integer-overflow -fsanitize=unsigned-integer-overflow -fsanitize=undefined -fsanitize=address -I/usr/local/opt/openjdk/include  -c -o tst-ilist.o tst-ilist.c

gcc -Wno-language-extension-token -Wall -Wextra -Werror -pedantic -ffunction-sections -fvisibility=hidden -I ../include -DDEBUG -O1 -ggdb -fsanitize=signed-integer-overflow -fsanitize=unsigned-integer-overflow -fsanitize=undefined -fsanitize=address -L ../lib -flto -o tdd-test.exe tst-ilist.o

ld: warning: directory not found for option '-L../lib'

./tdd-test.exe

tdd-test.exe(2569,0x1091a6600) malloc: nano zone abandoned due to inability to preallocate reserved vm space.

Test list empty...                              [ OK ]

Test list singular...                           [ OK ]

Test list dual...                               [ OK ]

Test list complex...                            [ OK ]

Test list foreach...                            [ OK ]

SUCCESS: No unit tests have failed.

tdd-test % make clean release  run | head -20  

rm -rf *.dSYM

rm -f *.ll *.o *.exe *.map *.dsk a.out

gcc -Wno-language-extension-token -Wall -Wextra -Werror -pedantic -ffunction-sections -fvisibility=hidden -I ../include -DNDEBUG -O3 -I/usr/local/opt/openjdk/include  -c -o tst-ilist.o tst-ilist.c

gcc -Wno-language-extension-token -Wall -Wextra -Werror -pedantic -ffunction-sections -fvisibility=hidden -I ../include -DNDEBUG -O3 -L ../lib -flto -o tdd-test.exe tst-ilist.o

ld: warning: directory not found for option '-L../lib'

./tdd-test.exe

Test list empty...                              [ OK ]

Test list singular...                           [ OK ]

Test list dual...                               [ OK ]

Test list complex...                            [ FAILED ]

  tst-ilist.c:82: &item3 == ilist_last_entry(&my_list, my_struct, list)... failed

  tst-ilist.c:84: ilist_is_last(&item3.list, &my_list)... failed

  tst-ilist.c:92: &item2 == ilist_next_entry(&item1, list)... failed

  tst-ilist.c:95: &item2 == ilist_prev_entry(&item3, list)... failed

  tst-ilist.c:96: &item1 == ilist_prev_entry(&item2, list)... failed

  tst-ilist.c:97: &item0 == ilist_prev_entry(&item1, list)... failed

Test list foreach...                            [ FAILED ]

  tst-ilist.c:123: seq_expected[5] == item->data;//1 == 32759... failed

  tst-ilist.c:123: seq_expected[6] == item->data;//2 == 7... failed

  tst-ilist.c:123: seq_expected[7] == item->data;//3 == 6... failed

  tst-ilist.c:123: seq_expected[8] == item->data;//538976288 == 5... failed


причем если вместо short signed int я переопределяю #define ILIST_IDX_T int 

то падает уже даже debug build и даже tcc X-|

ничего не понимаю...


tdd-test % export CC=tcc                    

tdd-test % make clean debug run  | head -20 

rm -rf *.dSYM

rm -f *.ll *.o *.exe *.map *.dsk a.out

tcc -Wno-language-extension-token -Wall -Wextra -Werror -pedantic -ffunction-sections -fvisibility=hidden -I ../include -DDEBUG -O1 -ggdb -fsanitize=signed-integer-overflow -fsanitize=unsigned-integer-overflow -fsanitize=undefined -fsanitize=address -I/usr/local/opt/openjdk/include  -c -o tst-ilist.o tst-ilist.c

tcc -Wno-language-extension-token -Wall -Wextra -Werror -pedantic -ffunction-sections -fvisibility=hidden -I ../include -DDEBUG -O1 -ggdb -fsanitize=signed-integer-overflow -fsanitize=unsigned-integer-overflow -fsanitize=undefined -fsanitize=address -L ../lib -flto -o tdd-test.exe tst-ilist.o

./tdd-test.exe

Test list empty...                              [ OK ]

Test list singular...                           [ OK ]

Test list dual...                               [ FAILED ]

  tst-ilist.c:56: ilist_is_last(&item2.list, &my_list)... failed

  tst-ilist.c:57: &item2 == ilist_next_entry(&item1, list)... failed

  tst-ilist.c:58: &item1 == ilist_prev_entry(&item2, list)... failed

Test list complex...                            [ FAILED ]

  tst-ilist.c:83: &item3 == ilist_last_entry(&my_list, my_struct, list)... failed

  tst-ilist.c:85: ilist_is_last(&item3.list, &my_list)... failed

  tst-ilist.c:92: &item1 == ilist_next_entry(&item0, list)... failed

  tst-ilist.c:93: &item2 == ilist_next_entry(&item1, list)... failed

  tst-ilist.c:94: &item3 == ilist_next_entry(&item2, list)... failed

  tst-ilist.c:96: &item2 == ilist_prev_entry(&item3, list)... failed

  tst-ilist.c:97: &item1 == ilist_prev_entry(&item2, list)... failed

  tst-ilist.c:98: &item0 == ilist_prev_entry(&item1, list)... failed


воскресенье, 2 марта 2025 г. в 13:57:42 UTC+1, Alex Loktionoff: 

Решил открыть отдельную тему по кодогенерации для нового оптимизирующего компилятора. 
... 

Michael Yaroslavtsev

unread,
Apr 17, 2025, 5:32:15 PMApr 17
to be...@googlegroups.com
On Thu, Apr 17, 2025 at 2:09 PM Alex Loktionoff <oxy...@gmail.com> wrote:
Наступил я на какие-то UB грабли в С. Прошу помощи зала!
--
Данное сообщение отправлено Вам, как участнику группы "БЭСМ-6":
http://groups.google.com/group/besm6/topics
---
Вы получили это сообщение, поскольку подписаны на группу "БЭСМ-6".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес besm6+un...@googlegroups.com.
Чтобы посмотреть обсуждение, перейдите по ссылке https://groups.google.com/d/msgid/besm6/e0d1355b-02a7-46cd-aab1-21fc5f97a78cn%40googlegroups.com.


--
Thanks,
-- Michael

Serge Vakulenko

unread,
Apr 17, 2025, 5:46:13 PMApr 17
to БЭСМ-6
Наткнулся я недавно на статью: "Abstract Syntax Tree Implementation Idioms".


Цитата из неё:
"Strictly imperative languages, like C or Pascal, provide the least support for implementing ASTs.
* * *
Avoid these languages if possible. If this isn’t possible, then implement the AST in a disciplined fashion, making representation and naming choices uniformly.
* * *"

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

--Сергей

Alex Loktionoff

unread,
Apr 18, 2025, 12:26:52 AMApr 18
to БЭСМ-6
Вот те раз, какой конфуз. https://github.com/oxy1914/ilist/blob/main/include/ilist.h


четверг, 17 апреля 2025 г. в 23:32:15 UTC+2, BOPOHOK:
On Thu, Apr 17, 2025 at 2:09 PM Alex Loktionoff <oxy...@gmail.com> wrote:
Наступил я на какие-то UB грабли в С. Прошу помощи зала!

воскресенье, 2 марта 2025 г. в 13:57:42 UTC+1, Alex Loktionoff: 

Решил открыть отдельную тему по кодогенерации для нового оптимизирующего компилятора. 
... 

Alex Loktionoff

unread,
Apr 18, 2025, 1:01:42 AMApr 18
to БЭСМ-6
А что мы? Мы очень дисциплинированные :)
И пишем мы сейчас не совсем AST, а Machine IR, это по-проще, хотя может это не принципиально. 

А на че-же тогда писать компилятор? Из системных языков - С самый простой, месяца 3 на разработку для новой платформы.
А на каком-же языке можно написать утоптанные структуры списков и хешей, чтоб использовали короткие смещения вместо полноразмерных указателей? Сейчас это С++, но для нас это не вариант для self-hosting, а аначе - прямая дорога для написания back-end llvm.

четверг, 17 апреля 2025 г. в 23:46:13 UTC+2, serge.v...@gmail.com:

Serge Vakulenko

unread,
May 6, 2025, 4:50:30 PMMay 6
to БЭСМ-6
Если хочется именно self-hosting, то придётся писать на Си, конечно. А так бы я выбрал Golang (если хочется попроще) или Rust (если хочется приключений).

А откуда возникло желание коротких смещений вместо полноразмерных указателей? В чём прелесть?

--Сергей

Serge Vakulenko

unread,
May 6, 2025, 6:25:01 PMMay 6
to БЭСМ-6
Помогу чем могу. Я попросил Грока сгенерить юнит тесты для этого ilist. Результат сложил здесь: github.com/sergev/test-ilist. Подробности смотрите README. Тесты проходят на Линуксе но падают на маке. Разная политика выделения памяти.

Проблема в том, что в функции ilist_add_() делается вычитание указателей, и результат запихивается в short int. В молчаливом предположении, что элементы списка находятся в памяти относительно близко, в пределах 32к элементов. Это предположение в общем случае неверно.  

--Сергей

On Thursday, April 17, 2025 at 2:09:48 PM UTC-7 oxy...@gmail.com wrote:

Alex Loktionoff

unread,
May 10, 2025, 1:19:13 PMMay 10
to БЭСМ-6


среда, 7 мая 2025 г. в 00:25:01 UTC+2, serge.v...@gmail.com:
Помогу чем могу. Я попросил Грока сгенерить юнит тесты для этого ilist. Результат сложил здесь: github.com/sergev/test-ilist. Подробности смотрите README. Тесты проходят на Линуксе но падают на маке. Разная политика выделения памяти.

Проблема в том, что в функции ilist_add_() делается вычитание указателей, и результат запихивается в short int. В молчаливом предположении, что элементы списка находятся в памяти относительно близко, в пределах 32к элементов. Это предположение в общем случае неверно.  
В общем случае неверно, но список как раз для конкретного - когда все лежит рядом.
Грок сгенерировал неподходящие fixture.
Удалось ли понять причину почему все разваливается при использовании long вместо short?
 
--Сергей

On Thursday, April 17, 2025 at 2:09:48 PM UTC-7 oxy...@gmail.com wrote:
Наступил я на какие-то UB грабли в С. Прошу помощи зала!
Для компилятора написал компактный двусвязный список, который вместо полноразмерных указателей использует короткие относительные индексы. И... все работает только до уровни оптимизации -O2 и в gcc и в clang /*tcc естественно работает всегда*/
Причем вывод одинаковый и в gcc и clang, что кабы намекает что это не баг а какая-то фича :-/
Это меня тормозит в написании back-end ну и понять хочу тоже, чего я до сих пор не понимаю в С,  если немого написать двусвязный список :( 


Alex Loktionoff

unread,
May 10, 2025, 4:21:21 PMMay 10
to БЭСМ-6


суббота, 10 мая 2025 г. в 19:19:13 UTC+2, Alex Loktionoff:


среда, 7 мая 2025 г. в 00:25:01 UTC+2, serge.v...@gmail.com:
Помогу чем могу. Я попросил Грока сгенерить юнит тесты для этого ilist. Результат сложил здесь: github.com/sergev/test-ilist. Подробности смотрите README. Тесты проходят на Линуксе но падают на маке. Разная политика выделения памяти.

Проблема в том, что в функции ilist_add_() делается вычитание указателей, и результат запихивается в short int. В молчаливом предположении, что элементы списка находятся в памяти относительно близко, в пределах 32к элементов. Это предположение в общем случае неверно.  
В общем случае неверно, но список как раз для конкретного - когда все лежит рядом.
Грок сгенерировал неподходящие fixture.
Удалось ли понять причину почему все разваливается при использовании long вместо short?
 
Мне кажется что первый в жизни я нарвался на pointer provenance 
 
--Сергей

Serge Vakulenko

unread,
May 10, 2025, 5:21:16 PMMay 10
to БЭСМ-6
On Saturday, May 10, 2025 at 1:21:21 PM UTC-7 oxy...@gmail.com wrote:
суббота, 10 мая 2025 г. в 19:19:13 UTC+2, Alex Loktionoff:
Удалось ли понять причину почему все разваливается при использовании long вместо short? 
Мне кажется что первый в жизни я нарвался на pointer provenance 

Таки да: нынешний Си уже не тот, что раньше. 😀
 
Я дальше не исследовал. Проблема очень далёкая от нашей темы компиляторостроения.

--Сергей
Reply all
Reply to author
Forward
0 new messages