компиляторы С++ используют SSA формат для генерации кода. А как он в этом формате обрабатывает ссылки и указатели? (если их не учитывать, то взяв адрес с переменной и преобразуется следующее выражение(оно будет в новой переменной) то адрес будет уже неправильным). Заранее благодарен.
промежуточное представление а куда результат записывается? что ты этим хотел сказать ? может скажешь как с ссылками дело обстоит ? https://courses.cs.washington.edu/courses/cse501/04wi/slides/slides.slides.ps.pdf есть пример но я его не догоняю
Там предлагается LLVM так и поступает. SSA только для регистров, а для памяти там не используется SSA-представление. Этим в тьюториале предлагают пользоваться для упрощения кодогенерации https://llvm.org/docs/tutorial/LangImpl07.html#memory-in-llvm
Так учитывайте. Кто вам не даёт? Взятие адреса это числовое преобразование, а в данном случае речь идёт о символьных. А во вторых основа адреса сохраняется так что всегда есть возможность восстановить адрес.
Да. Я просто остановился на том, о применении чего мне точно известно. Применяют ли GCC или MSVC i-функцию вместо не-SSA памяти я не знаю.
возник ещё такой вопрос: SSA строится в компиляторах над произвольном выражением типа оп1:=оп2+оп3 , или уже из машинно специфичных выражениях оп2:=оп2+оп3? всем спасибо!
зависит от SSA вероятно... LLVM IR строго типизирован, то есть оп1 = add i32 оп2 оп3, то есть сложение двух 32-битных интов в третий 32-битный инт... у GCC представление GIMPLE тож вроде строго типизированное, если мне не изменяет память... только там вроде не пишется типизация в операции, но все регистры объявляются в начале функции с указанием типа, аля старая сишечка... у GCC еще есть RTL представление, более низкоуровневое, но это уже почти как ассемблер, но в виде LISP-синтаксисе...
не совсем то (то что строго типизировано это понятно иначе бы не скомпилировалось) при помощи mov можно записать только в первый источник - приходится коректировать код как я понял современные компиляторы сначало переводят в SSA а потом при генерации кода переводят в бинарные (двух операторные) команды а почему так ? не подскажите - вроде можно и наоборот ...
немного подумавши стал догонять - в SSA каждое новое присваивание в новую переменную то есть для машинных команд не подходит а когда переводят SSA в машинные команды наверное учитывают специфику машинных команд во время распределения регистров где-нибудь это описано ? чтото эта тема плохо освещена... в книжках и интернете ... наверное сложная
что значит плохо освящена? в драконьей книге вроде была отдельная глава про распределение регистров, у стенфорда в видео курсе по компиляторам тож отдельная глава про это...
возник такой вопрос:" как я понял при обработке С++ выражений в промежуточный код получается очень много промежуточных переменных - компилятор скорее всего оптимизирует(переставляет мат операции местами) чтобы понадобилось меньше регистров/переменных для выполнения". Какими методами он это делает? Или перебором переставляет выражения а потом откидывает те которые используют не появившиеся переменные?
Что-то я не догоняю с парсингом ... Везде перед какими либо манипуляциями исходный текст вместе с выражениями парсят к примеру через LL в дерево. Но ведь по стандарту строго регламентировано в какой последовательности должно всё вычисляться в выражениях и удобнее воспроизвести вроде без дерева когда всё обычным текстом. Ответе пожалуйста что вы думаете по поводу этого вопроса.
Код (Text): void main() { int i = 5; i = ++i + ++i; printf("i = %d\n", i); } Думаю, вы поняли, где ошиблись.
По стандарту строго регламентировано что должно вычисляться в определенной последовательности, а что - на усмотрение компилятора. Например параметры функции могут быть вычислены в любой последовательности. a(b(), c()). Функции b() и с() могут быть вызваны в любом порядке.
слева на право --- Сообщение объединено, 12 фев 2019 --- к примеру часто встречается такая проверка if(obj!=0&&obj->n==1) если наоборот то возможно будет чтение из ненужного куска памяти
ни разу не так... даже на одном компиляторе в зависимости от настроек оптимизации может быть разный порядок вычисления...
VaVa, в приведенном тобой примере происходит вычисление параметров оператора &&, а не параметров функции. Порядок вычисления параметров оператора && действительно происходит слева направо, и так как в твоем примере - делать можно. За исключением ситуации, когда оператор && определен пользователем - тогда на него действую те же правила, что и на функцию: порядок вычисления остается на усмотрение компилятора, и все параметры будут вычислены, прежде чем вернуть результат. В отличие от встроенного оператора, который не будет вычислять параметры, если их значения уже не повлияют на результат: например if(false && foo()) { ... }
наверное не самый удачный пример а вот i = i + ++ i + i если правильно x1=++i (и i=i+1) x2=i+x1 x3=x2+i строим дерево Код (Text): = i + ++ + i i i если обходить левой рекурсией как обычно i=x1 x1=x2+x3 x2=++i (не вызвалось i=i+1 вовремя а не изменённая i посчиталась) x3=i+i --- Сообщение объединено, 16 фев 2019 --- никто не подскажет как ещё можно хранить выражения (кроме как мучатся с деревом) чтобы всё по порядку учитывать и без промежуточных переменных?