Например:
loadAI r1, 4 => r2 //это инструкция для загрузки значения по адресу вычисляется по базовому адресу, хранящемуся в виртуальном регистре 1 (r1) со смещением 4, в виртуальном регистре 2 (r2)
С точки зрения высокого уровня я хочу, чтобы инструкция сохранялась как тройка (loadAI, [r1, 4], [г2]). Общая форма: (код операции, [список исходных операндов], [список результирующих операндов])
Моя проблема заключается в фактической реализации такой структуры данных (на C++). Проблемы возникают из-за того, что операнды могут быть разных типов.
Теоретически я мог бы просто хранить каждый операнд как строку и таким образом представлять IR. Например, регистр r1 может быть сохранен как «r1». Или, если операнд является константой, например 524288, его можно сохранить как «524288». Это означает, что компилятору приходится читать, сравнивать и манипулировать строковыми значениями при работе с IR — это кажется неэффективным, особенно когда существует очевидный способ представить хотя бы некоторые типы операндов в виде чисел.
... поэтому я подумал, как все могло бы работать, если бы я использовал числа для представления операндов. Например, регистр r1 может быть представлен целочисленным значением 1. Однако помимо регистров существуют и другие типы операндов. Например, буквальные значения. Что, если мой компилятор встретит long int = -32? Инструкцией IR высокого уровня может быть loadI -32 => r2. Тогда это означает, что моя структура данных должна иметь возможность хранить/обрабатывать операнды разных типов и значений. Некоторые операнды могут быть регистрами. Некоторые из них могут быть литералами самых разных типов (char, short, int, long, float, double, знаковый или беззнаковый). Как я могу реализовать класс Operand, в котором базовый операнд может иметь разные представления?
После исследования некоторых функций C++ (я новичок в C++) мне показалось, что объединение может быть Хороший вариант решения проблемы с операндами различных возможных типов. В дополнение к этому я бы использовал перечисление, которое перечисляет все возможные типы операндов:
Код: Выделить всё
union OperandSymbol {
int regID;
int signed_int_const;
float float_const;
//... alot more types
}
enum {regID, signed_int_const, float_const, ... } //large enum
OperandSymbol opSym;
int operandType; //holds a value from the above enum
Сначала мы запросим OperandType этого операнда. Затем нам нужно будет жестко запрограммировать оператор переключения с одним регистром для каждого возможного значенияoperandType (т. е. размера перечисления, который может быть около 12). В зависимости от того, какая ветвь выбрана, мы получаем доступ к соответствующему члену объединения.
Это делается каждый раз, когда мы обращаемся к операнду какой-либо инструкции.
Мои последние вопросы:
Разумно ли это?
Должен ли я просто представлять операнды строками?
Если нет, существуют ли функции C++, которые решают эту проблему?
Я новичок в этом компиляторы, поэтому я понимаю, что мое непонимание может быть причиной реальный источник моей проблемы.
Подробнее здесь: https://stackoverflow.com/questions/792 ... ediate-rep
Мобильная версия