- 1
- 2
- 3
- 4
- 5
- 6
function main() {
const x = 21;
let s = "foo";
const r = `a${x * 2}X${s}X${s}Z`;
print(r);
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+1
function main() {
const x = 21;
let s = "foo";
const r = `a${x * 2}X${s}X${s}Z`;
print(r);
}
Продолжаем будни говно-писания говно-компилятора на LLVM. серия - а ваш говно-компилятор может так...
и результат работы
>>
C:\temp\MLIR_to_exe>out.exe
a42XfooXfooZ
ASD_77 10.05.2021 12:48 # 0
3_dar 10.05.2021 12:50 # 0
ASD_77 10.05.2021 12:57 # 0
3_dar 10.05.2021 13:02 # 0
ASD_77 10.05.2021 13:12 # 0
3_dar 10.05.2021 13:16 # +1
j123123 10.05.2021 23:08 # 0
MAKAKA 10.05.2021 23:10 # 0
Тем, что в нём нету регистра 33?
bormand 10.05.2021 23:13 # 0
MAKAKA 10.05.2021 23:16 # 0
Если я сделаю процессор, в котором можно "создать" 64 регистра, то я смогу запустить на нём llvm?
CHayT 10.05.2021 23:19 # 0
MAKAKA 10.05.2021 23:21 # 0
А что, их вообще может быть сколько угодно много? Фронтэнд может сгенерить код, в котором будет 65536 регистров?
bormand 10.05.2021 23:22 # 0
Ну да, это просто форма записи такая. Все переменные, промежуточные результаты и т.п. попадают в "регистры". Если функция сложная, там запросто нагенерится тыща "регистров".
Ну и да, посколько это single assignment, то там одна переменная может в десяток-другой раскрыться, чтобы для оптимизатора поток данных нагляднее был.
bormand 10.05.2021 23:22 # 0
MAKAKA 10.05.2021 23:25 # 0
А вот как это в gcc сделано? Там же тоже есть фронт и бек, но там не генерится промежуточный код? Или генерится? А тогда в чем разница?
Ябло вроде хвасталось, что перейдя на llvm они смогли применять какие-то фиксы (типа ARC или чего-то такого) уже вот прямо к llvm коду
bormand 10.05.2021 23:28 # +1
В gcc тоже промежуточный код был, как без него. Вроде даже джва. Но он там пиздец запутанный и фазы не так чётко разделены как в llvm, емнип.
CHayT 10.05.2021 23:29 # +1
guest6 10.05.2021 23:30 # 0
вот clang же высирает код в llvm, а далее llvm генерит по нему код под x86, верно?
как же сlang может чего-то не знать?
bormand 10.05.2021 23:31 # +3
А соглашения о вызовах, аллокация конкретных регистров, выбор конкретных инструкций -- это уже задача бэка.
guest6 10.05.2021 23:35 # 0
* в "промежуточном коде" LLVM есть понятие "регистр"
* в этом коде регистров может быть неограниченное количество
* clang генерирует это код, используя понятие "регистр"
* clang может создать промежуточный код, в котором используется 234234 регистра
* если доступ к первым пяти будет дешевым, а к остальным дорогим (бо в реальной архитектуре они эмулируются), то clang сгенерит неоптимизированный код
Или бекенд может "оптимизировать" код, удалив лишне регистры, если он знает, что делает код для гиоптетчиской LLVM машины с пятью регистрами?
Типа clang насрал 100500 регистров, а бек их причесал?
bormand 10.05.2021 23:38 # 0
Какие из них горячие, а какие нет фронт не знает. Да его это и не должно ебать. Выделять регистры и слоты на стеке -- задача бэка и только бэка. Ибо только он знает сколько там регистров на таргете и видит более-менее финальную форму кода после кучи перестановок и оптимизаций.
CHayT 10.05.2021 23:40 # +1
LLVM IR регистры — абстрактные, и к хардварным отношения не имеют.
> в этом коде регистров может быть неограниченное количество
> clang может создать промежуточный код, в котором используется 234234 регистра
Да, потому что SSA, и LLVM "регистры" иммутабельные. Если фронтенд заанроллит цикл с 234234 итерациями, то под i понадобится 234234 регистров.
> clang генерирует это код, используя понятие "регистр"
...из LLVM IR.
> Или бекенд может "оптимизировать" код, удалив лишне регистры, если он знает, что делает код для гиоптетчиской LLVM машины с пятью регистрами?
Бекенд по определению не делает код для гипотетической машины, он делает код для конкретной хардварной рахитектуры.
guest6 10.05.2021 23:42 # 0
я просто думал, реально ли сделать такое
фронт --> LLVM код --> реальный проц
но уже понял, что без бека это нереально
bormand 10.05.2021 23:44 # 0
guest6 10.05.2021 23:45 # 0
CHayT 10.05.2021 23:46 # +1
guest6 10.05.2021 23:47 # 0
bormand 11.05.2021 12:03 # +1
А почему? Их ленивые thunk'и плохо вписались в LLVM IR?
CHayT 11.05.2021 12:07 # +2
3.14159265 22.08.2021 01:55 # 0
Интересненько.
А у них до сих пор в качестве «промежуточного» кода урезанная Сишка?
CHayT 22.08.2021 02:05 # 0
Sandwich 22.08.2021 02:07 # 0
j123123 12.05.2021 00:40 # +1
Этот "универсальный" бэкенд настолько же универсален, как и какое-нибудь внутреннее говнопредставление из GCC. Нихуя такого прорывного там нет с т.з. фундаментальных вещей, просто еще одна питушня для промежуточного представления питушни с целью трансформации-оптимизации, коих было дохуя, есть дохуя, и будет еще дохуя. Не очень-то ясно, с хуев каких на него так все надрачивают.
3.14159265 22.08.2021 01:56 # +1
Очевидно же. Питузу в нём проще разобраться, чем в хитросплетениях гцц.
И любой питуз может клепать на коленке свои анскильные rustы и кричать на каждом углу «йаже как Сишка».
Sandwich 22.08.2021 01:59 # 0
j123123 20.07.2021 21:02 # +1
Нет. Он знает про то, что такой-то процессор имеет такой-то размер указателя и такие-то требования по выравниванию, а это влияет много на что, например на чтение-загрузку структур с указателями
Вот пример https://godbolt.org/z/ednTbTfMM - align 4 для 32 бит и и align 8 для 64 бит
А если clang будет генерить код под процессор, где например char 16-битный, там указатели на char (и указатели на void) будут не i8* а i16*
j123123 20.07.2021 21:10 # +1
А еще https://llvm.org/docs/LangRef.html#x86-amx-type есть вот такая x86-специфичная хуйня, которой очевидно нет нигде, кроме x86.
Так что говорить что фронт ничего не знает про процессор - некорректно. Он вообще-то дохуя чего знает
3.14159265 22.08.2021 02:03 # 0
> X86_mmx Type
Какое говно )))
Они добавили эту крайне специфичную питушню к таким базовым, универсальным вореционным типам как i8, i16, i32 и плавающим fp32, fp64, fp128.
Sandwich 22.08.2021 02:03 # 0
j123123 14.11.2021 00:35 # 0
Так-то этот LLVM может теоретически изначально оперировать generic-хуитой типа i8 i16 и проч, и на какой-то из говностадий перефигачить это во всякое процессорозависимое говно типа X86_mmx. Это еще называется "lowering"
https://llvm.org/docs/WritingAnLLVMBackend.html#basic-steps
> Describe the selection and conversion of the LLVM IR from a Directed Acyclic Graph (DAG) representation of instructions to native target-specific instructions. Use TableGen to generate code that matches patterns and selects instructions based on additional information in a target-specific version of TargetInstrInfo.td. Write code for XXXISelDAGToDAG.cpp, where XXX identifies the specific target, to perform pattern matching and DAG-to-DAG instruction selection. Also write code in XXXISelLowering.cpp to replace or remove operations and data types that are not supported natively in a SelectionDAG.
bormand 10.05.2021 23:34 # 0
guest6 10.05.2021 23:38 # 0
Я думал, что если я создам такую машину, которая запускает LLVM код напрямую, и в ней будет 4 регистра (а остальные эмулируются), то код будет не оптимальным
Но теперь я понял, что мне всё равно нужен будет для нее бек, и превратить идеальный LLVM код в реальный это будет задача уже бека
bormand 10.05.2021 23:40 # 0
Ну да, если ты надумаешь исполнять LLVM код "вживую", он будет неоптимальным. Ну потому что эта промежуточная форма весьма далека от железа.
А если у тебя будет бэк, то ты уже не LLVM код исполняешь, лол.
j123123 21.08.2021 06:35 # 0
Чтобы "вживую" его исполнять, нужно иметь соответствующий процессор, а такого процессора нет, да и сделать его похоже что нереально, ну вот как ты будешь регистры хуй знает какого размера в процессоре реализовывать? LLVM разве что интерпретировать можно вживую
bormand 21.08.2021 08:43 # 0
Сложнее с количеством. Видимо придется штук 30 держать регистрами, а остальное своповать в память.
j123123 21.08.2021 11:03 # 0
Сомнительная идея. Не всякий регистр ты сможешь микрокодом эмулировать.
Проэмулируй мне регистр размером в килобайт в микрокоде
guest6 21.08.2021 11:09 # 0
j123123 21.08.2021 11:11 # 0
guest6 21.08.2021 11:14 # 0
пусть ОСили прошивка загрузит ему адрес куска памятив регистр, как таблы страниц в CR3 (или куда их там грузят)
вот как освобождать -- это интересно
сделайте в процессоре GC
j123123 21.08.2021 11:26 # 0
Уже сделали: https://en.wikipedia.org/wiki/Symbolics#The_3600_series
> Hardware support was provided for virtual memory, which was common for machines in its class, and for garbage collection, which was unique.
Но эти аппаратные лисп-машины закономерно обосрались. Железо это не говноязык типа "C++", что туда всякое говно можно набрасывать спокойно, и ничего особо плохого не будет
MAKAKA 21.08.2021 16:15 # 0
так и случилось
j123123 21.08.2021 11:19 # +1
bormand 21.08.2021 12:05 # +1
На стеке же. А в реальный регистр положить её адрес и длину. Освободится вместе с фреймом.
j123123 21.08.2021 12:08 # 0
А если стека окажется недостаточно для такого жирного регистра? Ну и к тому же регистр можно возвратить из функции, а стек нельзя, как эта проблема будет решаться?
bormand 21.08.2021 12:10 # 0
Мне вот интересно, что реальные бекенды с этим делают. Просто шлют нахуй или эмулируют через длинную арифметику?
j123123 21.08.2021 12:27 # 0
Думаю что middle-end говнопредставление перед переходом в back-end должно все такое говно вычистить. Т.е. хуйня с жирными LLVM регистрами должна в этом LLVM там как-то заоптимизироваться и потом в итоге переписаться в регистры с допустимым размером.
bormand 21.08.2021 08:44 # 0
А где эта грань? Любой проц интерпретирует какой-то байткод.
Реальная конпеляция разве что в верилоге да вхдл, там не доебёшься.
MAKAKA 21.08.2021 09:36 # 0
bormand 21.08.2021 09:42 # 0
Да как это? Загружали команды по одной и исполняли их. Что это, если не интерпретация?
MAKAKA 21.08.2021 09:45 # 0
3.14159265 22.08.2021 02:15 # 0
Причём микрокодом. И со стадиями конвейера (начиная с 486).
Sandwich 22.08.2021 02:23 # 0
3.14159265 22.08.2021 02:09 # 0
В x86 микрокод был всегда.
Пруфом тому количество тактов на команду.
Причём всё было наоборот, они только где-то с 486 научились некоторые инстры исполнять напрямую.
Sandwich 22.08.2021 02:10 # 0
j123123 21.08.2021 06:23 # +1
У тебя тут "rol" а какая-то хуйня.
Если ты сдвигаешь 32-битного питуза, надо return (x << 15) | (x >> (32-15) );
grimskin 22.08.2021 02:35 # 0