компилятор ТСС. Tiny c compiler by Fabrice Bellard Описание алгоритмов
Скачать 191.99 Kb.
|
int t) Вызывается psym() static void asm_instr(void) Компилятор заврешается с ошибкой static Sym *label_push(Sym **ptop, int v, int flags) Получаем адрес символа с помощью sym_push2() В поле r полученного символа записываются преданные флаги. В мессиве table_ident берется элемент соответствующий переданному идентификатору. В переменную ps помещается адрес символа из поля sym_label найденного элемента Если адрес переданного сисвола отличается от global_label_stack Сдвигается цепочка символов, связывающая по полю prev_tok. При достижении нулевого значения. В этот всободный адрес помещатеся адрес символа, найденного в начале функции, этот же адрес возвражается в качестве результатат static Sym *label_find(int v) Переданный идернификатор метки умешьшается на TOK_IDENT Проверяется выход за границы идентификаторво Возвращается значение поля sym_label соостветствующего элемента массива table_ident[] static int is_label(void) Если текущий токен меньше TOK_UIDENT, функция завершается возвращая 0 Текущий токен сохраняется во временную переменную. Вызывается next() Если текущий токен равен ':', вызывается next(), возвращатеся сохраненный код токена. Если токен отличен от ':', вызывается unget_tok(last_tok), функция завершается возвращая 0 void gjmp_addr(int a) В переменную r помещается разность переданного адреса и указателя на данные и 2. Если полученное значение при отбрасывании страрших бит остается равной само себе, дважды вызывается g(), иначе вызывается oad() void ggoto(void) Вызывается gcall_or_jmp() Уменьшается цеопчка vtop static void indir(void) Если CType связанный с последней SValue не кодирует VT_PTR, проверяется кодирует ли он VT_FUNC. В этом случае функция завершатеся. Если ни то ни другое не кодируется, компилятор завершается с ошибкой Если поле r последней SValue содержит биты входящие в VT_LVAL и флаг nocode_wanted сброшен, вызывается gv() CType связанный с последней SValue обновляется значением расположенным по адресу полученному с при вызове pointed_type() Если биты полученного CType не кодируют VT_ARRAY и биты кодирующие простые типы не кодируют VT_FUNC, то в поле r последней SValue добавляются биты получаемые вызовом lvalue_type(), при этом если установлен флаг do_bounds_check, в этом поле устанавливается бит VT_MUSTBOUND void vstore(void) Во временную переменную ft сохраняются биты кодирующие тип предпоследней SValue Часть этих бит, кодирующая простые типы сохраняется во временную переменную dbt Во временную переменную sbt сохраняются биты кодирующие простые типы последней SValue Следующая обработка выполняется в следующих случаях: Если dbt кодирует VT_BYTE и при этом sbt кодирует VT_INT или VT_SHORT Если sbt кодирует VT_INT или dbt кодирует VT_SHORT Обработка заключается в том, что delayed_cast присваивается VT_MUSTCAST, биты кодирующие тип последней SValue обновляются битами ft входящими в VT_TYPE Если ft содержит бит VT_CONSTANT, выдается предупреждение. Если условия не выполняюся delayed_cast обнулятся, если ft не содержит бит VT_BITFIELD, вызывается gen_assign_cast() Если sbt кодирует VT_STRUCT, проверяется флаг nocode_wanted. Если он сброшен, происходит следующая обработка. Переменная size обновляется вызовом type_size(); Вызываются vpush_global_sym() и vpushv() Биты кодирующие тип последней SValue обновляются значением VT_INT Вызываются gaddrof() и vpushv(vtop - 2) Вызываются gaddrof(), vpushi(), gfunc_call(), vswap() и vpop() Если nocode_wanted установлен вызываются vswap() и vpop(); Если ft кодирует VT_BITFIELD В переменные bit_pos и bit_size записываются части ft содержащие позицию битового поля и его размер. В битах кодирующих тип предпоследней SValue сбрасываются биты входящие в VT_BITFIELD и все биты начиная от старшего и заканчивая битом с номером VT_STRUCT_SHIFT Вызываются gv_dup(), vswap(), vrott() и vdup(). Предпоследня SValue заменяется второй с конца. Вызываются gen_op('&'), vpushi(bit_pos), gen_op(TOK_SHL), vswap(), vpushi(), gen_op(), gen_op(), vstore(), vpop() Если sbt не кодирует VT_STRUCT и ft не кодирует VT_BITFIELD, проверяеся флаг nocode_wanted, если он установлен, происходит следующая обработка Переменной rc обновляется значением RC_INT Если ft проходит проверку is_float(), то rc обновляется значением RC_FLOAT; Переменная r обновляется вызовом gv() Если биты входящие в VT_VALMASK поля r предпоследней SValue содержит кодируют VT_LLOCAL происходит следующая обработка Переменая t обновляется вызовом get_reg() Биты кодирующие тип временной SValue обновляются значением. Биты r временной SValue обновляются побитовым ИЛИ VT_LOCAL и VT_LVAL Поле ul структуры CValue связанной с временной SValue обновляется значением соответствущего поля предпоследне SValue Вызывается load(), поле r предпоследней SValue обновляется значением t с установленным битом VT_LVAL Вызывается store(); Если биты ft кодирующие простые типы, кодируют VT_LLONG происходит следующая обработка. Вызывается vswap() Биты кодирующие тип последней SValue обновляются значением VT_INT; Вызываются gaddrof(), vpushi(), gen_op('+'); В поле r последней SValue устанавливается бит VT_LVAL Вызываются vswap()и store() Вызывается vswap() Уменьшается цепочка vtop В поле r последней SValue устанавливается биты delayed_cast static void label_pop(Sym **ptop, Sym *slast) Функция принимает в качестве параметра указатели на два символа, происходит обход от первого переданного до второго по полю prev. На каждом шаге происходит следующая обработка Поле если поле r теущего символа содержит LABEL_DECLARED, выводится предупреждение, если содержит LABEL_FORWARD, компилятор завершается с ошибкой. В остальных случаях, проверяется поле c, если оно содержит ненулевое значение, вызывается put_extern_sym() Из значения поля v вычитается TOK_IDENT. Полученное значение используется как индекс в массиве table_ident, полю sym_label соответствующего элемента присваивается значение поля prev_tok текущего символа. Вызывается sym_free() Указатель на первый символ передан в качестве указателя на указтель. Это позволяет в конце функции заменить указатель на первый символ вторым переданным указателем. static void sym_pop(Sym **ptop, Sym *b) Функция принимает в качестве параметра указатели на два символа, происходит обход от первого переданного до второго по полю prev. На каждом шаге происходит следующая обработка Значение поля v текущего символа сохраняется во временной переменной. Если это значение не содержит биты входящие в SYM_FIELD, и идентификатор структуры полученный отбрасыванием бит входящих в SYM_STRUCT меньше чем SYM_FIRST_ANOM, присходит следущая обработка: В переменной v обнуляются биты входящие в SYM_STRUCT, из полученного значения вычитается TOK_IDENT. Полученное значение используется как индекс в массиве table_ident. Адрес соответствующего элемента записывается в переменную ts Если переменная v содержит биты SYM_STRUCT, то ps обновляется адресом символа который указан в поле sym_struct найденного элемента. Если биты SYM_STRUCT не найдены, используется поле sym_identifier В адресу расположенному в ps записывается значение поля prev_tok текущего символа. Вызывается sym_free() Происходит переход к следующему символу. Указатель на первый символ передан в качестве указателя на указтель. Это позволяет в конце функции заменить указатель на первый символ вторым переданным указателем. static void gen_assign_cast(CType *dt) Адрес CType, связанного с последней SValue, сохраняется в переменной st. Поля кодирующие простые типы этой CType сохраняются в dbt, теже биты переданной CType сохраняются в sbt Если dt кодирует VT_CONSTANT происходит следующая обработка Выводится предупреждение. Происходит обработка dbt Если кодируется VT_PTR, происходит следующая обработка Если при проверке последней SValue с помощью is_null_pointer() получен ненулевой результат, происходит переход на метку type_ok Если при проверке sbt с помощью is_integer_btype() получен ненулевой результат, выводится предупреждение и происходит переход на метку type_ok В переменную type1 помещается результат вызова pointed_type() для dt Если sbt кодирует VT_FUNC, проверяется кодирует ли type1 тип отличный от VT_VOID, и is_compatible_types() для типа на который указывает dt возвращает нулевое значение. Чтобы получить этот тип вызывается pointed_type(). В этом случае происходит переход на метку error, в противном случае на метку type_ok Если sbt не кодирует VT_PTR, происходит переход на метку error В переменную type2 помещается результат вызова pointed_type() для st Если type1 и type2 не кодируют VT_VOID, происходит следующая обработка Типы, кодируемые type1и type2 сохраняются во временные переменные В битах, которые кодируют тип этих переменных, сбрасываются VT_UNSIGNED, VT_CONSTANT и VT_VOLATILE. Если is_compatible_types(), вызванная для этих CType возвращает ненулевое значение, выдается предупреждение. Если оба этих CType кодирую VT_CONSTANT или оба кодирую VT_VOLATILE, выдается предупреждение. Для VT_BYTE, VT_SHORT, VT_INT и VT_LLONG, проверяется, равна ли VT_PTR или VT_FUNC. В этом случае выдается предупреждение. Для VT_STRUCT. Во временные переменные сохраняются CType, адреса которых хранятся в dt и st. В битах, которые кодируют тип этих переменных, сбрасываются VT_CONSTANT и VT_VOLATILE. Если is_compatible_types(), вызванная для этих CType возвращает ненулевое значение, то для st и dt вызывается type_to_str(). Компилятор завершается с ошибкой, выводя полученное значение. Перед этой обработкой переменных st и dt расположена метка error. Вызывается gen_cast() перед этим вызовом расположена метка type_ok |