474 lines
20 KiB
Plaintext
474 lines
20 KiB
Plaintext
|
|
// ============================================================
|
|||
|
|
// Заголовочный файл компилятора RUSI
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
#еслинеопр RUSI_H
|
|||
|
|
#определить RUSI_H
|
|||
|
|
|
|||
|
|
#определить _POSIX_C_SOURCE 200809L
|
|||
|
|
|
|||
|
|
#включить <assert.h> // стандартная библиотека
|
|||
|
|
#включить <ctype.h> // стандартная библиотека
|
|||
|
|
#включить <errno.h> // стандартная библиотека
|
|||
|
|
#включить <glob.h> // стандартная библиотека
|
|||
|
|
#включить <libgen.h> // стандартная библиотека
|
|||
|
|
#включить <stdarg.h> // стандартная библиотека
|
|||
|
|
#включить <stdbool.h> // стандартная библиотека
|
|||
|
|
#включить <stdint.h> // стандартная библиотека
|
|||
|
|
#включить <stdio.h> // стандартная библиотека
|
|||
|
|
#включить <stdlib.h> // стандартная библиотека
|
|||
|
|
#включить <stdnoreturn.h> // стандартная библиотека
|
|||
|
|
#включить <string.h> // стандартная библиотека
|
|||
|
|
#включить <strings.h> // стандартная библиотека
|
|||
|
|
#включить <sys/stat.h> // стандартная библиотека
|
|||
|
|
#включить <sys/types.h> // стандартная библиотека
|
|||
|
|
#включить <sys/wait.h> // стандартная библиотека
|
|||
|
|
#включить <time.h> // стандартная библиотека
|
|||
|
|
#включить <unistd.h> // стандартная библиотека
|
|||
|
|
|
|||
|
|
пусто free_all_types(пусто);
|
|||
|
|
пусто free_all_tokens(пусто);
|
|||
|
|
пусто free_all_preprocess(пусто);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Общие макросы
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
#определить MAX(a, b) ((a) < (b) ? (b) : (a))
|
|||
|
|
#определить MIN(a, b) ((a) < (b) ? (a) : (b))
|
|||
|
|
|
|||
|
|
#еслинеопр __GNUC__
|
|||
|
|
#определить __attribute__(x)
|
|||
|
|
#конецесли
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Предварительные объявления структур
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
типдеф структ Type Type;
|
|||
|
|
типдеф структ Node Node;
|
|||
|
|
типдеф структ Member Member;
|
|||
|
|
типдеф структ Relocation Relocation;
|
|||
|
|
типдеф структ Hideset Hideset;
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль strings.c - Работа со строками
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
типдеф структ {
|
|||
|
|
символ **data; // Массив строк
|
|||
|
|
цел capacity; // Вместимость
|
|||
|
|
цел len; // Текущее количество
|
|||
|
|
} МассивСтрок;
|
|||
|
|
|
|||
|
|
пусто массив_строк_добавить(МассивСтрок *массив, символ *строка);
|
|||
|
|
символ *формат(символ *строка_формата, ...) __attribute__((format(printf, 1, 2)));
|
|||
|
|
пусто массив_строк_освободить(МассивСтрок *массив);
|
|||
|
|
пусто массив_строк_очистить(МассивСтрок *массив);
|
|||
|
|
символ *массив_строк_получить(конст МассивСтрок *массив, size_t инд);
|
|||
|
|
бул массив_строк_установить(МассивСтрок *массив, size_t инд, символ *строка);
|
|||
|
|
бул массив_строк_вставить(МассивСтрок *массив, size_t поз, символ *строка);
|
|||
|
|
бул массив_строк_удалить(МассивСтрок *массив, size_t инд);
|
|||
|
|
ssize_t массив_строк_найти(конст МассивСтрок *массив, конст символ *строка);
|
|||
|
|
бул массив_строк_содержит(конст МассивСтрок *массив, конст символ *строка);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль tokenize.c - Лексический анализ
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
типдеф переч {
|
|||
|
|
TK_IDENT, // Идентификаторы
|
|||
|
|
TK_PUNCT, // Пунктуаторы
|
|||
|
|
TK_KEYWORD, // Ключевые слова
|
|||
|
|
TK_STR, // Строковые литералы
|
|||
|
|
TK_NUM, // Числовые литералы
|
|||
|
|
TK_PP_NUM, // Препроцессорные числа
|
|||
|
|
TK_EOF, // Маркер конца файла
|
|||
|
|
} TokenKind;
|
|||
|
|
|
|||
|
|
типдеф структ {
|
|||
|
|
символ *name; // Имя файла
|
|||
|
|
цел file_no; // Номер файла
|
|||
|
|
символ *contents; // Содержимое файла
|
|||
|
|
символ *display_name; // Отображаемое имя (для #строка)
|
|||
|
|
цел line_delta; // Смещение строк
|
|||
|
|
} File;
|
|||
|
|
|
|||
|
|
типдеф структ Token Token;
|
|||
|
|
структ Token {
|
|||
|
|
TokenKind kind; // Тип токена
|
|||
|
|
Token *next; // Следующий токен
|
|||
|
|
int64_t val; // Значение для TK_NUM
|
|||
|
|
длин двойн fval; // Значение с плавающей точкой для TK_NUM
|
|||
|
|
символ *loc; // Позиция в исходном коде
|
|||
|
|
цел len; // Длина токена
|
|||
|
|
Type *ty; // Тип (для TK_NUM или TK_STR)
|
|||
|
|
символ *str; // Содержимое строкового литерала (с \0)
|
|||
|
|
|
|||
|
|
File *file; // Файл источника
|
|||
|
|
символ *filename; // Имя файла
|
|||
|
|
цел line_no; // Номер строки
|
|||
|
|
цел line_delta; // Смещение строки
|
|||
|
|
бул at_bol; // В начале строки
|
|||
|
|
бул has_space; // Есть пробел перед токеном
|
|||
|
|
Hideset *hideset; // Для раскрытия макросов
|
|||
|
|
Token *origin; // Исходный токен (если раскрыт из макроса)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// Ошибки и предупреждения
|
|||
|
|
noreturn пусто error(символ *format, ...) __attribute__((format(printf, 1, 2)));
|
|||
|
|
noreturn пусто error_at(символ *location, символ *format, ...) __attribute__((format(printf, 2, 3)));
|
|||
|
|
noreturn пусто error_tok(Token *token, символ *format, ...) __attribute__((format(printf, 2, 3)));
|
|||
|
|
пусто warn_tok(Token *token, символ *format, ...) __attribute__((format(printf, 2, 3)));
|
|||
|
|
|
|||
|
|
// Работа с токенами
|
|||
|
|
бул equal(Token *token, символ *operator);
|
|||
|
|
Token *skip(Token *token, символ *operator);
|
|||
|
|
бул consume(Token **rest, Token *token, символ *str);
|
|||
|
|
пусто convert_pp_tokens(Token *tokens);
|
|||
|
|
|
|||
|
|
// Работа с файлами
|
|||
|
|
File **get_input_files(пусто);
|
|||
|
|
File *new_file(символ *name, цел file_no, символ *contents);
|
|||
|
|
|
|||
|
|
// Токенизация
|
|||
|
|
Token *tokenize_string_literal(Token *token, Type *base_type);
|
|||
|
|
Token *tokenize(File *file);
|
|||
|
|
Token *tokenize_file(символ *filename);
|
|||
|
|
|
|||
|
|
#определить unreachable() error("internal error at %s:%d", __ФАЙЛ__, __ЛИНИЯ__)
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль preprocess.c - Препроцессинг
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
символ *search_include_paths(символ *filename);
|
|||
|
|
пусто init_macros(пусто);
|
|||
|
|
пусто define_macro(символ *name, символ *value);
|
|||
|
|
пусто undef_macro(символ *name);
|
|||
|
|
Token *preprocess(Token *tokens);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль parse.c - Синтаксический анализ
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
типдеф структ Obj Obj;
|
|||
|
|
структ Obj {
|
|||
|
|
Obj *next;
|
|||
|
|
символ *name; // Имя переменной
|
|||
|
|
Type *ty; // Тип
|
|||
|
|
Token *tok; // Представительный токен
|
|||
|
|
бул is_local; // Локальная или глобальная
|
|||
|
|
цел align; // Выравнивание
|
|||
|
|
|
|||
|
|
// Локальные переменные
|
|||
|
|
цел offset; // Смещение в стеке
|
|||
|
|
|
|||
|
|
// Глобальные переменные или функции
|
|||
|
|
бул is_function; // Это функция
|
|||
|
|
бул is_definition; // Это определение
|
|||
|
|
бул is_static; // Статическая
|
|||
|
|
|
|||
|
|
// Глобальные переменные
|
|||
|
|
бул is_tentative; // Предварительное объявление
|
|||
|
|
бул is_tls; // TLS переменная
|
|||
|
|
символ *init_data; // Данные инициализации
|
|||
|
|
Relocation *rel; // Релокации
|
|||
|
|
|
|||
|
|
// Функции
|
|||
|
|
бул is_inline; // Inline функция
|
|||
|
|
Obj *params; // Параметры
|
|||
|
|
Node *body; // Тело функции
|
|||
|
|
Obj *locals; // Локальные переменные
|
|||
|
|
Obj *va_area; // Область для va_list
|
|||
|
|
Obj *alloca_bottom; // Нижняя граница alloca
|
|||
|
|
цел stack_size; // Размер стека
|
|||
|
|
|
|||
|
|
// Статические inline функции
|
|||
|
|
бул is_live; // Используется
|
|||
|
|
бул is_root; // Корневая
|
|||
|
|
МассивСтрок refs; // Ссылки (было StringArray)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
типдеф структ Relocation Relocation;
|
|||
|
|
структ Relocation {
|
|||
|
|
Relocation *next;
|
|||
|
|
цел offset; // Смещение
|
|||
|
|
символ **label; // Метка
|
|||
|
|
длин addend; // Добавка
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
типдеф переч {
|
|||
|
|
ND_NULL_EXPR, // Пустое выражение
|
|||
|
|
ND_ADD, // Сложение
|
|||
|
|
ND_SUB, // Вычитание
|
|||
|
|
ND_MUL, // Умножение
|
|||
|
|
ND_DIV, // Деление
|
|||
|
|
ND_NEG, // Унарный минус
|
|||
|
|
ND_MOD, // Остаток от деления
|
|||
|
|
ND_BITAND, // Побитовое И
|
|||
|
|
ND_BITOR, // Побитовое ИЛИ
|
|||
|
|
ND_BITXOR, // Побитовое исключающее ИЛИ
|
|||
|
|
ND_SHL, // Сдвиг влево
|
|||
|
|
ND_SHR, // Сдвиг вправо
|
|||
|
|
ND_EQ, // Равно
|
|||
|
|
ND_NE, // Не равно
|
|||
|
|
ND_LT, // Меньше
|
|||
|
|
ND_LE, // Меньше или равно
|
|||
|
|
ND_ASSIGN, // Присваивание
|
|||
|
|
ND_COND, // Условный оператор ?:
|
|||
|
|
ND_COMMA, // Оператор запятая
|
|||
|
|
ND_MEMBER, // Доступ к члену структуры
|
|||
|
|
ND_ADDR, // Взятие адреса
|
|||
|
|
ND_DEREF, // Разыменование
|
|||
|
|
ND_NOT, // Логическое НЕ
|
|||
|
|
ND_BITNOT, // Побитовое НЕ
|
|||
|
|
ND_LOGAND, // Логическое И
|
|||
|
|
ND_LOGOR, // Логическое ИЛИ
|
|||
|
|
ND_RETURN, // возврат
|
|||
|
|
ND_IF, // если
|
|||
|
|
ND_FOR, // для или пока
|
|||
|
|
ND_DO, // делай-пока
|
|||
|
|
ND_SWITCH, // выбор
|
|||
|
|
ND_CASE, // случай
|
|||
|
|
ND_BLOCK, // Блок { ... }
|
|||
|
|
ND_GOTO, // перейти
|
|||
|
|
ND_GOTO_EXPR, // перейти с выражением (GNU)
|
|||
|
|
ND_LABEL, // Метка
|
|||
|
|
ND_LABEL_VAL, // Метка как значение (GNU)
|
|||
|
|
ND_FUNCALL, // Вызов функции
|
|||
|
|
ND_EXPR_STMT, // Выражение-инструкция
|
|||
|
|
ND_STMT_EXPR, // Инструкция-выражение (GNU)
|
|||
|
|
ND_VAR, // Переменная
|
|||
|
|
ND_VLA_PTR, // VLA дескриптор
|
|||
|
|
ND_NUM, // Число
|
|||
|
|
ND_CAST, // Приведение типа
|
|||
|
|
ND_MEMZERO, // Обнуление стековой переменной
|
|||
|
|
ND_ASM, // асм
|
|||
|
|
ND_CAS, // Атомарная compare-and-swap
|
|||
|
|
ND_EXCH, // Атомарный обмен
|
|||
|
|
} NodeKind;
|
|||
|
|
|
|||
|
|
структ Node {
|
|||
|
|
NodeKind kind; // Тип узла
|
|||
|
|
Node *next; // Следующий узел
|
|||
|
|
Type *ty; // Тип
|
|||
|
|
Token *tok; // Представительный токен
|
|||
|
|
|
|||
|
|
Node *lhs; // Левый операнд
|
|||
|
|
Node *rhs; // Правый операнд
|
|||
|
|
|
|||
|
|
// Условные и циклические конструкции
|
|||
|
|
Node *cond; // Условие
|
|||
|
|
Node *then; // Ветвь then
|
|||
|
|
Node *els; // Ветвь else
|
|||
|
|
Node *init; // Инициализация
|
|||
|
|
Node *inc; // Инкремент
|
|||
|
|
|
|||
|
|
// Метки для прерви и продолжи
|
|||
|
|
символ *brk_label;
|
|||
|
|
символ *cont_label;
|
|||
|
|
|
|||
|
|
// Блок или выражение-инструкция
|
|||
|
|
Node *body;
|
|||
|
|
|
|||
|
|
// Доступ к члену структуры
|
|||
|
|
Member *member;
|
|||
|
|
|
|||
|
|
// Вызов функции
|
|||
|
|
Type *func_ty; // Тип функции
|
|||
|
|
Node *args; // Аргументы
|
|||
|
|
бул pass_by_stack; // Передача через стек
|
|||
|
|
Obj *ret_buffer; // Буфер для возврата
|
|||
|
|
|
|||
|
|
// перейти, метки и метки как значения
|
|||
|
|
символ *label;
|
|||
|
|
символ *unique_label;
|
|||
|
|
Node *goto_next;
|
|||
|
|
|
|||
|
|
// выбор
|
|||
|
|
Node *case_next;
|
|||
|
|
Node *default_case;
|
|||
|
|
|
|||
|
|
// случай
|
|||
|
|
длин begin;
|
|||
|
|
длин end;
|
|||
|
|
|
|||
|
|
// асм
|
|||
|
|
символ *asm_str;
|
|||
|
|
|
|||
|
|
// Атомарные операции
|
|||
|
|
Node *cas_addr;
|
|||
|
|
Node *cas_old;
|
|||
|
|
Node *cas_new;
|
|||
|
|
Obj *atomic_addr;
|
|||
|
|
Node *atomic_expr;
|
|||
|
|
|
|||
|
|
// Переменная
|
|||
|
|
Obj *var;
|
|||
|
|
|
|||
|
|
// Числовой литерал
|
|||
|
|
int64_t val;
|
|||
|
|
длин двойн fval;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Node *new_cast(Node *expression, Type *type);
|
|||
|
|
int64_t const_expr(Token **rest, Token *token);
|
|||
|
|
Obj *parse(Token *tokens);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль type.c - Система типов
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
типдеф переч {
|
|||
|
|
TY_VOID, // пусто
|
|||
|
|
TY_BOOL, // _Bool
|
|||
|
|
TY_CHAR, // символ
|
|||
|
|
TY_SHORT, // корот
|
|||
|
|
TY_INT, // цел
|
|||
|
|
TY_LONG, // длин
|
|||
|
|
TY_FLOAT, // плав
|
|||
|
|
TY_DOUBLE, // двойн
|
|||
|
|
TY_LDOUBLE, // длин двойн
|
|||
|
|
TY_ENUM, // переч
|
|||
|
|
TY_PTR, // указатель
|
|||
|
|
TY_FUNC, // функция
|
|||
|
|
TY_ARRAY, // массив
|
|||
|
|
TY_VLA, // массив переменной длины
|
|||
|
|
TY_STRUCT, // структ
|
|||
|
|
TY_UNION, // объед
|
|||
|
|
} TypeKind;
|
|||
|
|
|
|||
|
|
структ Type {
|
|||
|
|
TypeKind kind; // Тип
|
|||
|
|
цел size; // Размер в байтах
|
|||
|
|
цел align; // Выравнивание
|
|||
|
|
бул is_unsigned; // Беззнаковый
|
|||
|
|
бул is_atomic; // _Atomic
|
|||
|
|
Type *origin; // Исходный тип (для типдеф)
|
|||
|
|
|
|||
|
|
// Для указателей и массивов
|
|||
|
|
Type *base;
|
|||
|
|
|
|||
|
|
// Имя (для объявлений)
|
|||
|
|
Token *name;
|
|||
|
|
Token *name_pos;
|
|||
|
|
|
|||
|
|
// Для массивов
|
|||
|
|
цел array_len; // Длина массива
|
|||
|
|
Node *vla_len; // Длина VLA (выражение)
|
|||
|
|
Obj *vla_size; // Размер VLA
|
|||
|
|
|
|||
|
|
// Для структур/объединений
|
|||
|
|
Member *members;
|
|||
|
|
бул is_flexible; // Гибкий массив
|
|||
|
|
бул is_packed; // Упакованный
|
|||
|
|
|
|||
|
|
// Для функций
|
|||
|
|
Type *return_ty; // Возвращаемый тип
|
|||
|
|
Type *params; // Параметры
|
|||
|
|
бул is_variadic; // Функция с переменным числом аргументов
|
|||
|
|
Type *next; // Следующий параметр
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
структ Member {
|
|||
|
|
Member *next;
|
|||
|
|
Type *ty;
|
|||
|
|
Token *tok; // Для сообщений об ошибках
|
|||
|
|
Token *name;
|
|||
|
|
цел idx; // Индекс
|
|||
|
|
цел align; // Выравнивание
|
|||
|
|
цел offset; // Смещение
|
|||
|
|
|
|||
|
|
// Битовые поля
|
|||
|
|
бул is_bitfield;
|
|||
|
|
цел bit_offset;
|
|||
|
|
цел bit_width;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// Базовые типы
|
|||
|
|
внеш Type *ty_void;
|
|||
|
|
внеш Type *ty_bool;
|
|||
|
|
внеш Type *ty_char;
|
|||
|
|
внеш Type *ty_short;
|
|||
|
|
внеш Type *ty_int;
|
|||
|
|
внеш Type *ty_long;
|
|||
|
|
внеш Type *ty_uchar;
|
|||
|
|
внеш Type *ty_ushort;
|
|||
|
|
внеш Type *ty_uint;
|
|||
|
|
внеш Type *ty_ulong;
|
|||
|
|
внеш Type *ty_float;
|
|||
|
|
внеш Type *ty_double;
|
|||
|
|
внеш Type *ty_ldouble;
|
|||
|
|
|
|||
|
|
// Проверка типов
|
|||
|
|
бул is_integer(Type *type);
|
|||
|
|
бул is_flonum(Type *type);
|
|||
|
|
бул is_numeric(Type *type);
|
|||
|
|
бул is_compatible(Type *first, Type *second);
|
|||
|
|
|
|||
|
|
// Создание типов
|
|||
|
|
Type *copy_type(Type *original);
|
|||
|
|
Type *pointer_to(Type *base_type);
|
|||
|
|
Type *func_type(Type *return_type);
|
|||
|
|
Type *array_of(Type *base_type, цел size);
|
|||
|
|
Type *vla_of(Type *base_type, Node *expr);
|
|||
|
|
Type *enum_type(пусто);
|
|||
|
|
Type *struct_type(пусто);
|
|||
|
|
|
|||
|
|
// Вывод типов
|
|||
|
|
пусто add_type(Node *node);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль codegen.c - Генерация кода
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
пусто codegen(Obj *program, FILE *output);
|
|||
|
|
цел align_to(цел value, цел alignment);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль unicode.c - Поддержка Unicode
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
цел encode_utf8(символ *buffer, uint32_t code_point);
|
|||
|
|
uint32_t decode_utf8(символ **new_position, символ *input);
|
|||
|
|
бул is_ident1(uint32_t code_point);
|
|||
|
|
бул is_ident2(uint32_t code_point);
|
|||
|
|
цел display_width(символ *text, цел length);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль hashmap.c - Хеш-таблица
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
типдеф структ {
|
|||
|
|
символ *ключ; // Ключ
|
|||
|
|
цел длина_ключа; // Длина ключа
|
|||
|
|
пусто *значение; // Значение
|
|||
|
|
} ЗаписьХеша;
|
|||
|
|
|
|||
|
|
типдеф структ {
|
|||
|
|
ЗаписьХеша *корзины; // Массив корзин
|
|||
|
|
цел вместимость; // Вместимость
|
|||
|
|
цел использовано; // Использовано
|
|||
|
|
} ХешТаблица;
|
|||
|
|
|
|||
|
|
пусто *хеш_получить(ХешТаблица *таблица, символ *ключ);
|
|||
|
|
пусто *хеш_получить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа);
|
|||
|
|
пусто хеш_вставить(ХешТаблица *таблица, символ *ключ, пусто *значение);
|
|||
|
|
пусто хеш_вставить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа, пусто *значение);
|
|||
|
|
пусто хеш_удалить(ХешТаблица *таблица, символ *ключ);
|
|||
|
|
пусто хеш_удалить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа);
|
|||
|
|
пусто хеш_тест(пусто);
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// Модуль main.c - Основная программа
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
бул file_exists(символ *path);
|
|||
|
|
|
|||
|
|
внеш МассивСтрок include_paths; // было StringArray
|
|||
|
|
внеш бул opt_fpic;
|
|||
|
|
внеш бул opt_fcommon;
|
|||
|
|
внеш символ *base_file;
|
|||
|
|
|
|||
|
|
#конецесли // RUSI_H
|