Skip to content

Созонов Илья. Лабораторная работа 3. Backend. Вариант 1. #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

sozozzya
Copy link

@sozozzya sozozzya commented May 6, 2025

No description provided.

Kuznetsov-Artyom and others added 30 commits February 14, 2025 07:49
1) Move resources
2) Add status build
Вариант 4.
Добавить к статическим, локальным,глобальным объектам и параметрам
функции
соответствующие префиксы (static_, local_, global_, param_).

> Код автоматически переименовывает переменные, добавляя префиксы, и
выводит изменённый исходный код.

**ExampleVisitor**: Просматривает объявления переменных (**VarDecl**),
параметров (**ParmVarDecl**) и выражений ссылок на объявления
(**DeclRefExpr**), добавляя к именам префиксы в зависимости от типа
переменной.

---------

Co-authored-by: Sergey <[email protected]>
This Clang plugin analyzes C++ user-defined types (classes/structs)
using LLVM/Clang's AST traversal capabilities.

### Functionality:
- Extracts class inheritance chains
- Lists fields with types/access modifiers
- Identifies methods with signatures, qualifiers (const/noexcept), and
special properties (virtual/override/pure)

### LLVM/Clang APIs Used:
- `RecursiveASTVisitor` for deep AST traversal
- `CXXRecordDecl` for class declarations
- `CXXBaseSpecifier` for inheritance info
- `FieldDecl`/`CXXMethodDecl` for member analysis

### Workflow:
- Registers as FrontendPlugin
- Traverses Translation Unit AST
- Filters implicit/compiler-generated elements
- Outputs structured type info via LLVM's raw_ostream
…-complr-tech#8)

Решение реализует плагин для Clang, который анализирует исходный код на
предмет неявных преобразований типов. Он использует RecursiveASTVisitor
для обхода абстрактного синтаксического дерева (AST) и отслеживает
преобразования типов в выражениях. Каждый случай неявного преобразования
фиксируется с указанием исходного и целевого типов, а также их порядка в
пределах функции. Результаты выводятся по функциям, где для каждого
преобразования указывается количество. Плагин сортирует и выводит
информацию о преобразованиях для каждого метода.
The task was to analyze user-defined classes and structures
(user-defined types)

For user-defined types, the base types are defined

The type and access modifier are defined for fields.

The methods are defined by the return type and the types of parameters
they accept, the access modifier, virtual, pure virtual, or override.

Implicitly created methods are ignored
…lr-tech#11)

Плагин выводит имя класса или структуры, указывает, является ли тип
структурой или классом, а также является ли он шаблонным, перечисляет
все поля и методы класса, указывая их имена, типы и спецификаторы
доступа, а для методов дополнительно выводит информацию о том, является
ли метод виртуальным, перегруженным оператором или чисто виртуальным.
При наличии базовых классов плагин выводит их имена и спецификаторы
доступа (public, protected, private).
…-tech#9)

**ПОСТАНОВКА ЗАДАЧИ**
Разработать Clang плагин с использованием AST для добавления префиксов к
переменным узлов
следующих типов: VarDecl, DeclRefExpr, ParmVarDecl. Плагин должен
успешно находить объявления переменных
,добавлять префиксы к ним и выводить изменённый код.

**ОПИСАНИЕ РЕШЕНИЯ**
Для обхода AST необходимо использовать стандартный шаблон Clang плагина,
указанный в файлах PR.
Перед обходом следует создать Rewriter - инструмент-модификатор кода
программы, который будет изменять префиксы переменных, в классе
FindNamedClassAction и затем передать в FindNamedClassConsumer для
использования в каждой Translation Unit. Далее в соответствующих
методах, начинающихся с Visit, обнаружить декларации переменных и
определить их область видимости: static, local, global и т.д После
обнаружения создаётся новый префикс и с помощью метода ReplaceText
Rewriter модифицируется исходный код.

**СПИСОК ИЗМЕНЕНИЙ**
- Переименована переменная класса Rewriter;
- Названия директорий л/р приведены в соответствие требованиям;
- Убран артефакт // в файле с плагином;
- Дублирование кода в файле с плагином значительно устранено;
- Тест усложнён: добавлены дополнительные CHECK;
- Нестрогая проверка строк изменена на строгую;
- Добавлены пустые строки в конец файлов с плагином и тестом;
- В контексте функции добавления префиксов теперь возвращается
спецзначение ;
в том случае, если не удалось определить область видимости переменной;
- Исключено дублирование обработки префиксов для параметров функции;
- Установлен правильный порядок проверок области видимости переменных;
- Обобщена обработка узлов VarDecl, DeclRefExpr, ParmVarDecl в одном
методе;
- Бесполезные методы убраны из кода;
…plr-tech#7)

Плагин обходит абстрактное синтаксическое дерево (AST) программы,
используя механизм `RecursiveASTVisitor`. Класс `ImplicitConvVisitor`
перехватывает узлы `ImplicitCastExpr`, соответствующие неявным
преобразованиям. Игнорируются преобразования, не влияющие на семантику
такие как `LValueToRValue`, `NoOp`, `FunctionToPointerDecay`. Для
каждого преобразования извлекаются исходный и целевой типы, а также
контекст — функция, где оно произошло. Статистика сохраняется в виде
отображения `[функция -> (тип_источник -> тип_цель) -> количество]`.
После обхода AST результаты выводятся в стандартный поток ошибок,
включая общее число преобразований.
…omplr-tech#13)

Clang плагин `CastCounter` реализует одноимённый класс, наследованный от
`RecursiveASTVisitor` и выполняющий обход AST, выявляя случаи неявного
приведения типов. В классе `CastCounter` реализованы методы:

- `VisitFunctionDecl`, получающий имя функции, в которую попали при
обходе;

- `VisitCXXConstructExpr`, проверяющий случаи, когда аргумент передаётся
в конструктор и вызывает преобразование

- `VisitImplicitCastExpr`, анализирующий неявные преобразования
(игнорирует LValueToRValue, FunctionToPointerDecay)

- `getResult` выводит информацию о найденных преобразованиях.

Информация о преобразованиях содержится в мапе `CastMap`. Класс
`CastCounterConsumer` управляет запуском обхода AST и вызывает
`getResult`. Класс `CastCounterAction` регистрирует плагин в компиляторе
Clang.

Тест для плагина выполнен согласно образцам `example`.
…mplr-tech#18)

Плагин ClangAST_4 для Clang автоматически добавляет префиксы (static_,
global_, local_, param_) к именам переменных и параметров функций, чтобы
обозначить их область видимости. Он использует RecursiveASTVisitor для
обхода AST и Rewriter для изменения кода. PrefixVisitor выполняет анализ
и переименование, PrefixConsumer запускает обработку, а PrefixAction
управляет работой плагина и выводит измененный код.
…mplr-tech#15)

Плагин анализирует пользовательский тип данных, определяя, обладает ли
структура наследованием, содержит ли поля и методы. При наличии
элементов выводится их описание: тип данных, уровень доступа, а также
характеристики методов — виртуальные, чисто виртуальные или
переопределенные.

---------

Co-authored-by: Arseniy Obolenskiy <[email protected]>
…ech#30)

Код реализует плагин для Clang, который анализирует неявные
преобразования типов в исходном коде. Он посещает функции и выражения,
такие как неявные преобразования, касты и конструкторы, чтобы
отслеживать, какие типы преобразуются друг в друга. Когда обнаруживается
преобразование типов, оно записывается в список. Плагин выводит отчет о
том, какие функции выполняют неявные преобразования типов, с указанием
исходного и целевого типов.
…omplr-tech#21)

Плагин использует возможности Clang для обхода абстрактного
синтаксического дерева (AST) и регистрирует все случаи неявных
преобразований, происходящих в коде. При каждом неявном преобразовании
плагин фиксирует типы, участвующие в преобразовании, и подсчитывает их
количество для каждой функции. Результаты анализа выводятся для каждой
функции, отображается имя и список неявных преобразований с
соответствующими количествами.
…omplr-tech#12)

Данный плагин выводит информацию о пользовательском типе данных:
является ли структура наследственной, имеет ли какие-либо поля и методы
и, если имеет, выводит информацию о них(тип данных, уровень доступа,
является ли метод виртуальным/чисто виртуальным/переопределенным)

---------

Co-authored-by: Kuznetsov-Artyom <[email protected]>
…-complr-tech#14)

Реализован Clang плагин, который добавляет к статическим, локальным,
глобальным объектам и параметрам функции
соответствующие префиксы (static_, local_, global_, param_). 

Класс PrefixVisitor обходит AST (Abstract Syntax Tree) с помощью
RecursiveASTVisitor и добавляет префиксы к переменным и параметрам в
зависимости от их типа, а также обновляет имена переменных в вызовах
функций, чтобы они соответствовали новым именам с префиксами.

**Используемые API LLVM/Clang:**

- RecursiveASTVisitor для обхода AST
- VarDecl для работы с переменными
- ParmVarDecl для работы с параметрами функций
- CallExpr для анализа вызовов функций
- Rewriter для модификации исходного кода

---------

Co-authored-by: Arseniy Obolenskiy <[email protected]>
Co-authored-by: Aleksey <[email protected]>
…omplr-tech#17)

Данный плагин проходит по параметрам функций и переменным и проверяет,
используются ли они. Если нет, то добавляет соответствующий атрибут

---------

Co-authored-by: Arseniy Obolenskiy <[email protected]>
…lr-tech#19)

## General
Реализован плагин для clang который работает с abstract syntax tree,
который строит clang во время frontend-analysis исходного кода.
## Specific
Наш плагин умеет различать пользовательские типы данных, анализировать
их и принтить их:
- Имена
- Struct или class
- Структуру наследования
- Поля
- - Модификаторы доступа
- - Типы
- Методы
- -Возвращаемое значение
- -Квалификаторы доступа
- -Являются ли методы 
- - - Виртуальными
- - - Чисто виртуальными
- - - Перегруженными
- - - Статическими

---------

Co-authored-by: Torcna <[email protected]>
Co-authored-by: Arseniy Obolenskiy <[email protected]>
…plr-tech#31)

Реализация плагина Clang, анализирующий исходный код C++ и подсчитывает
количество неявных преобразований типов (implicit casts) в функциях. Он
использует Clang AST (Abstract Syntax Tree) для обхода узлов и сбора
статистики. Не учитываются неявные преобразования укзателей функций. Для
тестирования плагина были написаны lit тесты.

---------

Co-authored-by: Arseniy <>
…NN-complr-tech#36)

Плагин обходит абстрактное синтаксическое дерево (AST) программы,
используя механизм `RecursiveASTVisitor`. Класс `ImplicitConvVisitor`
перехватывает узлы `ImplicitCastExpr`, соответствующие неявным
преобразованиям. Игнорируются преобразования, не влияющие на семантику
такие как `LValueToRValue`, `NoOp`, `FunctionToPointerDecay`. Для
каждого преобразования извлекаются исходный и целевой типы, а также
контекст — функция, где оно произошло. Статистика сохраняется в виде
отображения `[функция -> (тип_источник -> тип_цель) -> количество]`.
После обхода AST результаты выводятся в стандартный поток ошибок,
включая общее число преобразований.
revert: NN-complr-tech#29
Была проведена замена std::map на llvm:MapVector, так как
llvm::MapVector сохраняет порядок вставки функций в AST. Это
гарантирует, что при выводе функции будут перечислены в том же порядке,
в котором они встречались в исходном коде, что исключит дальнейшее
появление ошибок
…mplr-tech#32)

Реализован Clang-плагин, который автоматически добавляет префиксы к
именам переменных в исходном коде в зависимости от их области видимости.
Используя RecursiveASTVisitor, он обходит AST, находит объявления
переменных (VarDecl, ParmVarDecl) и ссылки на них (DeclRefExpr). Метод
determinePrefix определяет нужный префикс: global_, local_, static_,
param_. Rewriter переименовывает переменные в исходном коде.
PrefixConsumer запускает обход AST, а PrefixAction инициализирует
Rewriter и записывает изменения в выходной поток.

---------

Co-authored-by: Alexey-Solovev <[email protected]>
Co-authored-by: Kuznetsov-Artyom <[email protected]>
…omplr-tech#33)

Плагин использует возможности Clang для обхода абстрактного
синтаксического дерева (AST) и автоматического изменения исходного кода
на основе анализа структуры программы. Префиксы добавляются в процессе
обхода AST с помощью класса ExampleVisitor, который проверяет тип и
область видимости переменной. В зависимости от того, является ли
переменная локальной, статической, глобальной или параметром функции, к
её имени добавляется соответствующий префикс (local_, static_, global_,
param_). Изменения выполняются через clang::Rewriter, который заменяет
старые имена на новые в исходном коде.
…plr-tech#37)

Реализован плагин, который добавляет к именам статических, глобальных,
локальных переменных соответственно префиксы static_, global_, local_ и
к именам параметров функций - префикс param_.

Плагин изменяет имена не только при объявлении переменной, но и везде,
где эта переменная используется.
Также плагин может принимать при запуске два аргумента командной строки:
--help - выводит описание плагина и список аргументов, которые плагин
умеет принимать;
--no-log - отключает логирование каждого места, в котором прошло
изменение имени переменной или параметра.

---------

Co-authored-by: root <root@MSI>
Вариант 2 на compiler explorer:
https://compiler-explorer.com/z/P6z8G1M9x
Проходим по дереву с помощью recursive visitor. Как только попадаем в
объявление параметров функции или объявление переменной, то проверяем
используется переменная или нет, а также есть ли уже атрибут
[[maybe_unused]]. Если переменная не используется и атрибута еще нет, то
добавляем атрибут. Код переписывается с помощью интерфейса rewriter. В
конце берем готовый буфер из rewriter и перенаправляем его в вывод.
Тесты включают в себя проверку глобальной переменной, проверку
параметров функции и тела функции, а также переменной, уже помеченной
как Unused. Дополнительно реализован флаг --help, позволяющий узнать
подробнее про данный плагин.
DSolo03 and others added 20 commits March 20, 2025 14:07
…plr-tech#16)

Плагин обходит все переменные и параметры функций и если данная
переменная не используется, то помечает ее аттрибутом `maybe_unused`.
После этого, плагин обходит все функции, делая `dump` их AST.
Обход реализован двумя обходчиками: `UnusedVisitor` и `DumpVisitor`.
Сначала вызывается `UnusedVisitor`, который помечает переменные и
параметры функций, а затем вызывается `DumpVisitor` выводящий `dump` AST
для всех функций, для проверки наличия аттрибута `maybe_unused` при
помощи тестов.
…-tech#40)

This Clang plugin analyzes C++ classes and prints their inheritance,
fields, and methods.

1. **ClassInfoVisitor**

- Traverses the AST, finds class declarations, and checks their
definitions.
- Outputs the class name, base classes, fields, and methods.

**Processing methods:**

- **PrintBaseClassesInfo()** – prints the list of base classes.
- **PrintFieldsInfo()** – displays fields with their types and access
specifiers.
- **PrintMethodsInfo(**) – prints methods with their parameters, return
type, and specifiers (virtual, override, const).

2. **ClassInfoConsumer** – initiates AST traversal.

3. **ClassInfoAction** – registers the plugin in Clang.
…lr-tech#39)

Проверка неиспользуемых переменных, если такие имеются, выводится UNUSED
VAR
…r-tech#54)

Цель лабораторной работы: с помощью механизма обхода AST переименовать
переменные в соответствии со следующим правилом:
- для локальных переменных добавляется приставка `local_`
- для глобальных переменных добавляется приставка `global_`
- для статических переменных добавляется приставка `static_`
- для параметров функции добавляется приставка `param_`

Основной задействованный функционал:
- `VisitVarDecl` - обрабатывает объявления переменных
- - проверяет валидность имени переменной
- - конструирует новое имя
- - заменяет исходное имя на новое
- - сохраняет имя в `unordered_map` `rewrittenDecl`
- `VisitParmVarDecl `- обрабатывает объявления параметров функций
(аналогично `VisitVarDecl`)
- `VisitDeclRefExpr `- обрабатывает ссылки на переменные (заменяет на
соответствующее имя из `rewrittenDecl`)

---------

Signed-off-by: Mikhail Ivanov <[email protected]>
…plr-tech#51)

Плагин проходится по всем параметрам и переменным программы. Если
переменная нигде не используется, то она помечается флагом
[[maybe_unused]].

---------

Co-authored-by: m-ly4 <[email protected]>
…omplr-tech#57)

Решение реализует пасс для LLVM, который анализирует модуль и ищет
инструкции сложения (add). Если в модуле есть функция add, которая
принимает два аргумента с типами, совпадающими с типами операндов
инструкции add, то эта инструкция заменяется на вызов соответствующей
функции. Пасс проверяет наличие такой функции в модуле, а затем проходит
по всем функциям, исключая саму add, и ищет бинарные операторы сложения.
Когда такие операторы обнаружены, и их операнды соответствуют типам
аргументов функции add, они заменяются на вызов этой функции. В случае,
если функция add не найдена или типы не совпадают, исходная инструкция
остается неизменной.
This LLVM Pass optimizes floating point arithmetics in LLVM IR by
merging `fmul` and `fadd` instructions into `llvm.fmuladd` intrinsic.

### Functionality:
- Merge operations
- Dead code elimination: automatically removes `fmul` and `fadd`
instructions when they become unused
- Works with `float` and `double` data types

### LLVM APIs Used:
- `FunctionPass`: Analyzes and modifies functions within LLVM IR.
- `IRBuilder<>`: Constructs intrinsics and manages instruction
insertion.
- `BinaryOperator`: Identifies FAdd and FMul operations.
- `Intrinsic::fmuladd`: Generates the intrinsic.
- `PreservedAnalyses`: Tracks whether IR analyses remain valid after
transformations.

### Workflow:
1. Plugin Registration: Integrates with LLVM via `PassPlugin` for
compatibility with modern passmanager.
2. Basic Block Traversal: Iterates through all basic blocks in a
function.
3. Pattern Matching: Detects valid fmul+fadd patterns.
4. Intrinsic Replacement: Uses `IRBuilder` to create `llvm.fmuladd` and
replaces the original instructions.
5. Cleanup: Safely removes orphaned fmul and fadd instructions.
…tech#46)

Данный плагин для Clang анализирует исходный код на предмет неявных
преобразований типов. Он использует RecursiveASTVisitor для обхода AST.
Все случаи неявных преобразований фиксируются, сохраняя информацию об
исходном и целевом типах, а так же их количестве в пределах функции.
Результаты группируются по функциям и выводятся с общим числом
преобразований в коде.
…ech#60)

### [**ПОСТАНОВКА ЗАДАЧИ**]
Написать transform LLVM Pass, который должен выполнять следующие
оптимизации:
- Замена в некотором тестовом файле инструкций деления, где это
возможно,
   на инструкцию побитовый сдвиг вправо;

|_ОГРАНИЧЕНИЯ_|
Оптимизация применяется только в случае, если:

1. Побитовый сдвиг вправо согласно стандарту языка C++ применяется
только к
     целочисленным операндам;
2. Правый операнд, отвечающий за кол-во бит сдвига, неотрицательный;
3. Количество бит, на которое выполняется сдвиг, не превышает число бит
в двоичной записи левого операнда;

### [**ОПИСАНИЕ РЕШЕНИЯ**]

**СРЕДСТВА, ОПРЕДЕЛЯЮЩИЕ ИНТЕРФЕЙС PASS**

_Выбор подкласса PASS:_ FunctionPass Class Reference;
_Уровень оптимизации:_ BasicBlock Class Reference;
_Инструменты:_ IRBuilder;
_Структура данных для замены инструкций:_ SmallVector;

**АЛГОРИТМ ОБХОДА**

1. Создать два цикла: по базовым блокам функций и инструкциям этих
блоков;
2. В каждом блоке найти все инструкции деления, для которых возможна
замена
    на инструкцию побитовый сдвиг вправо и соблюдаются все ограничения;
3. Найденную инструкцию добавить в вектор для замены инструкций деления;
4. Выполнить замену инструкции деления на побитовый сдвиг с помощью
    конструктора IRBuilder. 

**РЕЗУЛЬТАТ**
Optimized IR

### СПИСОК ИСПРАВЛЕНИЙ

- Удалены артефакты в тестовом файле с расширением .cpp;
- Добавлены пустые строки в конец исходных файлов;
- endif() исключён из CMakeLists.txt для pass;
- Убрана директива using из .cpp файла с pass;
- Сгенерирован IR с удалением alloca, store, load инструкций;
- .cpp файл с тестом удалён; 
- std::vector заменён на оптимизированный вариант llvm::SmallVector;
…lr-tech#59)

Пасс анализирует LLVM IR, находя последовательности операций **fmul**
(умножение) и **fadd** (сложение). Если эти операции используются
вместе, он заменяет их одной инструкцией **llvm.fmuladd**, которая
выполняет умножение и сложение за один шаг. Это делает код более
эффективным.
…-tech#41)

Плагин анализирует абстрактное синтаксическое дерево (AST) программы с
использованием механизма RecursiveASTVisitor. Его основная задача
заключается в выявлении и подсчете неявных преобразований типов в коде.
Для этого применяется класс ImplicitCastVisitor, который перехватывает
узлы ImplicitCastExpr, соответствующие неявным преобразованиям типов.
При этом игнорируются преобразования, не оказывающие влияния на
семантику программы, такие как LValueToRValue, NoOp и
FunctionToPointerDecay. Для каждого обнаруженного преобразования
извлекаются исходный и целевой типы, а также контекст, в котором оно
произошло (например, функция).

---------

Co-authored-by: Arseniy Obolenskiy <[email protected]>
Co-authored-by: Kuznetsov-Artyom <[email protected]>
…ch#42)

Плагин который автоматически помечает неиспользуемые переменные и
параметры атрибутом [[maybe_unused]].
Плагин анализирует AST, находит неиспользуемые переменные (VarDecl) и
параметры функций (ParmVarDecl), после чего добавляет к ним атрибут
[[maybe_unused]] с помощью Rewriter.
Плагин для Clang, который анализирует неявные преобразования типов в
программах на C++. Он использует RecursiveASTVisitor для обхода
абстрактного синтаксического дерева (AST) и перехватывает узлы
ImplicitCastExpr, соответствующие неявным преобразованиям. Игнорируются
тривиальные преобразования, такие как LValueToRValue, NoOp и
FunctionToPointerDecay.

---------

Co-authored-by: Kuznetsov-Artyom <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.