Symbol Tables and related issues

Первые впечатления от символьных таблиц

Если я что-то понял неправильно, поправьте.

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

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.