Первые впечатления от символьных таблиц
Если я что-то понял неправильно, поправьте.
0. Символы (Symbols) суть представления обрабатываемых сущностей(глобальные/локальные функции/переменные) анализируемого кода(раз уж мы находимся внутри компилятора), они создаются, когда нам нужно их обработать. Символы имеют свойства: тип, область определения(глобальные/внешние/локальные/…) и др. Каждый символ принадлежит одной таблице (ассоциируется с ней при вызове конструктора), или с большим числом с помощью прокси.
1. Символьные таблицы используются в сопряжении с Отображениями символьных таблиц (Symbol Table Maps). При создании символьной таблицы автоматически создается отображение LocalIDMap (и что-то еще), позже можно добавлять свои собственные. Отображения используются для последующего поиска элементов по заданному признаку. Отображения могут выражать полные/частичные (можно ли с помощью него обратиться ко всему множеству символов Таблицы или к подмножеству) и выражать отношения один-к-одному/один-ко-многим (пример: NameMap, которая возвращает все Символы с данным именем; их, очевидно, может быть много)
2. Таблицы образуют иерархию с общим корнем. Это позволяет производить поиск Символов по всей иерархии дерева.
3. Прокси (букв. "заместители"). Применяются, в частности, для того, чтобы один символ мог содержаться в более чем одной таблице. Одно из использований этого - создание символа для статической переменной, находящейся в функции. В таком случае она имеет представления как в глобальной области видимости, так и в области видимости внутри функции.
Первые впечатления от Phoenix
1. Либо я что-то не понял в стандарте С++, либо Майкрософт использует непортабельный вариант языка, но в примерах встречаются объявления вида
Type ^ pointer_variable;
Как оказалось, эта галочка создает managed pointer, т.е. указатель, память для которого выделяется/освобождается отдельным менеджером. Вроде удобно, но непривычно, да и мой знакомый тут с пеной у рта доказывает, что такое будет работать в 15 раз медленнее. Интересно, нам придется их использовать?
2. Я не совсем понял, откуда в примерах берется определение переменной Phx, методы которой используются по всему коду. Нет ни одного хэдера, в котором что-либо включалось. Очевидно, всё указано в свойствах проекта. Но при попытке просмотра этой информации у меня падает VS… Если кто сможет узнать, как это работает, то напишите.
Что интерсного я нашел в документации и RDK Samples
В основном информацию я брал из Phoenix Documentation.chm, глава Inside Phoenix->Core Components->Symbol System. Интересно также почитать Reference, но там объем огромный, руки еще не дошли. Интересную вещь нашел среди RDK Samples: AddNop-plug-in и AddNop-tool. Там показано, как с помощью Феникса вставлять инструкции в генерируемый код.
//GGG
Было бы интереснее и понятнее для остальных, если бы ты добавил сюда примеры.
Например:
=====
foo.c:
статические и внешние глобальные объекты(переменные, массивы, структуры)
код функции
{
локальные объекты
}
=====
как эти объекты выглядят в символьной таблице
=====
//dimstar
Еще немного информации о символьных таблицах.
Ко всемы выше сказанному я хотел бы добавить следующее.
При компиляции для каждой функции, исходного файла создаются Unit'ы. Существуют следующие виды: AssemblyUnit, DataUnit, FuncUnit, GlobalUnit, ModuleUnit, PEModuleUnit. С каждым модулем связывается своя уникальная символьная таблица. К ней можно обращаться по средством члена соответствующего класса SymTable.
Пример.
Я сделал маленький пример, который пока не делает ничего полезного, кроме того, что выводить таблицы.
При создании я использовал шаблон c2phase из VS, фаза вставляется после SimpleRvd(куда ее лучше вставлять я не прошарил).
Привожу только функция Execute класса Phase.
void
Phase::Execute
(
Phx::Unit ^ unit
)
{
static int flag=0;
if (!flag) // глобальную таблицу выводим только раз, для этого ставим флаг//
{
Phx::ModuleUnit ^ moduleUnit = unit->ParentModuleUnit; //получаем указатель на ModuleUnit,в нем содержится//
//глобальная таблица для этого модуля(файла)//
if (moduleUnit == nullptr)
{
return;
}
moduleUnit->SymTable->Dump(); //распечатываем ее//
flag = 1;
}
//еще надо вывести локальные таблицы функций//
//такие модули называются FuncUnit//
if (!unit->IsFuncUnit) //представляет ли данный Unit функцию//
{
return;
}
Phx::FuncUnit ^ funcUnit = unit->AsFuncUnit; //заводим новую переменную, для FuncUnit//
//AsFuncUnit преобразовывает к типу Phx::FuncUnit//
if (funcUnit->SymTable == nullptr)
{
Phx::Output::WriteLine(L"SymTable == nullptr");
return;
}
funcUnit->SymTable->Dump(); //печатаем таблицу//
}
Проверял я работу своей фазы на следующей программе.
#include <stdio.h>
float t100 = 100.78;
char *myStr = "this test program";
float f1(int * a, char b)
{
return (*a);
}
int *f2(char *str, int y)
{
for (int i = 0; i < y; i++)
{
printf(str);
}
return &y;
}
int main(int argc, char **argv)
{
int a = 10, b = 6;
double t10h56k66;
f1(&a, 'a');
f2("asd", a);
return argc;
}
Результат работы:
C:\PROGRA~1\PHXRDK~1\APPLIC~1\Tests\src\cpp>cl exam.cpp -d2 plugin:C:\Projects\SymTable\Debug\SymTable.dll
exam.cpp
exam.cpp(25) : warning C4172: returning address of local variable or temporary
Глобальная таблица, для всей программы
SymTable for Module exam.cpp
Max Local Id: 32 SymCount: 32
Maps:
ExternId Size 1024 Count 32
LocalId Size 1024 Count 32
Symbols:
Sect LocID=1 ExtID=1 .data
Sect LocID=2 ExtID=6 .tls$
Sect LocID=3 ExtID=2 .rdata
Sect LocID=4 ExtID=13 .CRT$
Sect LocID=5 ExtID=3 .bss
Sect LocID=6 ExtID=4 .text
Sect LocID=7 ExtID=5 .debug$S
Sect LocID=8 ExtID=18 .debug$T
Sect LocID=9 ExtID=17 .debug$F
Sect LocID=10 ExtID=7 .xdata$x
Sect LocID=11 ExtID=16 .sxdata
Const LocID=12 ExtID=2530 c:\program files\microsoft visual studio 8\vc\include\sal.h
Const LocID=13 ExtID=2531 c:\program files\microsoft visual studio 8\vc\include\vadefs.h
Const LocID=14 ExtID=2529 c:\program files\microsoft visual studio 8\vc\include\crtdefs.h
Const LocID=15 ExtID=2528 c:\program files\microsoft visual studio 8\vc\include\stdio.h
Const LocID=16 ExtID=3414 c:\program files\microsoft visual studio 8\vc\include\swprintf.inl
Const LocID=17 ExtID=32 c:\program files\phxrdk_may06\applications\tests\src\cpp\exam.cpp
GlobalVar LocID=18 ExtID=3669 $SG3669 : Func UnmgdArr[Aggr8]176
GlobalVar LocID=19 ExtID=3700 $SG3700 : Func UnmgdArr[Aggr8]32
Func LocID=20 ExtID=3683 ?f1@@YAMPAHD@Z : GlobalDef CDecl.Func()->(f32)
Func LocID=21 ExtID=3687 ?f2@@YAPAHPADH@Z : GlobalDef CDecl.Func()->(up32->unk)
Func LocID=22 ExtID=3695 _main : GlobalDef CDecl.Func()->(i32)
Func LocID=23 ExtID=3131 _fgetwc : GlobalRef CDecl.Func()->(u16)
Func LocID=24 ExtID=2772 _printf : GlobalRef CDecl.Func(…)->(i32)
Func LocID=25 ExtID=3351 vswprintf_c_l : GlobalRef CDecl.Func()->(i32)
GlobalVar LocID=26 ExtID=3680 ?asd1asdf3UMyStrucA : GlobalDef Aggr6528
Func LocID=27 ExtID=3404 __vswprintf : GlobalRef CDecl.Func()->(i32)
Func LocID=28 ExtID=2626 _iob_func : GlobalRef CDecl.Func()->(up32->unk)
Func LocID=29 ExtID=3136 _fputwc : GlobalRef CDecl.Func()->(u16)
GlobalVar LocID=30 ExtID=3667 ?t100@@3MA : GlobalDef f32
Func LocID=31 ExtID=3413 ___vswprintf_l : GlobalRef CDecl.Func()->(i32)
GlobalVar LocID=32 ExtID=3668 ?myStr@@3PADA : GlobalDef up32->unk
Функция f1
SymTable for Func ?f1@@YAMPAHD@Z (State: Mir)
Max Local Id: 272 SymCount: 4
Maps:
ExternId Size 64 Count 2
LocalId Size 64 Count 4
Symbols:
Scope LocID=267 ScopeSym267
LocalVar LocID=268 ExtID=3682 _b : Func i8
Scope LocID=269 ScopeSym269
LocalVar LocID=270 ExtID=3681 _a : Func up32->unk
Функция f2
SymTable for Func ?f2@@YAPAHPADH@Z (State: Mir)
Max Local Id: 275 SymCount: 6
Maps:
ExternId Size 64 Count 3
LocalId Size 64 Count 6
Symbols:
Scope LocID=267 ScopeSym267
LocalVar LocID=268 ExtID=3686 _y : Func i32
Scope LocID=269 ScopeSym269
LocalVar LocID=270 ExtID=3685 _str : Func up32->unk
LocalVar LocID=271 ExtID=3689 _i : Func i32
Scope LocID=272 ScopeSym272
Функция main
SymTable for Func _main (State: Mir)
Max Local Id: 278 SymCount: 10
Maps:
ExternId Size 64 Count 7
LocalId Size 64 Count 10
Symbols:
Scope LocID=267 ScopeSym267
LocalVar LocID=268 ExtID=3694 _argv : Func up32->unk
Scope LocID=269 ScopeSym269
LocalVar LocID=270 ExtID=3693 _argc : Func i32
LocalVar LocID=271 ExtID=3697 _a : Func i32
Scope LocID=272 ScopeSym272
LocalVar LocID=273 ExtID=3698 _b : Func i32
LocalVar LocID=274 ExtID=3699 _t10h56k66 : Func f64
NonLocalVar LocID=276 ExtID=3700 $SG3700 : Func UnmgdArr[Aggr8]32
NonLocalVar LocID=278 ExtID=3680 ?asd1asdf3UMyStrucA : GlobalDef Aggr6528
Это пока все, что я сделал.
//firt