vak: (Default)
[personal profile] vak
Есть вариант, как небольшими усилиями соорудить Си компилятор для БЭСМ-6. Есть такой проект ELVM. Это универсальный компилятор Си на основе LLVM, но не для конкретных процессоров, а вообще. Он выдаёт код для некоторой абстрактной машины. И дальше строятся бекэнды для разнообразных от смешных типа Brainfuck или Conway's Life до реальных типа WebAssembly.

Для прикола народ скомпилировал простой компилятор Си на "машину" - скрипт для редактора VI. И оно работает! Хотя нешустро: компиляция "Hello World" в таком VI занимает двадцать минут: "C Compiler exists purely in VIM".

Идея аналогичная древнему компилятору BCPL, который позже превратился в B (предшественник Си). Выдаём код для абстрактной машины, и строим отдельные кодогенераторы, транслирующие абстрактный код в выполняемый бинарник для нужной архитектуры. Такой подход оказался успешным, и немало способствовал распространению BCPL пятьдесят лет назад.

Не вижу проблем повторить это дело для БЭСМ-6. Размер кодогенератора для архитектуры x86, к примеру - всего 309 строк.

Побробуем запустить классический пример "Hello World" через ELVM для архитектуры x86 под Линуксом.
Собираем компилятор:
git clone https://github.com/shinh/elvm.git
cd elvm
git submodule update --init
make
Результатом будут бинарники out/8cc (компилятор) и out/elc (кодогенератор). Возьмем простой вариант "Hello World":
int main() 
{
const char* p = "Hello, world!\n";
for (; *p; p++)
putchar(*p);
return 0;
}
Компилируем, получаем ассемблерный код абстрактной машины:
$ cd out
$ ./8cc -S hello.c
$ cat hello.s
.text
main:
#{push:main}
mov D, SP
add D, -1
store BP, D
mov SP, D
mov BP, SP
sub SP, 1
.file 1 "hello.c"
.loc 1 7 0
# }
.loc 1 4 0
# for (; *p; p++)
mov A, 0
mov B, SP
.data
.L3:
.string "Hello, world!\n"
.text
mov A, .L3
mov B, BP
add B, 16777215
store A, B
.loc 1 5 0
# putchar(*p);
.L0:
.loc 1 4 0
# for (; *p; p++)
mov B, BP
add B, 16777215
load A, B
mov B, A
load A, B
jeq .L4, A, 0
jmp .L5
.L4:
.loc 1 5 0
# putchar(*p);
jmp .L2
.L5:
.loc 1 4 0
# for (; *p; p++)
mov B, BP
add B, 16777215
load A, B
mov B, A
load A, B
mov D, SP
add D, -1
store A, D
mov SP, D
putc A
add SP, 1
.loc 1 5 0
# putchar(*p);
.L1:
.loc 1 4 0
# for (; *p; p++)
mov B, BP
add B, 16777215
load A, B
mov D, SP
add D, -1
store A, D
mov SP, D
add A, 1
mov B, BP
add B, 16777215
store A, B
load A, SP
add SP, 1
.loc 1 5 0
# putchar(*p);
jmp .L0
.L2:
.loc 1 7 0
# }
mov A, 0
mov B, A
#{pop:main}
exit
#{pop:main}
exit
Превращаем в бинарник для x86:
$ ./elc -x86 hello.s > hello.elf
$ file hello.elf
hello.elf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, no section header
Запускаем:
$ ./hello.elf
Hello, world!

Date: 2024-07-09 19:32 (UTC)
From: [personal profile] dijifi
Вроде у Цанга кто-то строил Си для СВС. Не сохранилось?

Date: 2024-07-09 21:14 (UTC)
From: [personal profile] dijifi
Цанга уже машина сбила

Date: 2024-07-09 21:47 (UTC)
From: [personal profile] dijifi
Да, Феликс Рудольфович Цанг, 1942 — 1984, человек талантливый и увлеченный. Си в его группе изучали в 1982. После его гибели всё развалилось, несмотря на мемориальное название ОС.
Edited Date: 2024-07-09 22:02 (UTC)

Date: 2024-07-10 06:49 (UTC)
x86128: (Default)
From: [personal profile] x86128
Вот это поворот!
Затем была запоминающаяся работа в замечательном творческом коллективе первой лаборатории по установке UNIX-ов на отечественные железяки: OS – Основич, Молчанов; Файловая система – Городилов, Райхерт, Семухина; Отладчики – Горр; мы с Вакуленко портировали первую версию С компилятора; Борис Кузнецов – утилиты и librt. Первой жертвой стала старушка БЭСМ, на которой мы установили мировой рекорд – UNIX на самой старой машине в мире.

Date: 2024-07-10 01:10 (UTC)
sab123: (Default)
From: [personal profile] sab123
Код абстрактной машины выглядит подозрительно похожим на i86. Поэтому, небось, для нее и такой маленький кодогенератор.

Date: 2024-07-10 15:12 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Игрушечный компилятор
No bit operations
No floating point arithmetic
конечно, получится. Ради оптимизации можно взять бэкенд для фортрана и допинать в приемлемый для Форекса, или написать бэкенд в Паскаль.
Но это не то, о чём так долго говорили большевики. :)

Date: 2024-07-10 20:50 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Абстрактная машина с каким-то произвольным количеством регистров плохо ложится на БЭСМ-6 - плотность порождаемого кода будет неприемлемая. Впрочем, и пресловутый компилятор в стековую машину, с которым можно было бы поиграться, https://github.com/rswier/c4/ - потребует серьёзной работы, если именно компилировать, а не интерпретировать. Из
int a, b;
exch() {
        a = a ^ (b = b ^ (a = a ^ b));
}

получается
1: int a, b;
2: exch() {
3:  	a = a ^ (b = b ^ (a = a ^ b));
    ENT  0
    IMM  -137158648
    PSH 
    IMM  -137158648
    LI  
    PSH 
    IMM  -137158644
    PSH 
    IMM  -137158644
    LI  
    PSH 
    IMM  -137158648
    PSH 
    IMM  -137158648
    LI  
    PSH 
    IMM  -137158644
    LI  
    XOR 
    SI  
    XOR 
    SI  
    XOR 
    SI  
4: }
    LEV 

а хочется, в конце концов, всего-навсего 7 команд
 XTA A
 AEX B
 ATX A
 AEX B
 ATX B
 AEX A
 ATX A


Так что для относительно быстрого результата - только хардкор в виде прихачивания сишного фронтенда к имеющемуся паскалевскому бэкенду.