diff --git a/.github/deadline.py b/.github/deadline.py index 0b3b8a44dbfe9..ca9a097e4b6b0 100644 --- a/.github/deadline.py +++ b/.github/deadline.py @@ -9,8 +9,8 @@ def main(): moscow_tz = ZoneInfo("Europe/Moscow") current_date = datetime.now(moscow_tz) deadline_date = { - "lab:clang": datetime(2025, 6, 1, hour=19, tzinfo=moscow_tz), - "lab:llvm ir": datetime(2025, 6, 1, hour=19, tzinfo=moscow_tz), + "lab:clang": datetime(2025, 3, 19, hour=19, tzinfo=moscow_tz), + "lab:llvm ir": datetime(2025, 4, 9, hour=19, tzinfo=moscow_tz), "lab:backend": datetime(2025, 6, 1, hour=19, tzinfo=moscow_tz), "lab:mlir": datetime(2025, 6, 1, hour=19, tzinfo=moscow_tz), } diff --git a/.github/labeler.yml b/.github/labeler.yml index 4201fd9ae4b57..ba181109ee6ca 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -12,5 +12,8 @@ tests: - "llvm/test/compiler-course/**" - "mlir/test/compiler-course/**" +docs: + - "README.md" + ci: - ".github/**" diff --git a/.github/workflows/compiler-course-build.yml b/.github/workflows/compiler-course-build.yml index e0d32823ada70..0454ac74c43da 100644 --- a/.github/workflows/compiler-course-build.yml +++ b/.github/workflows/compiler-course-build.yml @@ -1,6 +1,10 @@ name: Build LLVM on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: ${{ github.ref != 'refs/heads/course-spring-2025' && github.event_name != 'merge_group' && !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} + jobs: ubuntu-gcc-build: runs-on: ubuntu-latest @@ -19,8 +23,9 @@ jobs: - name: Setup ccache uses: hendrikmuhs/ccache-action@v1.2 with: - max-size: 500M - key: ccache-${{ github.job }} + key: ${{ runner.os }} + create-symlink: true + max-size: 1.5G - name: Build run: | cmake -S llvm -B build \ @@ -54,8 +59,9 @@ jobs: - name: Setup ccache uses: hendrikmuhs/ccache-action@v1.2 with: - max-size: 500M - key: ccache-${{ github.job }} + key: ${{ runner.os }} + create-symlink: true + max-size: 1.5G - name: Build run: | cmake -S llvm -B build \ diff --git a/.github/workflows/compiler-course-tidy.yml b/.github/workflows/compiler-course-tidy.yml index 7e0bf5a963d5f..712e9bfb9744f 100644 --- a/.github/workflows/compiler-course-tidy.yml +++ b/.github/workflows/compiler-course-tidy.yml @@ -6,12 +6,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Install clang-format run: | sudo apt-get install -y clang-format - name: Run clang-format run: | - git-clang-format --diff `git merge-base ${GITHUB_SHA} ${GITHUB_BASE_REF}` + git-clang-format --diff `git merge-base ${GITHUB_SHA} origin/${GITHUB_BASE_REF}` ${GITHUB_SHA} 2>&1 | tee log.txt + exit `grep -c diff log.txt` clang-tidy: runs-on: ubuntu-latest steps: @@ -20,10 +23,13 @@ jobs: submodules: recursive - name: Update submodules run: git submodule update --init --recursive - - name: ccache + + - name: Setup ccache uses: hendrikmuhs/ccache-action@v1.2 with: - key: ${{ github.job }} + key: ${{ runner.os }} + create-symlink: true + max-size: 1.5G - uses: aobolensk/clang-tidy-review@v0.20.1-patch-clang-tidy-19 id: review with: diff --git a/README.md b/README.md index 616afe0927d2e..bcb15276d6bba 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,34 @@ # Compiler course 2025 -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/llvm/llvm-project/badge)](https://securityscorecards.dev/viewer/?uri=github.com/llvm/llvm-project) -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8273/badge)](https://www.bestpractices.dev/projects/8273) -[![libc++](https://github.com/llvm/llvm-project/actions/workflows/libcxx-build-and-test.yaml/badge.svg?branch=main&event=schedule)](https://github.com/llvm/llvm-project/actions/workflows/libcxx-build-and-test.yaml?query=event%3Aschedule) +[![Build LLVM](https://github.com/NN-complr-tech/compiler-course-2025/actions/workflows/compiler-course-build.yml/badge.svg)](https://github.com/NN-complr-tech/compiler-course-2025/actions/workflows/compiler-course-build.yml) + +# Resources +- [Telegram сhat][chat] +- [Telegram сhannel][channel] +- [Tasks and results][results] +- Materials + - [Lecture recordings][recording] + - [Lecture presentations][lecture] + - [LLVM][llvm] + - [MLIR][mlir] + - [Clang][clang] + - [FileCheck][filecheck] + - [Official YouTube channel LLVM][youtube_llvm] + + + +[results]: https://docs.google.com/spreadsheets/d/1LiZ5FMd5t61yoGdnpANTFpzqtKD_ejtvLl1cHKZxvXQ/edit?usp=sharing + +[channel]: https://t.me/+TPntKPD8z0E3OWJi +[chat]: https://t.me/+JG3n1jeSAiIxZjMy + +[recording]: https://disk.yandex.ru/d/52gu5vJTSt1VFg +[lecture]: https://github.com/NN-complr-tech/Complr-course-lectures +[llvm]: https://llvm.org/ +[mlir]: https://mlir.llvm.org/ +[clang]: https://clang.llvm.org/ +[filecheck]: https://llvm.org/docs/CommandGuide/FileCheck.html +[youtube_llvm]: https://www.youtube.com/@LLVMPROJ # What is LLVM? LLLVM is a set of compiler and toolchain technologies that can be used to develop a frontend for any programming language and a backend for any instruction set architecture. LLVM is designed around a language-independent intermediate representation (IR) that serves as a portable, high-level assembly language that can be optimized with a variety of transformations over multiple passes. The name LLVM originally stood for Low Level Virtual Machine, though the project has expanded and the name is no longer officially an initialism. @@ -27,8 +53,8 @@ Recommended OS - Linux (WSL). 1. Create fork this repository 2. Clone local fork ```bash -git clone https://github.com//llvm.git -cd llvm/ +git clone https://github.com//compiler-course-2025.git +cd compiler-course-2025/ git checkout -b ``` @@ -105,26 +131,3 @@ For one test ```bash ./build/bin/llvm-lit -v /path/to/test_file ``` -# 6. Resources -- [Telegram сhat][chat] -- [Telegram сhannel][channel] -- [Tasks and results][results] -- Materials - - [Lectures][lecture] - - [LLVM][llvm] - - [MLIR][mlir] - - [Clang][clang] - - [Official YouTube channel LLVM][youtube_llvm] - - - -[results]: https://docs.google.com/spreadsheets/d/1LiZ5FMd5t61yoGdnpANTFpzqtKD_ejtvLl1cHKZxvXQ/edit?usp=sharing - -[channel]: https://t.me/+TPntKPD8z0E3OWJi -[chat]: https://t.me/+JG3n1jeSAiIxZjMy - -[lecture]: https://github.com/NN-complr-tech/Complr-course-lectures -[llvm]: https://llvm.org/ -[mlir]: https://mlir.llvm.org/ -[clang]: https://clang.llvm.org/ -[youtube_llvm]: https://www.youtube.com/@LLVMPROJ diff --git a/clang/compiler-course/Kholin_K_prefixes/CMakeLists.txt b/clang/compiler-course/Kholin_K_prefixes/CMakeLists.txt new file mode 100644 index 0000000000000..b93f2b11ac933 --- /dev/null +++ b/clang/compiler-course/Kholin_K_prefixes/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "PrefixesPlugin") +set(Student "KholinKirill") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/Kholin_K_prefixes/Kholin_K_prefixes_plugin.cpp b/clang/compiler-course/Kholin_K_prefixes/Kholin_K_prefixes_plugin.cpp new file mode 100644 index 0000000000000..5cd720b1aba93 --- /dev/null +++ b/clang/compiler-course/Kholin_K_prefixes/Kholin_K_prefixes_plugin.cpp @@ -0,0 +1,105 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +using namespace clang; + +class FindNamedClassVisitor + : public RecursiveASTVisitor { +public: + explicit FindNamedClassVisitor(ASTContext *Context, Rewriter &R) + : Context(Context), Rewrite(R) {} + + std::optional getVarPrefix(const VarDecl *Decl) { + if (Decl->isStaticLocal()) { + return "static_"; + } else if (Decl->isFileVarDecl()) { + return "global_"; + } else if (isa(Decl)) { + return "param_"; + } else if (Decl->isLocalVarDecl()) { + return "local_"; + } + return std::nullopt; + } + + void renameVariable(Decl *Decl, SourceLocation StartLocation) { + if (!Decl) return; + + std::optional VarPrefix = getVarPrefix(cast(Decl)); + if (!VarPrefix.has_value()) return; + + std::string NewID = VarPrefix.value() + cast(Decl)->getNameAsString(); + SourceLocation EndLocation = + StartLocation.getLocWithOffset(cast(Decl)->getNameAsString().length()); + Rewrite.ReplaceText(SourceRange(StartLocation, EndLocation), NewID); + + FullSourceLoc FullLocation = Context->getFullLoc(StartLocation); + if (FullLocation.isValid()) { + llvm::outs() << "Found variable: " << cast(Decl)->getNameAsString() << " -> " + << NewID << " at " << FullLocation.getSpellingLineNumber() << ":" + << FullLocation.getSpellingColumnNumber() << "\n"; + } + } + + bool VisitVarDecl(VarDecl *Decl) { + if (!Decl) return false; + renameVariable(Decl, Decl->getLocation()); + return true; + } + + bool VisitDeclRefExpr(DeclRefExpr *Expr) { + if (!Expr) return false; + + VarDecl *Decl = dyn_cast(Expr->getDecl()); + + renameVariable(Decl, Expr->getLocation()); + return true; + } + +private: + ASTContext *Context; + Rewriter &Rewrite; +}; + +class FindNamedClassConsumer : public clang::ASTConsumer { +public: + explicit FindNamedClassConsumer(ASTContext *Context, Rewriter &R) + : Visitor(Context, R) {} + + void HandleTranslationUnit(ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } + +private: + FindNamedClassVisitor Visitor; +}; + +class FindNamedClassAction : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(CompilerInstance &Compiler, + llvm::StringRef InFile) override { + m_rewriter.setSourceMgr(Compiler.getSourceManager(), + Compiler.getLangOpts()); + return std::make_unique(&Compiler.getASTContext(), + m_rewriter); + } + + bool ParseArgs(const CompilerInstance &CI, + const std::vector &Args) override { + return true; + } + +private: + Rewriter m_rewriter; +}; + +static clang::FrontendPluginRegistry::Add + X("PrefixesPlugin_KholinKirill_FIIT3_ClangAST", "set prefixes variables"); diff --git a/clang/compiler-course/Shurigin_S_FI1_ClangAst_var4/CMakeLists.txt b/clang/compiler-course/Shurigin_S_FI1_ClangAst_var4/CMakeLists.txt new file mode 100644 index 0000000000000..9ec74cffd5d94 --- /dev/null +++ b/clang/compiler-course/Shurigin_S_FI1_ClangAst_var4/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClangAST_1") +set(Student "ShuriginS") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/Shurigin_S_FI1_ClangAst_var4/ShuriginAST.cpp b/clang/compiler-course/Shurigin_S_FI1_ClangAst_var4/ShuriginAST.cpp new file mode 100644 index 0000000000000..36f4cd84e482c --- /dev/null +++ b/clang/compiler-course/Shurigin_S_FI1_ClangAst_var4/ShuriginAST.cpp @@ -0,0 +1,130 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace { + +class ExampleVisitor final : public clang::RecursiveASTVisitor { +public: + explicit ExampleVisitor(clang::ASTContext *Context, clang::Rewriter &Rewriter) + : MRewriter(Rewriter) {} + + bool VisitVarDecl(clang::VarDecl *Var) { + if (Var->getName().empty()) { + return true; + } + + std::string Prefix; + if (Var->isStaticLocal()) { + Prefix = "static_"; + } else if (Var->isLocalVarDecl()) { + Prefix = "local_"; + } else if (Var->hasGlobalStorage()) { + Prefix = "global_"; + } + + if (!Prefix.empty()) { + std::string OldName = Var->getName().str(); + if (OldName.find(Prefix) != 0) { + std::string NewName = Prefix + OldName; + MRenamedVars[OldName] = NewName; + clang::SourceLocation Loc = Var->getLocation(); + MRewriter.ReplaceText(Loc, OldName.length(), NewName); + } + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *Param) { + if (Param->getName().empty()) { + return true; + } + + std::string OldName = Param->getName().str(); + std::string NewName = "param_" + OldName; + MRenamedVars[OldName] = NewName; + MRewriter.ReplaceText(Param->getLocation(), OldName.size(), NewName); + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *Expr) { + clang::ValueDecl *Decl = Expr->getDecl(); + if (Decl->getName().empty()) { + return true; + } + + std::string OldName = Decl->getName().str(); + + if (llvm::isa(Decl)) { + return true; + } + + if (auto VD = llvm::dyn_cast(Decl)) { + VD = VD->getCanonicalDecl(); + + if (VD->hasExternalStorage()) { + std::string NewName = "global_" + OldName; + MRenamedVars[OldName] = NewName; + MRewriter.ReplaceText(Expr->getLocation(), OldName.length(), NewName); + return true; + } + } + + auto It = MRenamedVars.find(OldName); + if (It != MRenamedVars.end()) { + clang::SourceLocation Loc = Expr->getLocation(); + MRewriter.ReplaceText(Loc, OldName.length(), It->second); + } + return true; + } + +private: + clang::Rewriter &MRewriter; + std::unordered_map MRenamedVars; +}; + +class ExampleConsumer final : public clang::ASTConsumer { +public: + explicit ExampleConsumer(clang::ASTContext *Context, + clang::Rewriter &Rewriter) + : MRewriter(Rewriter), MVisitor(Context, Rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &Context) override { + MVisitor.TraverseDecl(Context.getTranslationUnitDecl()); + } + +private: + clang::Rewriter &MRewriter; + ExampleVisitor MVisitor; +}; + +class ExampleAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &Ci, llvm::StringRef) override { + MRewriter.setSourceMgr(Ci.getSourceManager(), Ci.getLangOpts()); + return std::make_unique(&Ci.getASTContext(), MRewriter); + } + + bool ParseArgs(const clang::CompilerInstance &Ci, + const std::vector &Args) override { + return true; + } + + void EndSourceFileAction() override { + MRewriter.getEditBuffer(MRewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + +private: + clang::Rewriter MRewriter; +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ClangAST_1_ShuriginS_FIIT1_ClangAST", "Adds prefixes to variables"); diff --git a/clang/compiler-course/baranov_a/CMakeLists.txt b/clang/compiler-course/baranov_a/CMakeLists.txt new file mode 100644 index 0000000000000..96b336719c35e --- /dev/null +++ b/clang/compiler-course/baranov_a/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "DataTypes") +set(Student "BARANOV_ALEKSEY") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/baranov_a/baranov_ast.cpp b/clang/compiler-course/baranov_a/baranov_ast.cpp new file mode 100644 index 0000000000000..f3768365010d2 --- /dev/null +++ b/clang/compiler-course/baranov_a/baranov_ast.cpp @@ -0,0 +1,166 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace baranov_ast_lab_1 { +std::string getQualifier(clang::AccessSpecifier temp) { + if (temp == clang::AS_public) + return "public"; + else if (temp == clang::AS_private) + return "private"; + else if (temp == clang::AS_protected) + return "protected"; + return ""; +} + +bool hasAnyField(const clang::CXXRecordDecl *recordDecl) { + for (const auto *Decl : recordDecl->decls()) { + if (llvm::isa(Decl)) + return true; + if (const auto *Var = llvm::dyn_cast(Decl)) { + return true; + } + } + return false; +} +void handleFields(const clang::CXXRecordDecl *recordDecl, + llvm::raw_ostream &output) { + for (const auto *Decl : recordDecl->decls()) { + if (const auto *Field = llvm::dyn_cast(Decl)) { + output << "| |_ " << Field->getName() << " (" + << Field->getType().getAsString() << "|" + << getQualifier(Field->getAccess()) << ")\n"; + } else if (const auto *Var = llvm::dyn_cast(Decl)) { + std::string typeStr = Var->getType().getAsString(); + output << "| |_ " << Var->getName() << " (" << typeStr; + if (Var->isStaticDataMember()) + output << "|static"; + + output << "|" << getQualifier(Var->getAccess()); + + output << ")\n"; + } + } +} + +void handleMethods(const clang::CXXRecordDecl *recordDecl, + llvm::raw_ostream &output) { + if (std::none_of(recordDecl->method_begin(), recordDecl->method_end(), + [](const clang::CXXMethodDecl *method) { + return !method->isImplicit(); + })) { + output << "| |_ (has no methods)\n"; + return; + } + + for (auto &&method : recordDecl->methods()) { + if (method->isImplicit()) + continue; + + output << "| |_ " << method->getNameAsString() << " (" + << method->getReturnType().getAsString(); + output << "("; + llvm::interleaveComma(method->parameters(), output, + [](const clang::ParmVarDecl *param) { + llvm::outs() << param->getType().getAsString(); + } + + ); + output << ")"; + if (method->isStatic()) + output << "|static"; + output << "|" << getQualifier(method->getAccess()); + if (recordDecl && + std::any_of(recordDecl->friends().begin(), recordDecl->friends().end(), + [method](const clang::FriendDecl *friendDecl) { + if (const auto *FD = friendDecl->getFriendDecl()) + return FD == method; + return false; + })) + output << "|friend"; + if (method->hasAttr()) + output << "|override"; + else if (method->isVirtual()) + output << (method->isPureVirtual() ? "|virtual|pure" : "|virtual"); + + output << ")\n"; + } +} + +class DataTypesVisitor final + : public clang::RecursiveASTVisitor { +public: + explicit DataTypesVisitor(clang::ASTContext *context) : m_context_(context) {} + bool VisitCXXRecordDecl(clang::CXXRecordDecl *recordDecl) { + auto &&output = llvm::outs(); + // is union + if (recordDecl->isUnion()) { + output << recordDecl->getNameAsString() << "(union)\n"; + } else { + // is class or whatever + output << recordDecl->getNameAsString(); + if (recordDecl->getDescribedClassTemplate()) { + output << "(" << (recordDecl->isStruct() ? "struct" : "class") + << "|template)"; + } else { + output << "(" << (recordDecl->isStruct() ? "struct" : "class") << ")"; + } + + if (recordDecl->getNumBases()) { + output << " -> "; + llvm::interleaveComma(recordDecl->bases(), output, + [&](const clang::CXXBaseSpecifier &base) { + output + << getQualifier(base.getAccessSpecifier()) + << " " << base.getType().getAsString(); + }); + } + output << "\n"; + } + output << "|_Fields\n"; + if (!hasAnyField(recordDecl)) { + output << "| |_ (has no fields)\n"; + } else { + handleFields(recordDecl, output); + } + + output << "|_Methods\n"; + handleMethods(recordDecl, output); + + return true; + } + +private: + clang::ASTContext *m_context_; +}; + +class DataTypesConsumer final : public clang::ASTConsumer { +public: + explicit DataTypesConsumer(clang::ASTContext *context) : visitor_(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + visitor_.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + DataTypesVisitor visitor_; +}; +class DataTypesAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; +} // namespace baranov_ast_lab_1 + +static clang::FrontendPluginRegistry::Add + X("BaranovDataPlugin", "Traverses data types, print info and qualifiers"); diff --git a/clang/compiler-course/beskhmelnova_k_implicit_conversions/CMakeLists.txt b/clang/compiler-course/beskhmelnova_k_implicit_conversions/CMakeLists.txt new file mode 100644 index 0000000000000..c4377d6591845 --- /dev/null +++ b/clang/compiler-course/beskhmelnova_k_implicit_conversions/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClangAST_1") +set(Student "BeskhmelnovaK") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/beskhmelnova_k_implicit_conversions/beskhmelnova_k_implicit_conversions.cpp b/clang/compiler-course/beskhmelnova_k_implicit_conversions/beskhmelnova_k_implicit_conversions.cpp new file mode 100644 index 0000000000000..015e1366147e2 --- /dev/null +++ b/clang/compiler-course/beskhmelnova_k_implicit_conversions/beskhmelnova_k_implicit_conversions.cpp @@ -0,0 +1,116 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace { + + class ImplicitCastVisitor final : public clang::RecursiveASTVisitor { + public: + explicit ImplicitCastVisitor() = default; + + bool VisitFunctionDecl(clang::FunctionDecl* Func) { + CurrentFunction = Func->getNameInfo().getName().getAsString(); + return true; + } + + bool VisitCXXConstructExpr(clang::CXXConstructExpr* Ctor) { + if (Ctor->getNumArgs() < 1) { + return true; + } + + clang::QualType FromType = Ctor->getArg(0)->getType(); + clang::QualType ToType = Ctor->getType(); + + if (FromType == ToType) { + return true; + } + + CastList.emplace_back(CastEntry{ CurrentFunction, FromType.getAsString(), ToType.getAsString() }); + return true; + } + + clang::QualType getRealType(clang::QualType Type) { + Type = Type.getCanonicalType(); + if (auto* TST = Type->getAs()) { + return TST->getDecl()->getUnderlyingType().getCanonicalType(); + } + return Type; + } + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr* Cast) { + clang::CastKind Kind = Cast->getCastKind(); + if (Kind == clang::CK_NoOp || Kind == clang::CK_LValueToRValue || Kind == clang::CK_FunctionToPointerDecay) { + return true; + } + + clang::QualType FromType = getRealType(Cast->getSubExpr()->getType()); + clang::QualType ToType = getRealType(Cast->getType()); + + if (FromType == ToType) { + return true; + } + + CastList.emplace_back(CastEntry{ CurrentFunction, FromType.getAsString(), ToType.getAsString() }); + return true; + } + + void PrintResults() { + std::string LastFunction; + for (const auto& Entry : CastList) { + if (Entry.FunctionName != LastFunction) { + llvm::outs() << "Function " << Entry.FunctionName << "\n"; + LastFunction = Entry.FunctionName; + } + llvm::outs() << Entry.getCastDescription() << ": 1\n"; + } + llvm::outs() << "Total implicit conversions: " << CastList.size() << "\n"; + } + + private: + struct CastEntry { + std::string FunctionName; + std::string FromType; + std::string ToType; + + std::string getCastDescription() const { + return FromType + " -> " + ToType; + } + }; + + std::string CurrentFunction; + std::vector CastList; + }; + + class ImplicitCastConsumer final : public clang::ASTConsumer { + public: + explicit ImplicitCastConsumer() = default; + + void HandleTranslationUnit(clang::ASTContext& Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + Visitor.PrintResults(); + } + + private: + ImplicitCastVisitor Visitor; + }; + + class ImplicitCastAction final : public clang::PluginASTAction { + public: + std::unique_ptr CreateASTConsumer(clang::CompilerInstance& CI, llvm::StringRef) override { + return std::make_unique(); + } + + bool ParseArgs(const clang::CompilerInstance& CI, const std::vector& Args) override { + return true; + } + }; + +} // namespace + +static clang::FrontendPluginRegistry::Add +X("ClangAST_1_BeskhmelnovaK_FIIT1_ClangAST", "Counts implicit type conversions"); diff --git a/clang/compiler-course/chistov_a_user_data_type/CMakeLists.txt b/clang/compiler-course/chistov_a_user_data_type/CMakeLists.txt new file mode 100644 index 0000000000000..9bc1da836206b --- /dev/null +++ b/clang/compiler-course/chistov_a_user_data_type/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "PrintData") +set(Student "Chistov_Alexey") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/chistov_a_user_data_type/chistov_a_user_data_type_plugin.cpp b/clang/compiler-course/chistov_a_user_data_type/chistov_a_user_data_type_plugin.cpp new file mode 100644 index 0000000000000..cdf558e7d6084 --- /dev/null +++ b/clang/compiler-course/chistov_a_user_data_type/chistov_a_user_data_type_plugin.cpp @@ -0,0 +1,119 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +class PrintDataVisitor final : public clang::RecursiveASTVisitor { + clang::ASTContext *class_context_; + + std::string AccessSpecifierToString(clang::AccessSpecifier accessSpecifier) { + switch (accessSpecifier) { + case clang::AS_public: + return "public"; + case clang::AS_protected: + return "protected"; + case clang::AS_private: + return "private"; + default: + llvm::errs() << "Error: Unknown access specifier\n"; + return "unknown access specifier"; + } + } + + void PrintMember(const clang::ValueDecl *member) { + auto &os = llvm::outs(); + os << "| |_ " << member->getNameAsString() << ' '; + os << '('; + + if (const auto *method = llvm::dyn_cast(member)) { + os << method->getReturnType().getAsString(); + os << '|' << AccessSpecifierToString(member->getAccess()); + if (method->isStatic()) { + os << "|static"; + } + if (method->isVirtual()) { + os << "|virtual"; + } + if (method->isOverloadedOperator()) { + os << "|override"; + } + if (method->isPureVirtual()) { + os << "|pure"; + } + } else { + os << member->getType().getAsString() << '|' + << AccessSpecifierToString(member->getAccess()); + } + + os << ")\n"; + } + +public: + explicit PrintDataVisitor(clang::ASTContext *context) : class_context_(context) {} + + bool VisitCXXRecordDecl(clang::CXXRecordDecl *declaration) { + auto &os = llvm::outs(); + os << declaration->getNameAsString() + << (declaration->isStruct() ? "(struct" : "(class") + << (declaration->isTemplated() ? "|template)" : ")") << '\n'; + + if (!declaration->bases().empty()) { + for (const auto &base : declaration->bases()) { + if (auto *baseDecl = base.getType()->getAsCXXRecordDecl()) { + clang::AccessSpecifier accessSpecifier = base.getAccessSpecifier(); + os << declaration->getName() << " -> " + << AccessSpecifierToString(accessSpecifier) << " " + << baseDecl->getName() << "\n"; + } + } + } + + if (!declaration->field_empty()) { + os << "|_Fields\n"; + for (const auto *decl : declaration->decls()) { + if (auto *field = llvm::dyn_cast(decl)) { + PrintMember(field); + } + } + } + + if (!declaration->methods().empty()) { + os << "|_Methods\n"; + for (const auto *method : declaration->methods()) { + PrintMember(method); + } + } + os << '\n'; + return true; + } +}; + +class PrintDataConsumer final : public clang::ASTConsumer { +public: + explicit PrintDataConsumer(clang::ASTContext *context) : visitor_(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + visitor_.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + PrintDataVisitor visitor_; +}; + +class PrintDataAction final : public clang::PluginASTAction { +public: + std::unique_ptr CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, const std::vector &args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("PrintDataPlugin", "Print information about a custom data type"); diff --git a/clang/compiler-course/chizhov_m_implicit_conversions/CMakeLists.txt b/clang/compiler-course/chizhov_m_implicit_conversions/CMakeLists.txt new file mode 100644 index 0000000000000..cf5c01f8e30a4 --- /dev/null +++ b/clang/compiler-course/chizhov_m_implicit_conversions/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "Implicit_Conv") +set(Student "Chizhov_Maxim") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/chizhov_m_implicit_conversions/chizhov_m_implicit_conversions.cpp b/clang/compiler-course/chizhov_m_implicit_conversions/chizhov_m_implicit_conversions.cpp new file mode 100644 index 0000000000000..d03d42e0ae7fe --- /dev/null +++ b/clang/compiler-course/chizhov_m_implicit_conversions/chizhov_m_implicit_conversions.cpp @@ -0,0 +1,133 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace { + +class ImplicitCastVisitor final + : public clang::RecursiveASTVisitor { +public: + void Conversions(const clang::QualType &FromType, + const clang::QualType &ToType) { + if (FromType == ToType) { + return; + } + + clang::QualType canonicalFromType = FromType.getCanonicalType(); + clang::QualType canonicalToType = ToType.getCanonicalType(); + + std::string fromTypeStr = canonicalFromType.getAsString(); + std::string toTypeStr = canonicalToType.getAsString(); + + std::string conversion = fromTypeStr + " -> " + toTypeStr; + + bool foundFunction = false; + for (auto &entry : converList) { + if (entry.funcName == currentFunction) { + bool foundConversion = false; + for (auto &[conversionStr, count] : entry.conv) { + if (conversionStr == conversion) { + count++; + foundConversion = true; + break; + } + } + + if (!foundConversion) { + entry.conv.push_back({conversion, 1}); + } + + foundFunction = true; + break; + } + } + + if (!foundFunction) { + Conv newConv; + newConv.funcName = currentFunction; + newConv.conv.push_back({conversion, 1}); + converList.push_back(newConv); + } + } + + bool VisitFunctionDecl(clang::FunctionDecl *Func) { + currentFunction = Func->getNameInfo().getName().getAsString(); + return true; + } + + bool VisitCXXConstructExpr(clang::CXXConstructExpr *construct) { + if (construct->getNumArgs() == 1) { + clang::QualType FromType = construct->getArg(0)->getType(); + clang::QualType ToType = construct->getType(); + Conversions(FromType, ToType); + } + return true; + } + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *Cast) { + clang::CastKind Kind = Cast->getCastKind(); + if (Kind == clang::CK_NoOp || Kind == clang::CK_LValueToRValue || + Kind == clang::CK_FunctionToPointerDecay) { + return true; + } + + clang::QualType FromType = Cast->getSubExpr()->getType(); + clang::QualType ToType = Cast->getType(); + + Conversions(FromType, ToType); + + return true; + } + + void PrintResults() { + for (const auto &Conv : converList) { + llvm::outs() << "Function " << Conv.funcName << "\n"; + + for (const auto &[conversion, count] : Conv.conv) { + llvm::outs() << " " << conversion << ": " << count << "\n"; + } + } + } + +private: + struct Conv { + std::string funcName; + std::vector> conv; + }; + std::string currentFunction; + std::vector converList; +}; + +class ImplicitCastConsumer final : public clang::ASTConsumer { +public: + void HandleTranslationUnit(clang::ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + Visitor.PrintResults(); + } + +private: + ImplicitCastVisitor Visitor; +}; + +class ImplicitCastAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &C, llvm::StringRef) override { + return std::make_unique(); + } + + bool ParseArgs(const clang::CompilerInstance &C, + const std::vector &Args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("Implicit_Conv_Chizhov_Maxim_FIIT3_ClangAST", + "Counts implicit type conversions"); diff --git a/clang/compiler-course/clang-plugin-Mamaeva/CMakeLists.txt b/clang/compiler-course/clang-plugin-Mamaeva/CMakeLists.txt new file mode 100644 index 0000000000000..8d061e837a071 --- /dev/null +++ b/clang/compiler-course/clang-plugin-Mamaeva/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClangAST_1") +set(Student "Mamaeva_Olga") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/clang-plugin-Mamaeva/myClangPlugin.cpp b/clang/compiler-course/clang-plugin-Mamaeva/myClangPlugin.cpp new file mode 100644 index 0000000000000..5571484662975 --- /dev/null +++ b/clang/compiler-course/clang-plugin-Mamaeva/myClangPlugin.cpp @@ -0,0 +1,127 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ParentMapContext.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +class MyClangVisitor : public clang::RecursiveASTVisitor { + +private: + clang::ASTContext *m_context; + llvm::MapVector, int>> + m_functionStats; + int m_totalConversions = 0; + +public: + explicit MyClangVisitor(clang::ASTContext *context) : m_context(context) {} + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *ICE) { + + auto castKind = ICE->getCastKind(); + if (castKind == clang::CK_LValueToRValue || castKind == clang::CK_NoOp || + castKind == clang::CK_FunctionToPointerDecay) { + return true; + } + clang::QualType SourceType = ICE->getSubExpr()->getType(); + clang::QualType TargetType = ICE->getType(); + + if (SourceType.getCanonicalType() == TargetType.getCanonicalType()) { + return true; + } + + auto Parents = m_context->getParents(*ICE); + while (!Parents.empty()) { + if (const auto *FD = Parents[0].get()) { + recordConversion(FD, SourceType, TargetType); + break; + } else if (const auto *Lambda = Parents[0].get()) { + if (const auto *CallOp = Lambda->getCallOperator()) { + recordConversion(CallOp, SourceType, TargetType); + break; + } + } else if (const auto *ME = Parents[0].get()) { + recordConversion(ME, SourceType, TargetType); + break; + } + Parents = m_context->getParents(Parents[0]); + } + return true; + } + + std::string normalizeTypeName(std::string typeName) { + const std::vector prefixes = {"struct ", "class ", "enum "}; + for (const auto &prefix : prefixes) { + size_t pos = typeName.find(prefix); + if (pos == 0) { + typeName.erase(0, prefix.length()); + break; + } + } + typeName.erase( + std::remove_if(typeName.begin(), typeName.end(), + [](unsigned char c) { return std::isspace(c); }), + typeName.end()); + size_t pos; + while ((pos = typeName.find("_Bool")) != std::string::npos) { + typeName.replace(pos, 5, "bool"); + } + return typeName; + } + + void recordConversion(const clang::FunctionDecl *FD, clang::QualType From, + clang::QualType To) { + std::string FromStr = + normalizeTypeName(From.getCanonicalType().getAsString()); + std::string ToStr = normalizeTypeName(To.getCanonicalType().getAsString()); + m_functionStats[FD][std::make_pair(FromStr, ToStr)]++; + m_totalConversions++; + } + + void printStats(llvm::raw_ostream &OS) { + for (const auto &[func, convs] : m_functionStats) { + OS << "Function `" << func->getName() << "`\n"; + for (const auto &[conv, num] : convs) { + OS << conv.first << " -> " << conv.second << ": " << num << "\n"; + } + } + OS << "Total implicit conversions: " << m_totalConversions << "\n"; + } +}; + +class MyClangConsumer : public clang::ASTConsumer { + +private: + MyClangVisitor m_visitor; + +public: + explicit MyClangConsumer(clang::ASTContext *context) : m_visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + m_visitor.printStats(llvm::errs()); + } +}; + +class MyClangPlugin : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; + +} // namespace + +// Регистрация плагина +static clang::FrontendPluginRegistry::Add + X("ClangAST_1", "Counts implicit type conversions"); diff --git a/clang/compiler-course/drozhdinov_d_clangast_var3/CMakeLists.txt b/clang/compiler-course/drozhdinov_d_clangast_var3/CMakeLists.txt new file mode 100644 index 0000000000000..a5ed44e068030 --- /dev/null +++ b/clang/compiler-course/drozhdinov_d_clangast_var3/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "CastCounter") +set(Student "DrozhdinovD") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/drozhdinov_d_clangast_var3/drozhdinov_clang.cpp b/clang/compiler-course/drozhdinov_d_clangast_var3/drozhdinov_clang.cpp new file mode 100644 index 0000000000000..48372679026e2 --- /dev/null +++ b/clang/compiler-course/drozhdinov_d_clangast_var3/drozhdinov_clang.cpp @@ -0,0 +1,106 @@ +#include +#include +#include + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +using llvm::outs; +using std::map; +using std::string; +using std::vector; + +namespace { +class CastCounter final : public clang::RecursiveASTVisitor { +public: + CastCounter() = default; + bool VisitFunctionDecl(clang::FunctionDecl *Expr) { + CurrentFunction = Expr->getNameAsString(); + return true; + } + + bool VisitCXXConstructExpr(clang::CXXConstructExpr *Expr) { + if (Expr->getNumArgs() < 1) { + return true; + } + + clang::QualType SourceType = Expr->getArg(0)->getType(); + clang::QualType DestType = Expr->getType(); + + if (SourceType == DestType) { + return true; + } + CastMap[CurrentFunction] + [std::make_pair(SourceType.getAsString(), DestType.getAsString())]++; + return true; + } + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *Expr) { + clang::CastKind Kind = Expr->getCastKind(); + + if (Kind == clang::CK_LValueToRValue || + Kind == clang::CK_FunctionToPointerDecay) { + return true; + } + + clang::QualType SourceType = + Expr->getSubExpr()->getType().getCanonicalType(); + clang::QualType DestType = Expr->getType().getCanonicalType(); + + if (SourceType == DestType) { + return true; + } + CastMap[CurrentFunction] + [std::make_pair(SourceType.getAsString(), DestType.getAsString())]++; + return true; + } + + void getResult() { + for (auto iter = CastMap.rbegin(); iter != CastMap.rend(); iter++) { + outs() << "Function " << iter->first << "\n"; + for (auto [cast, val] : iter->second) { + outs() << cast.first << " -> " << cast.second << ": " << val << "\n"; + } + } + } + +private: + map, int>> CastMap; + string CurrentFunction; +}; + +class CastCounterConsumer final : public clang::ASTConsumer { +private: + CastCounter cc; + +public: + CastCounterConsumer() = default; + + void HandleTranslationUnit(clang::ASTContext &Context) override { + cc.TraverseDecl(Context.getTranslationUnitDecl()); + cc.getResult(); + } +}; + +class CastCounterAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef) override { + return std::make_unique(); + } + + bool ParseArgs(const clang::CompilerInstance &CI, + const vector &Args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("CastCounter_DrozhdinovD_FIIT1_ClangAST", + "Detects and counts implicit casts in function bodies and constructor " + "conversions"); diff --git a/clang/compiler-course/frolova_e_implicit_conversions/CMakeLists.txt b/clang/compiler-course/frolova_e_implicit_conversions/CMakeLists.txt new file mode 100644 index 0000000000000..73db204e0f5b8 --- /dev/null +++ b/clang/compiler-course/frolova_e_implicit_conversions/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ImplicitConvPlugin") +set(Student "Frolova_Elizaveta") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/frolova_e_implicit_conversions/frolova_e_implicit_conversions.cpp b/clang/compiler-course/frolova_e_implicit_conversions/frolova_e_implicit_conversions.cpp new file mode 100644 index 0000000000000..3ea67a7610f05 --- /dev/null +++ b/clang/compiler-course/frolova_e_implicit_conversions/frolova_e_implicit_conversions.cpp @@ -0,0 +1,116 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace { +class ImplicitConvVisitor final + : public clang::RecursiveASTVisitor { + void handleTypeConversion(const clang::QualType &fromType, + const clang::QualType &toType) { + std::string fromTypeStr = fromType.getAsString(); + std::string toTypeStr = toType.getAsString(); + + fromTypeStr = (fromTypeStr == "_Bool") ? "bool" : fromTypeStr; + toTypeStr = (toTypeStr == "_Bool") ? "bool" : toTypeStr; + + if (fromTypeStr == toTypeStr) + return; + + std::string conversion = fromTypeStr + " -> " + toTypeStr; + auto &convList = conversions[currentFunction]; + + for (auto &entry : convList) { + if (entry.first == conversion) { + entry.second++; + break; + } + } + + convList.push_back({conversion, 1}); + } + +public: + explicit ImplicitConvVisitor(clang::ASTContext *context) : Context(context) {} + + bool VisitFunctionDecl(clang::FunctionDecl *func) { + currentFunction = func->getNameInfo().getName().getAsString(); + if (conversions.find(currentFunction) == conversions.end()) { + functionOrder.push_back(currentFunction); + } + return true; + } + + bool VisitCXXConstructExpr(clang::CXXConstructExpr *expr) { + if (expr->getNumArgs() == 1) { + clang::QualType fromType = expr->getArg(0)->getType(); + clang::QualType toType = expr->getType(); + handleTypeConversion(fromType, toType); + } + return true; + } + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *cast) { + if (!cast || !cast->getSubExpr() || + cast->getCastKind() == clang::CK_FunctionToPointerDecay) { + return true; + } + + clang::QualType fromType = cast->getSubExpr()->getType(); + clang::QualType toType = cast->getType(); + handleTypeConversion(fromType, toType); + return true; + } + + void printResults() { + auto &os = llvm::outs(); + for (const auto &funcName : functionOrder) { + os << "Function: " << funcName << "\n"; + for (const auto &[c1, c2] : conversions[funcName]) { + os << " " << c1 << ": " << c2 << "\n"; + } + os << "\n"; + } + } + +private: + clang::ASTContext *Context; + std::string currentFunction; + std::vector functionOrder; + std::map>> conversions; +}; + +class ConversionConsumer final : public clang::ASTConsumer { +public: + explicit ConversionConsumer(clang::ASTContext *context) : Visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + Visitor.TraverseDecl(context.getTranslationUnitDecl()); + Visitor.printResults(); + } + +private: + ImplicitConvVisitor Visitor; +}; + +class ConversionAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ImplicitConvPlugin", + "Output the number of implicit conversions in the entire file"); diff --git a/clang/compiler-course/grudzin_k_unused_vars_ast/CMakeLists.txt b/clang/compiler-course/grudzin_k_unused_vars_ast/CMakeLists.txt new file mode 100644 index 0000000000000..b9068694ea757 --- /dev/null +++ b/clang/compiler-course/grudzin_k_unused_vars_ast/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "UnusedVars") +set(Student "Grudzin_Konstantin") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/grudzin_k_unused_vars_ast/grudzin_k_unused_vars.cpp b/clang/compiler-course/grudzin_k_unused_vars_ast/grudzin_k_unused_vars.cpp new file mode 100644 index 0000000000000..eac3cdadeb905 --- /dev/null +++ b/clang/compiler-course/grudzin_k_unused_vars_ast/grudzin_k_unused_vars.cpp @@ -0,0 +1,86 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Attr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +class MyUnVarsVisitor final + : public clang::RecursiveASTVisitor { +public: + explicit MyUnVarsVisitor(clang::ASTContext *context, clang::Rewriter &R) + : m_context(context), TheRewriter(R) {} + + bool VisitParamVarDecl(clang::ParmVarDecl *parametr) { + if (!parametr->isUsed() && !parametr->hasAttr()) { + clang::SourceLocation loc = parametr->getSourceRange().getBegin(); + TheRewriter.InsertText(loc, "[[maybe_unused]] ", true, true); + } + return true; + } + + bool VisitVarDecl(clang::VarDecl *variable) { + if (!variable->isUsed() && !variable->hasAttr()) { + clang::SourceLocation loc = variable->getSourceRange().getBegin(); + TheRewriter.InsertText(loc, "[[maybe_unused]] ", true, true); + } + return true; + } + +private: + clang::ASTContext *m_context; + clang::Rewriter &TheRewriter; +}; + +class MyUnVarsConsumer final : public clang::ASTConsumer { +public: + MyUnVarsConsumer(clang::ASTContext *context, clang::Rewriter &R) + : Visitor(context, R) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + Visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + MyUnVarsVisitor Visitor; +}; + +class MyUnVarsAction final : public clang::PluginASTAction { +private: + clang::Rewriter TheRewriter; + +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef) override { + TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); + return std::make_unique(&CI.getASTContext(), TheRewriter); + } + + void EndSourceFileAction() override { + TheRewriter.getEditBuffer(TheRewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + + bool ParseArgs(const clang::CompilerInstance &CI, + const std::vector &args) override { + for (const auto &arg : args) { + if (arg == "--help") { + // Returning false stops further processing after printing help. + llvm::outs() << "This plugin marks unused variables with " + "[[maybe_unused]] attribute"; + return false; + } + } + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("grudzin_k_UnVars_plugin", + "This plugin marks unused variables by adding attribute and adding " + "[[maybe_unused]] flag in code"); diff --git a/clang/compiler-course/ionova_ekaterina_lab_1/CMakeLists.txt b/clang/compiler-course/ionova_ekaterina_lab_1/CMakeLists.txt new file mode 100644 index 0000000000000..d3c9f653967a9 --- /dev/null +++ b/clang/compiler-course/ionova_ekaterina_lab_1/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClassInfoVisitorPlugin") +set(Student "Ionova_Ekaterina") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/ionova_ekaterina_lab_1/ClassInfoPlugin.cpp b/clang/compiler-course/ionova_ekaterina_lab_1/ClassInfoPlugin.cpp new file mode 100644 index 0000000000000..02a8761a1d41c --- /dev/null +++ b/clang/compiler-course/ionova_ekaterina_lab_1/ClassInfoPlugin.cpp @@ -0,0 +1,148 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +class ClassInfoVisitor final + : public clang::RecursiveASTVisitor { +public: + explicit ClassInfoVisitor(clang::ASTContext *context) + : m_context(context), m_os(llvm::outs()) {} + + bool VisitCXXRecordDecl(clang::CXXRecordDecl *declaration) { + if (!declaration->isThisDeclarationADefinition() || + declaration->isImplicit()) + return true; + + printClassInfo(declaration); + printBaseClasses(declaration); + printFields(declaration); + printMethods(declaration); + + return true; + } + +private: + void printClassInfo(const clang::CXXRecordDecl *userType) { + m_os << userType->getNameAsString() << ' ' + << (userType->isStruct() ? "(struct" : "(class") + << (userType->isTemplated() ? "|template)" : ")") << '\n'; + } + + void printBaseClasses(const clang::CXXRecordDecl *declaration) { + if (declaration->getNumBases() == 0) + return; + + m_os << "|_Base Classes: "; + + llvm::interleaveComma( + declaration->bases(), m_os, [&](const clang::CXXBaseSpecifier &base) { + if (auto baseDecl = base.getType()->getAsCXXRecordDecl()) + m_os << baseDecl->getNameAsString(); + }); + + m_os << "\n"; + } + + void printFields(const clang::CXXRecordDecl *declaration) { + m_os << "|_Fields\n"; + + bool hasFields = false; + for (const auto *field : declaration->fields()) { + hasFields = true; + m_os << "| |_ " << field->getNameAsString() << " (" + << field->getType().getAsString() << "|" + << getAccessSpecifierAsString(field) << ")\n"; + } + + for (const auto *decl : declaration->decls()) { + if (const auto *varDecl = llvm::dyn_cast(decl)) { + if (varDecl->isStaticDataMember()) { + hasFields = true; + m_os << "| |_ " << varDecl->getNameAsString() << " (" + << varDecl->getType().getAsString() << "|" + << getAccessSpecifierAsString(varDecl) << "|static)\n"; + } + } + } + + if (!hasFields) + m_os << "| |_ (no fields)\n"; + } + + void printMethods(const clang::CXXRecordDecl *declaration) { + if (declaration->method_begin() == declaration->method_end()) + return; + + m_os << "|_Methods\n"; + + for (const auto *method : declaration->methods()) { + if (method->isImplicit()) + continue; + + m_os << "| |_ " << method->getNameAsString() << " (" + << method->getReturnType().getAsString() << "|" + << getAccessSpecifierAsString(method); + + if (method->isVirtual()) + m_os << "|virtual"; + if (method->isPureVirtual()) + m_os << "|pure"; + if (method->isConst()) + m_os << "|const"; + + m_os << ")\n"; + } + } + + std::string getAccessSpecifierAsString(const clang::Decl *decl) { + if (auto *namedDecl = llvm::dyn_cast(decl)) { + switch (namedDecl->getAccess()) { + case clang::AS_public: + return "public"; + case clang::AS_protected: + return "protected"; + case clang::AS_private: + return "private"; + default: + return "unknown"; + } + } + return "unknown"; + } + + clang::ASTContext *m_context; + llvm::raw_ostream &m_os; +}; + +class ClassInfoConsumer final : public clang::ASTConsumer { +public: + explicit ClassInfoConsumer(clang::ASTContext *context) : m_visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + ClassInfoVisitor m_visitor; +}; + +class ClassInfoAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ClassInfoVisitorPlugin_Ionova_Ekaterina_FIIT1_ClangAST", + "Prints detailed info about user-defined types"); diff --git a/clang/compiler-course/ivanov_m_prefix_4/CMakeLists.txt b/clang/compiler-course/ivanov_m_prefix_4/CMakeLists.txt new file mode 100644 index 0000000000000..0a5fdbc62e4f3 --- /dev/null +++ b/clang/compiler-course/ivanov_m_prefix_4/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "Prefix_Plugin") +set(Student "Ivanov_Mikhail") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/ivanov_m_prefix_4/ivanov_m_prefix.cpp b/clang/compiler-course/ivanov_m_prefix_4/ivanov_m_prefix.cpp new file mode 100644 index 0000000000000..9b225e3a28df7 --- /dev/null +++ b/clang/compiler-course/ivanov_m_prefix_4/ivanov_m_prefix.cpp @@ -0,0 +1,106 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace { +class NewPrefixVisitor final + : public clang::RecursiveASTVisitor { + clang::Rewriter &m_rewriter; + std::unordered_map rewrittenDecl; + +public: + explicit NewPrefixVisitor(clang::ASTContext *context, + clang::Rewriter &rewriter) + : m_rewriter(rewriter) {} + bool VisitVarDecl(clang::VarDecl *varDecl) { + if (!varDecl) + return true; + + std::string prevName = varDecl->getName().str(); + + if (prevName.empty()) + return true; + + std::string prefix; + + if (varDecl->isStaticLocal()) { + prefix = "static_"; + } else if (varDecl->hasGlobalStorage()) { + prefix = "global_"; + } else if (varDecl->isLocalVarDecl()) { + prefix = "local_"; + } + + if (!prefix.empty()) { + std::string newName = prefix + prevName; + m_rewriter.ReplaceText(varDecl->getLocation(), prevName.size(), newName); + rewrittenDecl[varDecl] = newName; + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *parDecl) { + std::string prevName = parDecl->getName().str(); + if (prevName.empty()) + return true; + + std::string newName = "param_" + prevName; + m_rewriter.ReplaceText(parDecl->getLocation(), prevName.size(), newName); + rewrittenDecl[parDecl] = newName; + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *declRef) { + auto *varDecl = clang::dyn_cast(declRef->getDecl()); + auto it = rewrittenDecl.find(varDecl); + if (it != rewrittenDecl.end()) { + std::string newName = it->second; + clang::SourceLocation loc = declRef->getLocation(); + std::string prevName = varDecl->getName().str(); + m_rewriter.ReplaceText(loc, prevName.size(), newName); + } + return true; + } +}; + +class NewPrefixConsumer final : public clang::ASTConsumer { + clang::Rewriter &m_rewriter; + NewPrefixVisitor m_visitor; + +public: + explicit NewPrefixConsumer(clang::ASTContext *context, + clang::Rewriter &rewriter) + : m_rewriter(rewriter), m_visitor(context, rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + m_rewriter.getEditBuffer(context.getSourceManager().getMainFileID()) + .write(llvm::outs()); + } +}; + +class NewPrefixAction : public clang::PluginASTAction { + clang::Rewriter m_rewriter; + +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + m_rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), m_rewriter); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("Prefix_Plugin_Ivanov_Mikhail_FIIT1_ClangAST", + "Plugin adds corresponding prefixes to static, local and global " + "variables and parameters"); diff --git a/clang/compiler-course/kabalova_clangAST/CMakeLists.txt b/clang/compiler-course/kabalova_clangAST/CMakeLists.txt new file mode 100644 index 0000000000000..0b5690ff4d4d9 --- /dev/null +++ b/clang/compiler-course/kabalova_clangAST/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClangAST") +set(Student "Kabalova_Valeria") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/kabalova_clangAST/kabalova_ClangAST.cpp b/clang/compiler-course/kabalova_clangAST/kabalova_ClangAST.cpp new file mode 100644 index 0000000000000..9fbcdbf81bc75 --- /dev/null +++ b/clang/compiler-course/kabalova_clangAST/kabalova_ClangAST.cpp @@ -0,0 +1,88 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +class UnusedVisitor final : public clang::RecursiveASTVisitor { +public: + UnusedVisitor(clang::ASTContext *context, clang::Rewriter &rewriter) + : m_context(context), m_rewriter(rewriter) {} + bool VisitFuncParameterDecl(clang::ParmVarDecl *parameter) { + if (!parameter->isUsed() && !parameter->hasAttr()) { + clang::SourceLocation Loc = parameter->getBeginLoc(); + if (clang::Rewriter::isRewritable(Loc)) { + m_rewriter.InsertTextBefore(Loc, "[[maybe_unused]] "); + } else + return false; + } + return true; + } + bool VisitVarDecl(clang::VarDecl *variable) { + if (!variable->isUsed() && !variable->hasAttr()) { + clang::SourceLocation Loc = variable->getBeginLoc(); + if (clang::Rewriter::isRewritable(Loc)) { + m_rewriter.InsertTextBefore(Loc, "[[maybe_unused]] "); + } else + return false; + } + return true; + } + +private: + clang::ASTContext *m_context; + // Using rewriter - the main interface to rewrite buffers + clang::Rewriter &m_rewriter; +}; + +class UnusedConsumer final : public clang::ASTConsumer { +public: + UnusedConsumer(clang::ASTContext *context, clang::Rewriter &rewriter) + : m_visitor(context, rewriter) {} + void HandleTranslationUnit(clang::ASTContext &context) override { + // TraverseDecl - Recursively visit a declaration + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + UnusedVisitor m_visitor; +}; + +class UnusedAction final : public clang::PluginASTAction { +private: + clang::Rewriter m_rewriter; + +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + m_rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), m_rewriter); + } + + void EndSourceFile() override { + m_rewriter.getEditBuffer(m_rewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + for (auto &i : args) { + if (i == "--help") { + llvm::outs() + << "This plugin searches for unused variables or unused parameters " + "of functions and marks them with attribute [[maybe__unused]]" + << "\n"; + } + } + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ClangAST_Kabalova_Valeria_FIIT1_ClangAST", + "Adds attribute [[maybe_unused]] if the variable or parameter is unused"); diff --git a/clang/compiler-course/kolodkin_g_lab_1_var_1/CMakeLists.txt b/clang/compiler-course/kolodkin_g_lab_1_var_1/CMakeLists.txt new file mode 100644 index 0000000000000..a8f00e4f397ea --- /dev/null +++ b/clang/compiler-course/kolodkin_g_lab_1_var_1/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "LabPlugin") +set(Student "KolodkinGrigorii") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/kolodkin_g_lab_1_var_1/kolodkin_g_lab1_plugin.cpp b/clang/compiler-course/kolodkin_g_lab_1_var_1/kolodkin_g_lab1_plugin.cpp new file mode 100644 index 0000000000000..806f396908e29 --- /dev/null +++ b/clang/compiler-course/kolodkin_g_lab_1_var_1/kolodkin_g_lab1_plugin.cpp @@ -0,0 +1,155 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace { +std::string getAccessLevel(clang::AccessSpecifier access) { + switch (static_cast(access)) { + case clang::AccessSpecifier::AS_public: + return "public"; + case clang::AccessSpecifier::AS_protected: + return "protected"; + case clang::AccessSpecifier::AS_private: + return "private"; + default: + return ""; + } +} + +class LabPluginVisitor final + : public clang::RecursiveASTVisitor { +public: + explicit LabPluginVisitor(clang::ASTContext *context) {} + + bool VisitCXXRecordDecl(const clang::CXXRecordDecl *record) { + if (!record->isCompleteDefinition()) + return true; + + llvm::outs() << record->getName(); + + if (!record->bases().empty()) { + llvm::outs() << " -> "; + for (auto base = record->bases_begin(); base != record->bases_end(); + ++base) { + if (base != record->bases_begin()) { + llvm::outs() << ", "; + } + llvm::outs() << base->getType()->getAsCXXRecordDecl()->getName(); + } + } + + llvm::outs() << "\n"; + + llvm::outs() << "|_Friends\n"; + if (record->friend_begin() == record->friend_end()) { + llvm::outs() << "| |_ (no friends)\n"; + } else { + for (const auto *friendDecl : record->friends()) { + const clang::Decl *friendDeclType = friendDecl->getFriendDecl(); + if (const auto *friendClass = + llvm::dyn_cast(friendDeclType)) { + llvm::outs() << "| |_ " << friendClass->getName() << "\n"; + } else if (const auto *friendFunction = + llvm::dyn_cast(friendDeclType)) { + llvm::outs() << "| |_ " << friendFunction->getName() << "\n"; + } else { + llvm::outs() << "| |_ (unknown friend kind)\n"; + } + } + } + + llvm::outs() << "|_Fields\n"; + if (record->field_empty()) { + llvm::outs() << "| |_ (no fields)\n"; + } else { + for (const auto *field : record->fields()) { + llvm::outs() << "| |_ " << field->getName() << " (" + << field->getType().getAsString() << "|" + << ::getAccessLevel(field->getAccess()) << ")\n"; + } + } + + llvm::outs() << "|_Methods\n"; + if (record->methods().empty()) { + llvm::outs() << "| |_ (no methods)\n"; + } else { + for (const auto *method : record->methods()) { + if (method->isImplicit()) + continue; + + llvm::SmallVector specs; + + if (method->isVirtual() && !method->hasAttr()) { + specs.push_back("virtual"); + } + if (method->isPureVirtual()) { + specs.push_back("pure"); + } + if (method->hasAttr()) { + specs.push_back("override"); + } + + std::string oss_str; + llvm::raw_string_ostream oss(oss_str); + oss << method->getReturnType().getAsString() << "("; + + std::vector paramTypes; + for (unsigned i = 0; i < method->getNumParams(); ++i) { + const auto *param = method->getParamDecl(i); + paramTypes.push_back(param->getType().getAsString()); + } + + llvm::interleaveComma(paramTypes, oss, + [&](const std::string &type) { return type; }); + oss << ")"; + + llvm::outs() << "| |_ " << method->getName() << " (" << oss.str() << "|" + << ::getAccessLevel(method->getAccess()); + + for (const auto &s : specs) { + llvm::outs() << "|" << s; + } + llvm::outs() << ")\n"; + } + } + + llvm::outs() << "\n"; + + return true; + } +}; + +class LabPluginConsumer final : public clang::ASTConsumer { +public: + explicit LabPluginConsumer(clang::ASTContext *context) : m_visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + LabPluginVisitor m_visitor; +}; + +class LabPluginAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add<::LabPluginAction> + X("LabPlugin_KolodkinGrigorii_FIIT3_ClangAST", + "Prints info about user defined data types"); \ No newline at end of file diff --git a/clang/compiler-course/komshina_d_num_implicit_conversions/CMakeLists.txt b/clang/compiler-course/komshina_d_num_implicit_conversions/CMakeLists.txt new file mode 100644 index 0000000000000..c0dd8653d3623 --- /dev/null +++ b/clang/compiler-course/komshina_d_num_implicit_conversions/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "Implicit_Conversions") +set(Student "Komshina_Daria") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/komshina_d_num_implicit_conversions/komshina_d_num_implicit_conversions.cpp b/clang/compiler-course/komshina_d_num_implicit_conversions/komshina_d_num_implicit_conversions.cpp new file mode 100644 index 0000000000000..9de0c0b78328b --- /dev/null +++ b/clang/compiler-course/komshina_d_num_implicit_conversions/komshina_d_num_implicit_conversions.cpp @@ -0,0 +1,129 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include + +namespace { + +class ImplicitConversionsAnalyzer final + : public clang::RecursiveASTVisitor { +public: + ImplicitConversionsAnalyzer() {} + + bool VisitFunctionDecl(clang::FunctionDecl *func) { + CurrentFunction = func->getNameAsString(); + return true; + } + + bool VisitCXXConstructExpr(clang::CXXConstructExpr *Conv) { + if (Conv->getNumArgs() == 0) + return true; + HandleConv(Conv->getArg(0)->getType(), Conv->getType()); + return true; + } + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *CastExpr) { + switch (CastExpr->getCastKind()) { + case clang::CK_NoOp: + case clang::CK_LValueToRValue: + case clang::CK_FunctionToPointerDecay: + return true; + default: + HandleConv(CastExpr->getSubExpr()->getType(), CastExpr->getType()); + return true; + } + } + + void PrintReport(bool includeTotal = false) const { + std::set processedFunctions; + int totalConversions = 0; + + for (const auto &entry : CastList) { + const auto &[FunctionName, FromType, ToType] = entry; + + if (processedFunctions.find(FunctionName) == processedFunctions.end()) { + llvm::outs() << "Function " << FunctionName << "\n"; + processedFunctions.insert(FunctionName); + } + + llvm::outs() << FromType + " -> " + ToType << ": 1\n"; + totalConversions++; + } + + if (includeTotal) { + llvm::outs() << "Total implicit conversions: " << totalConversions + << "\n"; + } + } + +private: + void HandleConv(clang::QualType From, clang::QualType To) { + From = ResolveType(From); + To = ResolveType(To); + if (From == To) + return; + + CastList.emplace_back(CurrentFunction, From.getAsString(), + To.getAsString()); + } + + clang::QualType ResolveType(clang::QualType Type) { + Type = Type.getCanonicalType(); + if (auto *TST = Type->getAs()) { + return TST->getDecl()->getUnderlyingType().getCanonicalType(); + } + if (auto *ET = Type->getAs()) { + return ET->getNamedType().getCanonicalType(); + } + return Type; + } + + std::string CurrentFunction; + std::vector> CastList; +}; + +class ImplicitConversionsConsumer final : public clang::ASTConsumer { +public: + ImplicitConversionsConsumer() {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + m_visitor.PrintReport(true); + } + +private: + ImplicitConversionsAnalyzer m_visitor; +}; + +class ImplicitConversionsAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + for (const auto &arg : args) { + if (arg == "--help") { + llvm::errs() << "Usage: -Xclang -plugin -Xclang " + "Implicit_Conversions_Komshina_Daria_FIIT1_ClangAST\n" + << "Options:\n" + << " --help Show this help message\n"; + return false; + } + } + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("Implicit_Conversions_Komshina_Daria_FIIT1_ClangAST", + "Count implicit type conversions"); diff --git a/clang/compiler-course/kozlova_e_variant_4/CMakeLists.txt b/clang/compiler-course/kozlova_e_variant_4/CMakeLists.txt new file mode 100644 index 0000000000000..50fb18da5a766 --- /dev/null +++ b/clang/compiler-course/kozlova_e_variant_4/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "FirstPlugin") +set(Student "KozlovaEkaterina") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/kozlova_e_variant_4/kozlova_e_var_4.cpp b/clang/compiler-course/kozlova_e_variant_4/kozlova_e_var_4.cpp new file mode 100644 index 0000000000000..90d1751797c03 --- /dev/null +++ b/clang/compiler-course/kozlova_e_variant_4/kozlova_e_var_4.cpp @@ -0,0 +1,143 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +class ExampleVisitor : public clang::RecursiveASTVisitor { +public: + explicit ExampleVisitor(clang::ASTContext *context, clang::Rewriter &rewriter) + : m_rewriter(rewriter) {} + + bool VisitVarDecl(clang::VarDecl *var) { + if (var->isLocalVarDecl()) { + if (var->isStaticLocal()) { + renameVar(var, "static_"); + } else { + renameVar(var, "local_"); + } + } else if (var->isFileVarDecl()) { + if (var->getStorageClass() == clang::SC_Static) { + renameVar(var, "static_global_"); + } else { + renameVar(var, "global_"); + } + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *param) { + llvm::StringRef oldName = param->getName(); + if (oldName.empty()) + return true; + + std::string newName = "param_" + oldName.str(); + std::string defaultValueStr; + if (param->hasDefaultArg()) { + clang::Expr *defaultArg = param->getDefaultArg(); + llvm::raw_string_ostream stream(defaultValueStr); + defaultArg->printPretty(stream, nullptr, + clang::PrintingPolicy(clang::LangOptions())); + stream.flush(); + newName += "_default_" + defaultValueStr; + clang::SourceLocation loc = param->getLocation(); + if (loc.isValid() && m_rewriter.getSourceMgr().isWrittenInMainFile(loc)) { + m_rewriter.ReplaceText(loc, oldName.size() + defaultValueStr.size() + 3, + newName); + } + } else { + clang::SourceLocation loc = param->getLocation(); + if (loc.isValid() && m_rewriter.getSourceMgr().isWrittenInMainFile(loc)) { + m_rewriter.ReplaceText(loc, oldName.size(), newName); + } + } + renamedVars[param] = newName; + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *expr) { + if (auto *var = llvm::dyn_cast(expr->getDecl())) { + llvm::StringRef oldName = var->getName(); + + if (!shouldRename(var)) + return true; + + clang::SourceLocation loc = expr->getLocation(); + if (loc.isValid() && m_rewriter.getSourceMgr().isWrittenInMainFile(loc)) { + std::string newName = getPrefixedName(var); + m_rewriter.ReplaceText(loc, oldName.size(), newName); + } + } + return true; + } + +private: + clang::Rewriter &m_rewriter; + llvm::DenseMap renamedVars; + + bool shouldRename(clang::VarDecl *var) { return renamedVars.count(var) > 0; } + + std::string getPrefixedName(clang::VarDecl *var) { return renamedVars[var]; } + + void renameVar(clang::VarDecl *var, llvm::StringRef prefix) { + llvm::StringRef oldName = var->getName(); + if (oldName.empty()) + return; + + std::string newName = (prefix + oldName).str(); + + clang::SourceLocation loc = var->getLocation(); + if (loc.isValid() && m_rewriter.getSourceMgr().isWrittenInMainFile(loc)) { + m_rewriter.ReplaceText(loc, oldName.size(), newName); + } + + renamedVars[var] = newName; + } +}; + +class ExampleConsumer : public clang::ASTConsumer { +public: + explicit ExampleConsumer(clang::ASTContext *context, + clang::Rewriter &rewriter) + : m_visitor(context, rewriter), m_rewriter(rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + + auto &buffer = + m_rewriter.getEditBuffer(m_rewriter.getSourceMgr().getMainFileID()); + if (buffer.size() > 0) { + buffer.write(llvm::outs()); + } + } + +private: + ExampleVisitor m_visitor; + clang::Rewriter &m_rewriter; +}; + +class ExampleAction : public clang::PluginASTAction { +public: + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } + + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + m_rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), m_rewriter); + } + +private: + clang::Rewriter m_rewriter; +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("FirstPlugin_KozlovaEkaterina_FIIT3_ClangAST", + "Adds prefixes to variables"); diff --git a/clang/compiler-course/kudryashova_i_compilers_clangast/CMakeLists.txt b/clang/compiler-course/kudryashova_i_compilers_clangast/CMakeLists.txt new file mode 100644 index 0000000000000..978ec399ea946 --- /dev/null +++ b/clang/compiler-course/kudryashova_i_compilers_clangast/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "Implicit_Conv") +set(Student "Kudryashova_Irina") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/kudryashova_i_compilers_clangast/kudryashova_i_clangast_plugin.cpp b/clang/compiler-course/kudryashova_i_compilers_clangast/kudryashova_i_clangast_plugin.cpp new file mode 100644 index 0000000000000..beec55923c46d --- /dev/null +++ b/clang/compiler-course/kudryashova_i_compilers_clangast/kudryashova_i_clangast_plugin.cpp @@ -0,0 +1,129 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ParentMapContext.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +class ImplicitConvVisitor + : public clang::RecursiveASTVisitor { + +private: + clang::ASTContext *m_context; + llvm::MapVector, int>> + m_functionStats; + int m_totalConversions = 0; + +public: + explicit ImplicitConvVisitor(clang::ASTContext *context) + : m_context(context) {} + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *ICE) { + + auto castKind = ICE->getCastKind(); + if (castKind == clang::CK_LValueToRValue || castKind == clang::CK_NoOp || + castKind == clang::CK_FunctionToPointerDecay) { + return true; + } + clang::QualType SourceType = ICE->getSubExpr()->getType(); + clang::QualType TargetType = ICE->getType(); + + if (SourceType.getCanonicalType() == TargetType.getCanonicalType()) { + return true; + } + + auto Parents = m_context->getParents(*ICE); + while (!Parents.empty()) { + if (const auto *FD = Parents[0].get()) { + recordConversion(FD, SourceType, TargetType); + break; + } else if (const auto *Lambda = Parents[0].get()) { + if (const auto *CallOp = Lambda->getCallOperator()) { + recordConversion(CallOp, SourceType, TargetType); + break; + } + } else if (const auto *ME = Parents[0].get()) { + recordConversion(ME, SourceType, TargetType); + break; + } + Parents = m_context->getParents(Parents[0]); + } + return true; + } + + std::string normalizeTypeName(std::string typeName) { + const std::vector prefixes = {"struct ", "class ", "enum "}; + for (const auto &prefix : prefixes) { + size_t pos = typeName.find(prefix); + if (pos == 0) { + typeName.erase(0, prefix.length()); + break; + } + } + typeName.erase( + std::remove_if(typeName.begin(), typeName.end(), + [](unsigned char c) { return std::isspace(c); }), + typeName.end()); + size_t pos; + while ((pos = typeName.find("_Bool")) != std::string::npos) { + typeName.replace(pos, 5, "bool"); + } + return typeName; + } + + void recordConversion(const clang::FunctionDecl *FD, clang::QualType From, + clang::QualType To) { + std::string FromStr = + normalizeTypeName(From.getCanonicalType().getAsString()); + std::string ToStr = normalizeTypeName(To.getCanonicalType().getAsString()); + m_functionStats[FD][std::make_pair(FromStr, ToStr)]++; + m_totalConversions++; + } + + void printStats(llvm::raw_ostream &OS) { + for (const auto &[func, convs] : m_functionStats) { + OS << "Function `" << func->getName() << "`\n"; + for (const auto &[conv, num] : convs) { + OS << conv.first << " -> " << conv.second << ": " << num << "\n"; + } + } + OS << "Total implicit conversions: " << m_totalConversions << "\n"; + } +}; + +class ImplicitConvConsumer : public clang::ASTConsumer { + +private: + ImplicitConvVisitor m_visitor; + +public: + explicit ImplicitConvConsumer(clang::ASTContext *context) + : m_visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + m_visitor.printStats(llvm::errs()); + } +}; + +class ImplicitConvAction : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ImplicitConvPlugin", "Count implicit type conversions"); diff --git a/clang/compiler-course/kurakin_user_data_type/CMakeLists.txt b/clang/compiler-course/kurakin_user_data_type/CMakeLists.txt new file mode 100644 index 0000000000000..83993472be215 --- /dev/null +++ b/clang/compiler-course/kurakin_user_data_type/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "UserDataTypePlugin") +set(Student "Kurakin_Matvey") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/kurakin_user_data_type/kurakin_user_data_type_plugin.cpp b/clang/compiler-course/kurakin_user_data_type/kurakin_user_data_type_plugin.cpp new file mode 100644 index 0000000000000..e5c33341ed6aa --- /dev/null +++ b/clang/compiler-course/kurakin_user_data_type/kurakin_user_data_type_plugin.cpp @@ -0,0 +1,110 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/STLExtras.h" + +namespace { + +std::string getAccessModifier(clang::AccessSpecifier am){ + if(am == clang::AS_public) return "|public"; + else if(am == clang::AS_private) return "|private"; + else if(am == clang::AS_protected) return "|protected"; + return ""; +} + +class UserDataTypeVisitor final : public clang::RecursiveASTVisitor { +public: + explicit UserDataTypeVisitor(clang::ASTContext *context) : m_context(context) {} + bool VisitCXXRecordDecl(clang::CXXRecordDecl *rd) { + auto &os = llvm::outs(); + + os << rd->getNameAsString(); + if(rd->getNumBases()) { + os << " -> "; + llvm::interleave( + rd->bases(), + os, + [&](const clang::CXXBaseSpecifier &x) { + os << x.getType().getAsString(); + }, + "," + ); + } + os << "\n"; + + os << "|_Fields\n"; + for(const auto &f : rd->fields()) { + os << "| |_ " << f->getName() << " (" << f->getType().getAsString(); + os << getAccessModifier(f->getAccess()); + os << ")\n"; + } + if(rd->fields().empty()) + os << "| |_ (has no fields)\n"; + + os << "|\n"; + + os << "|_Methods\n"; + for(const auto &m : rd->methods()) { + if(m->isImplicit()) continue; + + os << "| |_ " << m->getNameAsString() << " (" << m->getReturnType().getAsString() << "("; + if(m->getNumParams()) { + llvm::interleave( + m->parameters(), + os, + [&](const clang::ParmVarDecl* x) { + os << x->getType().getAsString(); + }, + "," + ); + } + os << ")"; + os << getAccessModifier(m->getAccess()); + + if(m->hasAttr()) os << "|override"; + else if(m->isVirtual()) os << "|virtual"; + if(m->isPureVirtual()) os << "|pure"; + if(m->isStatic()) os << "|static"; + + os << ")\n"; + } + if(rd->methods().empty()) + os << "| |_ (has no methods)\n"; + + return true; + } + +private: + clang::ASTContext *m_context; +}; + +class UserDataTypeConsumer final : public clang::ASTConsumer { +public: + explicit UserDataTypeConsumer(clang::ASTContext *context) : m_visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + UserDataTypeVisitor m_visitor; +}; + +class UserDataTypeAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("UserDataTypePlugin_Kurakin_Matvey_FIIT1_ClangAST", "Print information about the user's data type"); diff --git a/clang/compiler-course/lopatin_i_user_data_type/CMakeLists.txt b/clang/compiler-course/lopatin_i_user_data_type/CMakeLists.txt new file mode 100644 index 0000000000000..d65f2670f4d5f --- /dev/null +++ b/clang/compiler-course/lopatin_i_user_data_type/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "UserDataTypePlugin") +set(Student "LopatinIlya") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/lopatin_i_user_data_type/lopatin_i_user_data_type_plugin.cpp b/clang/compiler-course/lopatin_i_user_data_type/lopatin_i_user_data_type_plugin.cpp new file mode 100644 index 0000000000000..067261f8e6e4e --- /dev/null +++ b/clang/compiler-course/lopatin_i_user_data_type/lopatin_i_user_data_type_plugin.cpp @@ -0,0 +1,115 @@ +#include +#include + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +std::string getAccessSpelling(clang::AccessSpecifier access) { + switch (access) { + case clang::AS_public: return "public"; + case clang::AS_protected: return "protected"; + case clang::AS_private: return "private"; + default: return ""; + } +} + +class UserDataTypeVisitor final : public clang::RecursiveASTVisitor { +public: + explicit UserDataTypeVisitor(clang::ASTContext *context) {} + bool VisitCXXRecordDecl(clang::CXXRecordDecl *D) { + if (!D->isThisDeclarationADefinition() || D->isImplicit()) + return true; + + auto& os = llvm::outs(); + os << D->getName(); + + // classes + if (D->getNumBases()) { + os << " -> "; + bool first = true; + for (const clang::CXXBaseSpecifier &B : D->bases()) { + if (!first) os << ", "; + first = false; + os << B.getType()->getAsCXXRecordDecl()->getName(); + } + } + os << "\n"; + + // fields + os << "|_Fields\n"; + bool hasFields = false; + for (clang::FieldDecl *F : D->fields()) { + hasFields = true; + os << "| |_ " << F->getName() << " (" + << F->getType().getAsString() << "|" + << ::getAccessSpelling(F->getAccess()) << ")\n"; + } + if (!hasFields) os << "| |_ (no fields)\n"; + + // methods + if (D->method_begin() != D->method_end()) { + os << "|_Methods\n"; + for (clang::CXXMethodDecl *M : D->methods()) { + if (M->isImplicit()) continue; + + std::stringstream TypeStr; + TypeStr << M->getReturnType().getAsString() << "("; + for (unsigned i = 0; i < M->getNumParams(); ++i) { + if (i > 0) TypeStr << ", "; + TypeStr << M->getParamDecl(i)->getType().getAsString(); + } + TypeStr << ")"; + + // specs + llvm::SmallVector Specs; + if (M->isVirtual() && !M->hasAttr()) + Specs.push_back("virtual"); + if (M->isPureVirtual()) Specs.push_back("pure"); + if (M->hasAttr()) Specs.push_back("override"); + if (M->isConst()) Specs.push_back("const"); + + os << "| |_ " << M->getNameAsString() << " (" << TypeStr.str() << "|" + << ::getAccessSpelling(M->getAccess()); + for (const auto &S : Specs) + os << "|" << S; + os << ")\n"; + } + } + return true; + } +}; + +class UserDataTypeConsumer final : public clang::ASTConsumer { +public: + explicit UserDataTypeConsumer(clang::ASTContext *context) : m_visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + UserDataTypeVisitor m_visitor; +}; + +class UserDataTypeAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("UserDataTypePlugin_LopatinIlya_FIIT3_ClangAST", "Prints info about user defined data types"); diff --git a/clang/compiler-course/lysov_ivan_1stLabs/CMakeLists.txt b/clang/compiler-course/lysov_ivan_1stLabs/CMakeLists.txt new file mode 100644 index 0000000000000..64b1eff998eda --- /dev/null +++ b/clang/compiler-course/lysov_ivan_1stLabs/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "unUsedVarPlugin") +set(Student "LysovIvan") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/lysov_ivan_1stLabs/lysov_ivan_1stLabs.cpp b/clang/compiler-course/lysov_ivan_1stLabs/lysov_ivan_1stLabs.cpp new file mode 100644 index 0000000000000..a06bd563d2324 --- /dev/null +++ b/clang/compiler-course/lysov_ivan_1stLabs/lysov_ivan_1stLabs.cpp @@ -0,0 +1,76 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Attr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +class UnusedVarMyVisitor final + : public clang::RecursiveASTVisitor { +public: + UnusedVarMyVisitor(clang::ASTContext *ctx, clang::Rewriter &rwrt) + : context(ctx), rewriter(rwrt) {} + bool VisitVarDecl(clang::VarDecl *var) { + if (!var->isUsed() && !var->hasAttr()) { + clang::SourceLocation loc = var->getSourceRange().getBegin(); + rewriter.InsertText(loc, "[[maybe_unused]]"); + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *param) { + if (!param->isUsed() && !param->hasAttr()) { + clang::SourceLocation loc = param->getSourceRange().getBegin(); + rewriter.InsertText(loc, "[[maybe_unused]]"); + } + return true; + } + +private: + clang::ASTContext *context; + clang::Rewriter &rewriter; +}; + +class UnusedVarConsumer final : public clang::ASTConsumer { +public: + UnusedVarConsumer(clang::ASTContext *ctx, clang::Rewriter &rwrt) + : Label(ctx, rwrt) {} + + void HandleTranslationUnit(clang::ASTContext &ctx) override { + Label.TraverseDecl(ctx.getTranslationUnitDecl()); + } + +private: + UnusedVarMyVisitor Label; +}; + +class UnusedVarAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), rewriter); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } + + void EndSourceFileAction() override { + rewriter.getEditBuffer(rewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + +private: + clang::Rewriter rewriter; +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("unUsedVarPlugin_LysovIvan_FIIT3_ClangAST", + "The plugin detects unused variables and function parameters in code and " + "adds the [[maybe_unused]] attribute."); diff --git a/clang/compiler-course/mironov_a_lab1/CMakeLists.txt b/clang/compiler-course/mironov_a_lab1/CMakeLists.txt new file mode 100644 index 0000000000000..d2df09e091b55 --- /dev/null +++ b/clang/compiler-course/mironov_a_lab1/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "Lab1_AST") +set(Student "Mironov_Arseniy") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/mironov_a_lab1/source.cpp b/clang/compiler-course/mironov_a_lab1/source.cpp new file mode 100644 index 0000000000000..0bf14008e4a04 --- /dev/null +++ b/clang/compiler-course/mironov_a_lab1/source.cpp @@ -0,0 +1,108 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include + +namespace { +class CastVisitor final : public clang::RecursiveASTVisitor { +public: + CastVisitor() {} + + bool VisitFunctionDecl(clang::FunctionDecl *function) { + scope_name_ = function->getNameAsString(); + return true; + } + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *cast) { + + clang::CastKind cast_kind = cast->getCastKind(); + + if (cast_kind == clang::CK_FunctionToPointerDecay || + cast_kind == clang::CK_NoOp || cast_kind == clang::CK_LValueToRValue) { + return true; + } + + // CanonicalType needs not to use any type qualifiers + std::string source_type = + cast->getSubExpr()->getType().getCanonicalType().getAsString(); + std::string target_type = cast->getType().getCanonicalType().getAsString(); + + // needs if cast int->int (it is possible cuz type qualifiers); + if (source_type == target_type) { + return true; + } + + casts_[scope_name_][std::make_pair(source_type, target_type)]++; + return true; + } + + bool VisitCXXConstructExpr(clang::CXXConstructExpr *construct) { + + std::string target_type = + construct->getType().getCanonicalType().getAsString(); + + for (const auto *arg : construct->arguments()) { + std::string source_type = arg->getType().getCanonicalType().getAsString(); + + casts_[scope_name_][std::make_pair(source_type, target_type)]++; + } + return true; + } + + void Results() { + for (const auto &[func, table] : casts_) { + if (func == "global_scope") { + llvm::outs() << "In global scope\n"; + } else { + llvm::outs() << "In function: " << func << '\n'; + } + for (const auto &[types, value] : table) { + llvm::outs() << types.first << " -> " << types.second << ": " << value + << '\n'; + } + } + } + +private: + // table: function: {type1, type2}: a number of implicit casts + std::map, int>> + casts_; + std::string scope_name_ = "global_scope"; +}; + +class CastConsumer final : public clang::ASTConsumer { +public: + explicit CastConsumer() {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + visitor_.TraverseDecl(context.getTranslationUnitDecl()); + visitor_.Results(); + } + +private: + CastVisitor visitor_; +}; + +class CastAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("Lab1_AST_Mironov_Arseniy_FIIT1_ClangAST", + "The plugin counts the number of implicit conversations and returns it"); diff --git a/clang/compiler-course/plekhanov_unused_variables/CMakeLists.txt b/clang/compiler-course/plekhanov_unused_variables/CMakeLists.txt new file mode 100644 index 0000000000000..fc3eb378d423e --- /dev/null +++ b/clang/compiler-course/plekhanov_unused_variables/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "FindUnused") +set(Student "Plekhanov_Daniil") +set(Group "FIIT2") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/plekhanov_unused_variables/plekhanov.cpp b/clang/compiler-course/plekhanov_unused_variables/plekhanov.cpp new file mode 100644 index 0000000000000..d1229531eb0c6 --- /dev/null +++ b/clang/compiler-course/plekhanov_unused_variables/plekhanov.cpp @@ -0,0 +1,78 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Attr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +class UnusedVariablesVisitor final + : public clang::RecursiveASTVisitor { +public: + UnusedVariablesVisitor(clang::ASTContext *Context, clang::Rewriter &R) + : m_context(Context), TheRewriter(R) {} + + bool VisitParamVarDecl(clang::ParmVarDecl *param) { + if (!param->isUsed() && !param->hasAttr()) { + clang::SourceLocation loc = param->getSourceRange().getBegin(); + TheRewriter.InsertText(loc, "[[maybe_unused]] "); + } + return true; + } + + bool VisitVarDecl(clang::VarDecl *var) { + if (!var->isUsed() && !var->hasAttr()) { + clang::SourceLocation loc = var->getSourceRange().getBegin(); + TheRewriter.InsertText(loc, "[[maybe_unused]] "); + } + return true; + } + +private: + clang::ASTContext *m_context; + clang::Rewriter &TheRewriter; +}; + +class UnusedVariablesConsumer final : public clang::ASTConsumer { +public: + UnusedVariablesConsumer(clang::ASTContext *Context, clang::Rewriter &R) + : Visitor(Context, R) {} + + void HandleTranslationUnit(clang::ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } + +private: + UnusedVariablesVisitor Visitor; +}; + +class UnusedVariablesAction final : public clang::PluginASTAction { +private: + clang::Rewriter TheRewriter; + +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef) override { + TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); + return std::make_unique(&CI.getASTContext(), + TheRewriter); + } + + void EndSourceFileAction() override { + TheRewriter.getEditBuffer(TheRewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + + bool ParseArgs(const clang::CompilerInstance &CI, + const std::vector &args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("FindUnused", + "Find unused variables in code and mark them as the /MAYBE UNUSED/"); diff --git a/clang/compiler-course/rezantseva_a_prefixes/CMakeLists.txt b/clang/compiler-course/rezantseva_a_prefixes/CMakeLists.txt new file mode 100644 index 0000000000000..618b95297bef3 --- /dev/null +++ b/clang/compiler-course/rezantseva_a_prefixes/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "PrefixesPlugin") +set(Student "RezantsevaAnastasia") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/rezantseva_a_prefixes/rezantseva_a_prefixes.cpp b/clang/compiler-course/rezantseva_a_prefixes/rezantseva_a_prefixes.cpp new file mode 100644 index 0000000000000..b1a5d42d7c757 --- /dev/null +++ b/clang/compiler-course/rezantseva_a_prefixes/rezantseva_a_prefixes.cpp @@ -0,0 +1,133 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace { +class PrefixVisitor : public clang::RecursiveASTVisitor { +public: + explicit PrefixVisitor(clang::ASTContext *context, clang::Rewriter &rewriter) + : m_rewriter(rewriter) {} + + bool VisitVarDecl(clang::VarDecl *var) { + if (!var) { + return true; + } + if (var->getName().empty()) { + return true; + } + std::string prefix; + if (var->isStaticLocal()) { + prefix = "static_"; + } else if (var->isLocalVarDecl()) { + prefix = "local_"; + } else if (var->hasGlobalStorage()) { + prefix = "global_"; + } + + if (!prefix.empty()) { + std::string newName = prefix + var->getName().str(); + renameVar(var, newName); + m_renamedVars[var] = newName; + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *param) { + if (!param) { + return true; + } + if (param->getName().empty()) { + return true; + } + std::string newName = "param_" + param->getName().str(); + renameVar(param, newName); + m_renamedVars[param] = newName; + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *expr) { + if (!expr) { + return true; + } + auto *decl = expr->getDecl(); + if (!decl) { + return true; + } + if (decl->getName().empty()) { + return true; + } + + if (auto *var = clang::dyn_cast(decl)) { + auto it = m_renamedVars.find(var); + if (it != m_renamedVars.end()) { + m_rewriter.ReplaceText(expr->getLocation(), var->getName().size(), + it->second); + } + } + return true; + } + +private: + clang::Rewriter &m_rewriter; + std::unordered_map m_renamedVars; + + void renameVar(clang::VarDecl *var, const std::string &newName) { + m_rewriter.ReplaceText(var->getLocation(), var->getName().size(), newName); + } +}; + +class PrefixConsumer : public clang::ASTConsumer { +public: + explicit PrefixConsumer(clang::ASTContext *context, clang::Rewriter &rewriter) + : m_visitor(context, rewriter), m_rewriter(rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + m_rewriter.getEditBuffer(context.getSourceManager().getMainFileID()) + .write(llvm::outs()); + } + +private: + PrefixVisitor m_visitor; + clang::Rewriter &m_rewriter; +}; + +class PrefixAction : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + if (m_shouldExit) { + return nullptr; + } + + m_rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), m_rewriter); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + for (const auto &arg : args) { + if (arg == "--help") { + llvm::outs() << "PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST:\n"; + llvm::outs() << "This plugin adds appropriate prefixes to variables " + "and parameters in the code.\n"; + m_shouldExit = true; + return true; + } + } + return true; + } + +private: + clang::Rewriter m_rewriter; + bool m_shouldExit = false; +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST", + "Adds appropriate prefixes to objects and parameters"); \ No newline at end of file diff --git a/clang/compiler-course/savchenko_m_l1_v2/CMakeLists.txt b/clang/compiler-course/savchenko_m_l1_v2/CMakeLists.txt new file mode 100644 index 0000000000000..4d7686fd764fd --- /dev/null +++ b/clang/compiler-course/savchenko_m_l1_v2/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "UnusedVariables") +set(Student "Savchenko_Maxim") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/savchenko_m_l1_v2/savchenko_m_l1_v2.cpp b/clang/compiler-course/savchenko_m_l1_v2/savchenko_m_l1_v2.cpp new file mode 100644 index 0000000000000..87ca54c2360f5 --- /dev/null +++ b/clang/compiler-course/savchenko_m_l1_v2/savchenko_m_l1_v2.cpp @@ -0,0 +1,94 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Attr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +class UnusedVarsVisitor final + : public clang::RecursiveASTVisitor { +public: + explicit UnusedVarsVisitor(clang::ASTContext *context, + clang::Rewriter &rewriter) + : m_context(context), m_rewriter(rewriter) {} + + bool VisitParamVarDecl(clang::ParmVarDecl *param) { + if (!param->isUsed() && !param->hasAttr()) { + clang::SourceLocation location = param->getBeginLoc(); + if (clang::Rewriter::isRewritable(location)) { + m_rewriter.InsertTextBefore(location, "[[maybe_unused]] "); + } else { + return false; + } + } + return true; + } + + bool VisitVarDecl(clang::VarDecl *var) { + if (!var->isUsed() && !var->hasAttr()) { + clang::SourceLocation location = var->getBeginLoc(); + if (clang::Rewriter::isRewritable(location)) { + m_rewriter.InsertTextBefore(location, "[[maybe_unused]] "); + } else { + return false; + } + } + return true; + } + +private: + clang::ASTContext *m_context; + clang::Rewriter &m_rewriter; +}; + +class UnusedVarsConsumer final : public clang::ASTConsumer { +public: + explicit UnusedVarsConsumer(clang::ASTContext *context, + clang::Rewriter &rewriter) + : m_visitor(context, rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + UnusedVarsVisitor m_visitor; +}; + +class UnusedVarsAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + m_rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), + m_rewriter); + } + + void EndSourceFileAction() override { + m_rewriter.getEditBuffer(m_rewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + for (const auto &arg : args) { + if (arg == "-h" || arg == "--help") { + llvm::outs() << "The plugin adds the [[maybe_unused]] flag to " + "variables and parameters that are not in use.\n"; + return true; + } + } + return true; + } + +private: + clang::Rewriter m_rewriter; +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("savchenko_m_UnusedVars_plugin", + "Adding the [[maybe_unused]] flag to variables and parameters if they " + "are not in use."); diff --git a/clang/compiler-course/shkurinskaya_e_var_renaming/CMakeLists.txt b/clang/compiler-course/shkurinskaya_e_var_renaming/CMakeLists.txt new file mode 100644 index 0000000000000..2ba4b4c8b0ca5 --- /dev/null +++ b/clang/compiler-course/shkurinskaya_e_var_renaming/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClangAST_4") +set(Student "Shkurinskaya_Elena") +set(Group "FIIT2") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/shkurinskaya_e_var_renaming/shkurinskaya_e_var_renaming.cpp b/clang/compiler-course/shkurinskaya_e_var_renaming/shkurinskaya_e_var_renaming.cpp new file mode 100644 index 0000000000000..a8d890d9c25b5 --- /dev/null +++ b/clang/compiler-course/shkurinskaya_e_var_renaming/shkurinskaya_e_var_renaming.cpp @@ -0,0 +1,85 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +class PrefixVisitor final : public clang::RecursiveASTVisitor { +public: + explicit PrefixVisitor(clang::ASTContext *context, clang::Rewriter &rewriter) + : m_rewriter(rewriter) {} + + bool VisitVarDecl(clang::VarDecl *VD) { + if (VD->getLocation().isInvalid() || !VD->getIdentifier()) + return true; + + std::string newName = VD->getNameAsString(); + if (VD->isStaticLocal()) { + newName = "static_" + newName; + } else if (VD->hasGlobalStorage() && !VD->isStaticLocal()) { + newName = "global_" + newName; + } else if (VD->isLocalVarDecl() && !VD->isStaticLocal()) { + newName = "local_" + newName; + } + + if (newName != VD->getNameAsString()) { + m_rewriter.ReplaceText(VD->getLocation(), VD->getNameAsString().size(), + newName); + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *PVD) { + if (PVD->getLocation().isInvalid() || !PVD->getIdentifier()) + return true; + + std::string newName = "param_" + PVD->getNameAsString(); + m_rewriter.ReplaceText(PVD->getLocation(), PVD->getNameAsString().size(), + newName); + return true; + } + +private: + clang::Rewriter &m_rewriter; +}; + +class PrefixConsumer final : public clang::ASTConsumer { +public: + explicit PrefixConsumer(clang::ASTContext *context, clang::Rewriter &rewriter) + : m_visitor(context, rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + PrefixVisitor m_visitor; +}; + +class PrefixAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + m_rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), m_rewriter); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } + + void EndSourceFileAction() override { + m_rewriter.getEditBuffer(m_rewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + +private: + clang::Rewriter m_rewriter; +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ClangAST_4", "Adding prefixes to variables"); diff --git a/clang/compiler-course/shulpin_i_implicit_conversion/CMakeLists.txt b/clang/compiler-course/shulpin_i_implicit_conversion/CMakeLists.txt new file mode 100644 index 0000000000000..d1920484cacab --- /dev/null +++ b/clang/compiler-course/shulpin_i_implicit_conversion/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClangAST_Lab") +set(Student "ShulpinIlya") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/shulpin_i_implicit_conversion/shulpin_i_ClangAST_lab.cpp b/clang/compiler-course/shulpin_i_implicit_conversion/shulpin_i_ClangAST_lab.cpp new file mode 100644 index 0000000000000..504a60e96f2a9 --- /dev/null +++ b/clang/compiler-course/shulpin_i_implicit_conversion/shulpin_i_ClangAST_lab.cpp @@ -0,0 +1,159 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include + +namespace { +class ImplicitVisitor final + : public clang::RecursiveASTVisitor { +public: + ImplicitVisitor() = default; + + bool VisitFunctionDecl(clang::FunctionDecl *Func) { + FunctionToCheck = Func->getNameInfo().getName().getAsString(); + return true; + } + + bool VisitCXXConstructExpr(clang::CXXConstructExpr *Ctor) { + if (!Ctor || Ctor->getNumArgs() == 0) { + return true; + } + + const auto *FirstArg = Ctor->getArg(0); + if (!FirstArg) { + return true; + } + + clang::QualType FromType = FirstArg->getType(); + clang::QualType ToType = Ctor->getType(); + + static std::unordered_map TypeComparisonCache; + std::string FromStr = FromType.getAsString(); + std::string ToStr = ToType.getAsString(); + + TypeComparisonCache.try_emplace(FromStr + ToStr, FromType == ToType); + + if (TypeComparisonCache[FromStr + ToStr]) { + return true; + } + + CastInfo.emplace_back(CastAgrigation{FunctionToCheck, std::move(FromStr), + std::move(ToStr), 1}); + return true; + } + + clang::QualType getRealType(clang::QualType Type) { + while (Type->getAs()) { + Type = Type->getAs()->getDecl()->getUnderlyingType(); + } + return Type.getCanonicalType(); + } + + bool VisitImplicitCastExpr(clang::ImplicitCastExpr *Cast) { + if (!Cast) { + return true; + } + + if (const auto *SubExpr = Cast->getSubExpr()) { + clang::CastKind Kind = Cast->getCastKind(); + if ((Kind == clang::CK_NoOp) || (Kind == clang::CK_LValueToRValue) || + (Kind == clang::CK_FunctionToPointerDecay)) { + return true; + } + + clang::QualType FromType = getRealType(SubExpr->getType()); + clang::QualType ToType = getRealType(Cast->getType()); + + if (!FromType.isNull() && !ToType.isNull() && + FromType.getTypePtr() != ToType.getTypePtr()) { + + std::string FromStr = FromType.getAsString(); + std::string ToStr = ToType.getAsString(); + + auto it = std::find_if( + CastInfo.begin(), CastInfo.end(), [&](const CastAgrigation &entry) { + return entry.FuncName == FunctionToCheck && + entry.FromType == FromStr && entry.ToType == ToStr; + }); + + if (it != CastInfo.end()) { + it->CastNum++; + } else { + CastInfo.emplace_back(CastAgrigation{ + FunctionToCheck, std::move(FromStr), std::move(ToStr), 1}); + } + } + } + return true; + } + + void CastsResult() { + std::string LastFunction; + + std::size_t totalCasts = + std::accumulate(CastInfo.begin(), CastInfo.end(), 0, + [](std::size_t sum, const CastAgrigation &cast) { + return sum + cast.CastNum; + }); + + for (const auto &Entry : CastInfo) { + if (Entry.FuncName != LastFunction) { + llvm::outs() << "Function " << Entry.FuncName << "\n"; + LastFunction = Entry.FuncName; + } + llvm::outs() << Entry.getCastDescription() << "\n"; + } + llvm::outs() << "Summary of total conversions: " << totalCasts << "\n"; + } + +private: + struct CastAgrigation { + std::string FuncName; + std::string FromType; + std::string ToType; + std::size_t CastNum; + + std::string getCastDescription() const { + return FromType + " -> " + ToType + ": " + std::to_string(CastNum); + } + }; + std::string FunctionToCheck; + std::vector CastInfo; +}; + +class ImplicitCastConsumer final : public clang::ASTConsumer { +public: + ImplicitCastConsumer() = default; + + void HandleTranslationUnit(clang::ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + Visitor.CastsResult(); + } + +private: + ImplicitVisitor Visitor; +}; + +class ImplicitCastAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef) override { + return std::make_unique(); + } + + bool ParseArgs(const clang::CompilerInstance &CI, + const std::vector &Args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ClangAST_Lab_ShulpinIlya_FIIT1_ClangAST", + "Counts implicit type conversions"); diff --git a/clang/compiler-course/solovev_a/CMakeLists.txt b/clang/compiler-course/solovev_a/CMakeLists.txt new file mode 100644 index 0000000000000..01dba9da886bc --- /dev/null +++ b/clang/compiler-course/solovev_a/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "ClangAST_1") +set(Student "Solovev_a") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/solovev_a/solovev_a.cpp b/clang/compiler-course/solovev_a/solovev_a.cpp new file mode 100644 index 0000000000000..428bfa0037f64 --- /dev/null +++ b/clang/compiler-course/solovev_a/solovev_a.cpp @@ -0,0 +1,111 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace { + +class PrefixVariableNames + : public clang::RecursiveASTVisitor { +public: + explicit PrefixVariableNames(clang::Rewriter &rewriter) + : rewriter_(rewriter) {} + + bool VisitVarDecl(clang::VarDecl *varDecl) { + if (!varDecl->getName().empty()) { + std::string prefix = determinePrefix(varDecl); + if (!prefix.empty() && varDecl->getName().str().find(prefix) != 0) { + std::string name = varDecl->getName().str(); + std::string mod_name = prefix + name; + renamedVariables_[name] = mod_name; + rewriter_.ReplaceText(varDecl->getLocation(), name.length(), mod_name); + } + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *paramVarDecl) { + if (!paramVarDecl->getName().empty()) { + std::string name = paramVarDecl->getName().str(); + std::string mod_name = "param_" + name; + renamedVariables_[name] = mod_name; + rewriter_.ReplaceText(paramVarDecl->getLocation(), name.length(), + mod_name); + } + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *expr) { + auto decl = expr->getDecl(); + if (decl) { + std::string name = decl->getName().str(); + auto it = renamedVariables_.find(name); + if (it != renamedVariables_.end()) { + rewriter_.ReplaceText(expr->getLocation(), name.length(), it->second); + } + } + return true; + } + +private: + std::string determinePrefix(clang::VarDecl *varDecl) { + if (varDecl->isStaticLocal()) { + return "static_"; + } else if (varDecl->isLocalVarDecl()) { + return "local_"; + } else if (varDecl->hasGlobalStorage()) { + if (varDecl->getStorageClass() == clang::SC_Static) { + return "static_global_"; + } + return "global_"; + } + return ""; + } + + clang::Rewriter &rewriter_; + std::unordered_map renamedVariables_; +}; + +class PrefixConsumer : public clang::ASTConsumer { +public: + explicit PrefixConsumer(clang::Rewriter &rewriter) : visitor_(rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + visitor_.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + PrefixVariableNames visitor_; +}; + +class PrefixAction : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + rewriter_.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(rewriter_); + } + + bool ParseArgs(const clang::CompilerInstance &, + const std::vector &) override { + return true; + } + + void EndSourceFileAction() override { + rewriter_.getEditBuffer(rewriter_.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + +private: + clang::Rewriter rewriter_; +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("ClangAST_1_Solovev_a_FIIT1_ClangAST", + "Prefixes variables based on type"); diff --git a/clang/compiler-course/solovyev_d_unused_variable/CMakeLists.txt b/clang/compiler-course/solovyev_d_unused_variable/CMakeLists.txt new file mode 100644 index 0000000000000..8ab892226ec37 --- /dev/null +++ b/clang/compiler-course/solovyev_d_unused_variable/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "UnusedVariable") +set(Student "Solovyev_Danila") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/solovyev_d_unused_variable/solovyev_d_unused_variable_plugin.cpp b/clang/compiler-course/solovyev_d_unused_variable/solovyev_d_unused_variable_plugin.cpp new file mode 100644 index 0000000000000..ae05e2698f360 --- /dev/null +++ b/clang/compiler-course/solovyev_d_unused_variable/solovyev_d_unused_variable_plugin.cpp @@ -0,0 +1,81 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Attr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +namespace { +class UnusedVisitor final : public clang::RecursiveASTVisitor { +public: + explicit UnusedVisitor(clang::ASTContext *context, clang::Rewriter &Rewriter) + : m_context(context), MRewriter(Rewriter) {} + bool VisitVarDecl(clang::VarDecl *var) { + if (!var->isUsed() && !var->hasAttr()) { + MRewriter.InsertText(var->getSourceRange().getBegin(), + "[[maybe_unused]] ", true, true); + var->addAttr(clang::UnusedAttr::Create(*m_context)); + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *param) { + if (!param->isUsed() && !param->hasAttr()) { + MRewriter.InsertText(param->getSourceRange().getBegin(), + "[[maybe_unused]] ", true, true); + param->addAttr(clang::UnusedAttr::Create(*m_context)); + } + return true; + } + +private: + clang::Rewriter &MRewriter; + clang::ASTContext *m_context; +}; + +class UnusedConsumer final : public clang::ASTConsumer { +public: + explicit UnusedConsumer(clang::ASTContext *context, clang::Rewriter &Rewriter) + : um_visitor(context, Rewriter) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + um_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + UnusedVisitor um_visitor; +}; + +class UnusedAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + MRewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), MRewriter); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + for (const auto &arg : args) { + if (arg == "--help") { + llvm::outs() << "Marking unused variables and function parameters as " + "[[maybe_unused]]\n"; + return true; + } + } + return true; + } + + void EndSourceFileAction() override { + MRewriter.getEditBuffer(MRewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + +private: + clang::Rewriter MRewriter; +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("unused_variable_plugin", + "Marking unused variables and function parameters as [[maybe_unused]]"); diff --git a/clang/compiler-course/sozonov_i_user_defined_data_type/CMakeLists.txt b/clang/compiler-course/sozonov_i_user_defined_data_type/CMakeLists.txt new file mode 100644 index 0000000000000..73c90c6e2f38c --- /dev/null +++ b/clang/compiler-course/sozonov_i_user_defined_data_type/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "UserDefinedDataTypePlugin") +set(Student "SozonovIlya") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/sozonov_i_user_defined_data_type/sozonov_i_user_defined_data_type_plugin.cpp b/clang/compiler-course/sozonov_i_user_defined_data_type/sozonov_i_user_defined_data_type_plugin.cpp new file mode 100644 index 0000000000000..a3c858d3d8b45 --- /dev/null +++ b/clang/compiler-course/sozonov_i_user_defined_data_type/sozonov_i_user_defined_data_type_plugin.cpp @@ -0,0 +1,157 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +std::string AccessToString(clang::AccessSpecifier access) { + switch (access) { + case clang::AS_public: + return "public"; + case clang::AS_protected: + return "protected"; + case clang::AS_private: + return "private"; + default: + return ""; + } +} + +class ClassInfoVisitor final + : public clang::RecursiveASTVisitor { +public: + explicit ClassInfoVisitor(clang::ASTContext *context) {} + bool VisitCXXRecordDecl(clang::CXXRecordDecl *record) { + if (!record->isThisDeclarationADefinition() || record->isImplicit()) + return true; + + auto &output = llvm::outs(); + output << record->getQualifiedNameAsString(); + + PrintBaseClassesInfo(output, record); + output << "\n|_Fields\n"; + PrintFieldsInfo(output, record); + output << "|\n|_Methods\n"; + PrintMethodsInfo(output, record); + output << "|\n|_Nested Types\n"; + PrintNestedTypesInfo(output, record); + output << "\n"; + + return true; + } + +private: + void PrintBaseClassesInfo(llvm::raw_ostream &output, + const clang::CXXRecordDecl *record) { + if (record->getNumBases() == 0) + return; + + llvm::SmallVector bases; + for (const auto &base : record->bases()) + if (auto *base_decl = base.getType()->getAsCXXRecordDecl()) + bases.push_back(base_decl->getQualifiedNameAsString()); + + output << " -> " << llvm::join(bases, ", "); + } + + void PrintFieldsInfo(llvm::raw_ostream &output, + const clang::CXXRecordDecl *record) { + if (record->field_empty()) { + output << "| |_ (no fields)\n"; + return; + } + + for (const auto *field : record->fields()) + output << "| |_ " << field->getNameAsString() << " (" + << field->getType().getAsString() << "|" + << AccessToString(field->getAccess()) << ")\n"; + } + + void PrintMethodsInfo(llvm::raw_ostream &output, + const clang::CXXRecordDecl *record) { + if (record->method_begin() == record->method_end()) { + output << "| |_ (no methods)\n"; + return; + } + + for (const auto *method : record->methods()) { + if (method->isImplicit()) + continue; + + output << "| |_ " << method->getNameAsString() << " (" + << method->getReturnType().getAsString() << "("; + + llvm::interleaveComma(method->parameters(), output, + [](const clang::ParmVarDecl *param) { + llvm::outs() << param->getType().getAsString(); + }); + + output << ")|" << AccessToString(method->getAccess()); + + if (method->isVirtual() && !method->hasAttr()) + output << "|virtual"; + if (method->isPureVirtual()) + output << "|pure"; + if (method->hasAttr()) + output << "|override"; + if (method->isConst()) + output << "|const"; + + output << ")\n"; + } + } + + void PrintNestedTypesInfo(llvm::raw_ostream &output, + const clang::CXXRecordDecl *record) { + bool has_nested_types = false; + + for (const auto *decl : record->decls()) { + if (const auto *nested = llvm::dyn_cast(decl)) { + if (!nested->isThisDeclarationADefinition() || nested->isImplicit()) + continue; + + if (!has_nested_types) { + has_nested_types = true; + } + output << "| |_ " << nested->getNameAsString() << "\n"; + } + } + + if (!has_nested_types) + output << "| |_ (no nested types)\n"; + } +}; + +class ClassInfoConsumer final : public clang::ASTConsumer { +public: + explicit ClassInfoConsumer(clang::ASTContext *context) + : class_visitor(context) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + class_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + ClassInfoVisitor class_visitor; +}; + +class ClassInfoAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("user_defined_data_type_plugin", + "Prints information about the user defined data type: 1) Fields; 2) " + "Methods; 3) Basic classes"); diff --git a/clang/compiler-course/suvorov_d_lab1_var4/CMakeLists.txt b/clang/compiler-course/suvorov_d_lab1_var4/CMakeLists.txt new file mode 100644 index 0000000000000..e89fc8a9a66c9 --- /dev/null +++ b/clang/compiler-course/suvorov_d_lab1_var4/CMakeLists.txt @@ -0,0 +1,18 @@ +set(Title "AddingPrefixesPlugin") +set(Student "Suvorov_Dmitrii") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_ClangAST") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) +add_llvm_library(${TARGET_NAME} MODULE ${SOURCES} PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS Support) + clang_target_link_libraries(${TARGET_NAME} PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "${TARGET_NAME}" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/compiler-course/suvorov_d_lab1_var4/suvorov_d_adding_prefs.cpp b/clang/compiler-course/suvorov_d_lab1_var4/suvorov_d_adding_prefs.cpp new file mode 100755 index 0000000000000..1a7d4a780c527 --- /dev/null +++ b/clang/compiler-course/suvorov_d_lab1_var4/suvorov_d_adding_prefs.cpp @@ -0,0 +1,154 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace { +class RenameVisitor final : public clang::RecursiveASTVisitor { +public: + RenameVisitor(clang::ASTContext *context, clang::Rewriter &rewriter, + bool logChanges) + : m_rewriter(rewriter), m_logChanges(logChanges) {} + + std::string getPrefixForVarDecl(const clang::VarDecl *varDecl) const { + if (varDecl->isStaticLocal()) { + return "static_"; + } else if (varDecl->hasGlobalStorage() && !varDecl->isStaticLocal()) { + return "global_"; + } else if (varDecl->isLocalVarDecl() && !varDecl->isStaticLocal()) { + return "local_"; + } + return ""; + } + + bool VisitVarDecl(clang::VarDecl *varDecl) { + if (varDecl->getLocation().isInvalid() || !varDecl->getIdentifier()) + return true; + + const std::string originalName = varDecl->getNameAsString(); + const std::string prefix = getPrefixForVarDecl(varDecl); + + if (!prefix.empty() && originalName.find(prefix) != 0) { + const std::string updatedName = prefix + originalName; + m_nameMap[varDecl] = updatedName; + m_rewriter.ReplaceText(varDecl->getLocation(), originalName.size(), + updatedName); + + if (m_logChanges) { + llvm::outs() << "Renamed variable at " + << varDecl->getLocation().printToString( + m_rewriter.getSourceMgr()) + << ": " << originalName << " -> " << updatedName << "\n"; + } + } + return true; + } + + bool VisitParmVarDecl(clang::ParmVarDecl *paramDecl) { + if (paramDecl->getLocation().isInvalid() || !paramDecl->getIdentifier()) + return true; + + const std::string originalName = paramDecl->getNameAsString(); + const std::string prefix = "param_"; + + if (originalName.find(prefix) != 0) { + const std::string updatedName = prefix + originalName; + m_nameMap[paramDecl] = updatedName; + m_rewriter.ReplaceText(paramDecl->getLocation(), originalName.size(), + updatedName); + + if (m_logChanges) { + llvm::outs() << "Renamed parameter at " + << paramDecl->getLocation().printToString( + m_rewriter.getSourceMgr()) + << ": " << originalName << " -> " << updatedName << "\n"; + } + } + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *declRef) { + if (auto *varDecl = llvm::dyn_cast(declRef->getDecl())) { + auto it = m_nameMap.find(varDecl); + if (it != m_nameMap.end()) { + const std::string originalName = varDecl->getNameAsString(); + const std::string updatedName = it->second; + m_rewriter.ReplaceText(declRef->getLocation(), originalName.size(), + updatedName); + + if (m_logChanges) { + llvm::outs() << "Updated reference at " + << declRef->getLocation().printToString( + m_rewriter.getSourceMgr()) + << ": " << originalName << " -> " << updatedName << "\n"; + } + } + } + return true; + } + +private: + clang::Rewriter &m_rewriter; + bool m_logChanges; + std::unordered_map m_nameMap; +}; + +class RenameConsumer final : public clang::ASTConsumer { +public: + RenameConsumer(clang::ASTContext *context, clang::Rewriter &rewriter, + bool logChanges) + : m_visitor(context, rewriter, logChanges) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + RenameVisitor m_visitor; +}; + +class RenameAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + m_rewriter.setSourceMgr(ci.getSourceManager(), ci.getLangOpts()); + return std::make_unique(&ci.getASTContext(), m_rewriter, + m_logChanges); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + for (const auto &arg : args) { + if (arg == "--help") { + llvm::outs() + << "Rename Plugin - Adds prefixes to variables and parameters.\n" + << "Usage:\n" + << " --no-log Disable logging of changes\n" + << " --help Show this help message\n"; + return true; + } else if (arg == "--no-log") { + m_logChanges = false; + } + } + return true; + } + + void EndSourceFileAction() override { + m_rewriter.getEditBuffer(m_rewriter.getSourceMgr().getMainFileID()) + .write(llvm::outs()); + } + +private: + clang::Rewriter m_rewriter; + bool m_logChanges = true; +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST", + "Renames variables and parameters with appropriate prefixes"); diff --git a/clang/test/compiler-course/Kholin_K_prefixes/Kholin_K_prefixes_test.cpp b/clang/test/compiler-course/Kholin_K_prefixes/Kholin_K_prefixes_test.cpp new file mode 100644 index 0000000000000..34cac25e4f2b4 --- /dev/null +++ b/clang/test/compiler-course/Kholin_K_prefixes/Kholin_K_prefixes_test.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/PrefixesPlugin_KholinKirill_FIIT3_ClangAST%pluginext -plugin PrefixesPlugin_KholinKirill_FIIT3_ClangAST %s -fsyntax-only 2>&1 | FileCheck -v %s + +// CHECK: Found variable: var1 -> global_var1 at 18:5 +// CHECK-NEXT: Found variable: var3 -> global_var3 at 19:14 +// CHECK-NEXT: Found variable: ll -> global_ll at 20:21 +// CHECK-NEXT: Found variable: a -> param_a at 21:13 +// CHECK-NEXT: Found variable: b -> param_b at 21:20 +// CHECK-NEXT: Found variable: var2 -> static_var2 at 22:14 +// CHECK-NEXT: Found variable: var3 -> local_var3 at 23:7 +// CHECK-NEXT: Found variable: var2 -> static_var2 at 24:5 +// CHECK-NEXT: Found variable: a -> param_a at 25:10 +// CHECK-NEXT: Found variable: b -> param_b at 25:14 +// CHECK-NEXT: Found variable: var1 -> global_var1 at 25:18 +// CHECK-NEXT: Found variable: var2 -> static_var2 at 25:25 +// CHECK-NEXT: Found variable: var3 -> local_var3 at 25:32 +// CHECK-NEXT: Found variable: ll -> global_ll at 25:39 + +int var1 = 0; +extern float var3; +constexpr long long ll = 1L; +int foo(int a, int b) { + static int var2 = 0; + int var3 = 123; + ++var2; + return a + b + var1 + var2 + var3 + ll; +} diff --git a/clang/test/compiler-course/Shurigin_S_FI1_ClangAst_var4_test/ShuriginS_AST.cpp b/clang/test/compiler-course/Shurigin_S_FI1_ClangAst_var4_test/ShuriginS_AST.cpp new file mode 100644 index 0000000000000..5e3e15c9ae007 --- /dev/null +++ b/clang/test/compiler-course/Shurigin_S_FI1_ClangAst_var4_test/ShuriginS_AST.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_1_ShuriginS_FIIT1_ClangAST%pluginext -plugin ClangAST_1_ShuriginS_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s + +// CHECK: int static global_Var1 = 0; +// CHECK-NEXT: extern int global_Var3; +// CHECK-NEXT: int rA(int param_A) { +// CHECK-NEXT: return -param_A; +// CHECK-NEXT: } +// CHECK-NEXT: int static foo(int param_A, int param_B) { +// CHECK-NEXT: static int static_Var2 = 0; +// CHECK-NEXT: int local_Var3 = 123; +// CHECK-NEXT: int &local_rA = param_A; +// CHECK-NEXT: ++static_Var2; +// CHECK-NEXT: return local_rA + param_B + global_Var1 + static_Var2 + local_Var3; +// CHECK-NEXT: } +// CHECK-NEXT: int static global_X = foo(1, rA(global_Var3)); + +int static Var1 = 0; +extern int Var3; +int rA(int A) { + return -A; +} +int static foo(int A, int B) { + static int Var2 = 0; + int Var3 = 123; + int &rA = A; + ++Var2; + return rA + B + Var1 + Var2 + Var3; +} +int static X = foo(1, rA(Var3)); + + diff --git a/clang/test/compiler-course/baranov_a_ast_tests/test.cpp b/clang/test/compiler-course/baranov_a_ast_tests/test.cpp new file mode 100644 index 0000000000000..3b8f8ecfa8630 --- /dev/null +++ b/clang/test/compiler-course/baranov_a_ast_tests/test.cpp @@ -0,0 +1,124 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/DataTypes_BARANOV_ALEKSEY_FIIT1_ClangAST%pluginext -plugin BaranovDataPlugin -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: myClass(class|template) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ x (T|private) +// CHECK-NEXT: | |_ inner (int|private) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) + +template class myClass { + T x; + int inner; +}; +// CHECK: A(struct) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (has no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) +struct A {}; +// CHECK: B(struct) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (has no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) +struct B {}; + +// CHECK: C(class) -> public A, public B +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (has no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) +class C : public A, public B {}; + +// CHECK: myClassBase(class) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (has no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) +class myClassBase {}; + +// CHECK: myClassPubl(class) -> public myClassBase +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (has no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) +class myClassPubl : public myClassBase {}; + +// CHECK: myClassPriv(class) -> private myClassBase +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (has no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) +class myClassPriv : private myClassBase {}; + +// CHECK: publPriv(struct) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ i (long long|public) +// CHECK-NEXT: | |_ x (float|private) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (has no methods) +struct publPriv { + long long i; + +private: + float x; +}; + +// CHECK: Person(struct) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ age (unsigned int|public) +// CHECK-NEXT: | |_ height (unsigned int|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ sleep (void()|public|virtual|pure) +// CHECK-NEXT: | |_ eat (void()|public|virtual|pure) +struct Person { + unsigned age; + unsigned height; + + virtual void sleep() = 0; + virtual void eat() = 0; +}; + +// CHECK: twoTemplates(class|template) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ first (T|private) +// CHECK-NEXT: | |_ second (U|private) +template class twoTemplates { + T first; + U second; +}; + +// reviewers request + +struct vi { + virtual void foo() = 0; +}; +// CHECK: overrideCheck(class) -> public vi +// CHECK: |_Methods +// CHECK-NEXT: | |_ foo (void()|private|override) +class overrideCheck : public vi { + void foo() override; +}; + +// CHECK: staticCheck(struct) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ r (long long|static|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ bbbb (int(double)|static|public) +struct staticCheck { + static long long int r; + static int bbbb(double arg); +}; + +// CHECK: E(union) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ F (int|public) +// CHECK-NEXT: | |_ I (float|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ t (float(int, double *)|static|public) +union E { + static float t(int i, double *d); + int F; + float I; +}; diff --git a/clang/test/compiler-course/beskhmelnova_k_implicit_conversions/beskhmelnova_k_implicit_conversions_test.cpp b/clang/test/compiler-course/beskhmelnova_k_implicit_conversions/beskhmelnova_k_implicit_conversions_test.cpp new file mode 100644 index 0000000000000..9d0354ec9134e --- /dev/null +++ b/clang/test/compiler-course/beskhmelnova_k_implicit_conversions/beskhmelnova_k_implicit_conversions_test.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_1_BeskhmelnovaK_FIIT1_ClangAST%pluginext -plugin ClangAST_1_BeskhmelnovaK_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s + +// Проверка порядка выводимых строк: +// CHECK: Function sum +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 + +double sum(int a, float b) { + return a + b; +} + +// CHECK: Function mul +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 + +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function createX +// CHECK-NEXT: int -> X: 1 + +class X { + int x; +public: + X(int val) : x(val) {} +}; + +X createX() { + return 10; +} + +// CHECK: Function foo +// CHECK-NEXT: int -> float: 1 +// CHECK-NEXT: float -> int: 1 +// CHECK-NEXT: int * -> void *: 1 + +using Abrakadabra = float; +using Boom = int; + +void boo(void*); + +void foo() { + Abrakadabra x = Boom(); + Boom y = x; + boo(&y); +} + +// CHECK: Total implicit conversions: 9 diff --git a/clang/test/compiler-course/chistov_a_user_data_type/chistov_a_user_data_type_test.cpp b/clang/test/compiler-course/chistov_a_user_data_type/chistov_a_user_data_type_test.cpp new file mode 100644 index 0000000000000..91a9691fb0272 --- /dev/null +++ b/clang/test/compiler-course/chistov_a_user_data_type/chistov_a_user_data_type_test.cpp @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/PrintData_Chistov_Alexey_FIIT1_ClangAST%pluginext -plugin PrintDataPlugin %s -fsyntax-only 2>&1 | FileCheck %s + +// CHECK: A(class) +class A {}; + +// CHECK: B(struct) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ a (A|public) +struct B { + A a; +}; + +// CHECK: Simple(struct) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ x (int|public) +// CHECK-NEXT: | |_ y (double|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ method (int|public) +struct Simple { + int x; + double y; + + int method(int x, int y) {} +}; + +// CHECK: Static(class) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ method (void|private|static) +class Static { + static void method() {} +}; + +// CHECK: Template(class|template) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ x (T|private) +// CHECK-NEXT: | |_ z (int|private) +template +class Template { + T x; + int z; +}; + +// CHECK: MultiTemplate(class|template) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ first (T|private) +// CHECK-NEXT: | |_ second (U|private) +template +class MultiTemplate { + T first; + U second; +}; + +// CHECK: C -> public A +// CHECK: C -> public B +class C : public A, public B {}; + +// CHECK: PublicDerived -> public Base +// CHECK: ProtectedDerived -> protected Base +// CHECK: PrivateDerived -> private Base +class Base {}; +class PublicDerived : public Base {}; +class ProtectedDerived : protected Base {}; +class PrivateDerived : private Base {}; + +// CHECK: AccessModifiers +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ x (float|private) +// CHECK-NEXT: | |_ y (double|protected) +// CHECK-NEXT: | |_ z (long long|public) +class AccessModifiers { +private: + float x; +protected: + double y; +public: + long long z; +}; + +// CHECK: Person +// CHECK: |_Fields +// CHECK: | |_ age (unsigned int|public) +// CHECK: | |_ height (unsigned int|public) +// CHECK: |_Methods +// CHECK: | |_ sleep (void|public|virtual|pure) +// CHECK: | |_ eat (void|public|virtual|pure) +struct Person { + unsigned age; + unsigned height; + + virtual void sleep() = 0; + virtual void eat() = 0; +}; \ No newline at end of file diff --git a/clang/test/compiler-course/chizhov_m_implicit_conversions/chizhov_m_implicit_conversions.cpp b/clang/test/compiler-course/chizhov_m_implicit_conversions/chizhov_m_implicit_conversions.cpp new file mode 100644 index 0000000000000..df6aefbe39e01 --- /dev/null +++ b/clang/test/compiler-course/chizhov_m_implicit_conversions/chizhov_m_implicit_conversions.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/Implicit_Conv_Chizhov_Maxim_FIIT3_ClangAST%pluginext -plugin Implicit_Conv_Chizhov_Maxim_FIIT3_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s + +using Abrakadabra = int; +#define int Abrakadabra + +// CHECK: Function foo +// CHECK-NEXT: float -> int: 1 +// CHECK-NEXT: int -> double: 1 +// CHECK-NEXT: double -> int: 1 + +void foo(float a) { + int tmp = a; + double tmp2 = tmp; + Abrakadabra tmp3 = tmp2; +} + +// CHECK: Function sum +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 +double sum(int a, float b) { + return a + b; +} + +// CHECK: Function mul +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 + +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function Create +// CHECK-NEXT: int -> class Class: 1 +class Class { + int x; + public: + Class(int); +}; + +Class Create() { + return 1; +} + +// CHECK: Function LongToFloat +// CHECK-NEXT: long long -> float: 1 + +float LongToFloat() { + long long x = 9223372036854775807LL; + float y = x; + return y; +} + +// CHECK: Function CharToInt +// CHECK-NEXT: char -> int: 1 + +int CharToInt() { + char x = 'c'; + int y = x; + return y; +} + +// CHECK: Function PointerImplicitCast +// CHECK-NEXT: int * -> void *: 1 + +void PointerImplicitCast(int* ptr) { + void* voidPtr = ptr; +} + + +int NoImplicitCasts(int a) { + return a; +} diff --git a/clang/test/compiler-course/clang-plugin-Mamaeva/mamaeva-test.cpp b/clang/test/compiler-course/clang-plugin-Mamaeva/mamaeva-test.cpp new file mode 100644 index 0000000000000..acfc4c46c4b0e --- /dev/null +++ b/clang/test/compiler-course/clang-plugin-Mamaeva/mamaeva-test.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_1_Mamaeva_Olga_FIIT3_ClangAST%pluginext -plugin ClangAST_1 -fsyntax-only %s 2>&1 | FileCheck %s -dump-input=always + +enum class Color { Red }; +enum OldStyleEnum { ONE, TWO, THREE }; + +class NumberWrapper { +public: + operator int() const { return 42; } +}; + +// CHECK: Function `sum` +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 +double sum(int a, float b) { + return a + b; +} + +// CHECK-NEXT: Function `mul` +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function `convertTypes` +// CHECK-NEXT: float -> int: 1 +// CHECK-NEXT: int -> float: 1 +using FloatType = float; +using IntType = int; +void convertTypes() { + FloatType floatVar = IntType(); + IntType intVar = floatVar; +} + +// CHECK: Function `handlePointers` +// CHECK-NEXT: int* -> void*: 1 +void handlePointers() { + int value; + void* voidPtr = &value; +} + +// CHECK: Function `checkPointer` +// CHECK-NEXT: int* -> bool: 1 +void checkPointer(int* ptr) { + if (ptr) {} +} + +// CHECK: Function `convertToBool` +// CHECK-NEXT: int -> bool: 1 +void convertToBool() { + int number = 7; + bool booleanValue = number; +} + +// CHECK: Function `useEnums` +// CHECK-NEXT: OldStyleEnum -> int: 1 +void useEnums() { + OldStyleEnum e = TWO; + int x = e; +} + +// CHECK: Total implicit conversions: 11 diff --git a/clang/test/compiler-course/drozhdinov_d_clangast_var3_test/test.cpp b/clang/test/compiler-course/drozhdinov_d_clangast_var3_test/test.cpp new file mode 100644 index 0000000000000..5c62ae75953c5 --- /dev/null +++ b/clang/test/compiler-course/drozhdinov_d_clangast_var3_test/test.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/CastCounter_DrozhdinovD_FIIT1_ClangAST%pluginext -plugin CastCounter_DrozhdinovD_FIIT1_ClangAST %s -fsyntax-only 2>&1 | FileCheck %s +using Abrakadabra = int; +#define int Abrakadabra + +// CHECK: Function sum +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 + +// CHECK: Function mul +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 + +double sum(int a, float b) { + return a + b; +} + +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function func +// CHECK-NEXT: _Bool -> int: 1 +// CHECK-NEXT: double -> _Bool: 2 +// CHECK-NEXT: int -> double: 1 + +void func() { + bool b = 3.14; + bool bb = 0.00; + int x = b; + double d = x; +} + +// CHECK: Function foo +// CHECK-NEXT: int * -> const int *: 1 + +void bar(const int*); +void foo() { + int x = 42; + bar(&x); +} + +// CHECK: Function createX +// CHECK-NEXT: int -> X: 1 + +class X { + int x; +public: + X(int val) : x(val) {} +}; + + +X createX() { + return 10; +} diff --git a/clang/test/compiler-course/frolova_e_implicit_conversions/frolova_e_implicit_conversions.cpp b/clang/test/compiler-course/frolova_e_implicit_conversions/frolova_e_implicit_conversions.cpp new file mode 100644 index 0000000000000..f9eb00674e815 --- /dev/null +++ b/clang/test/compiler-course/frolova_e_implicit_conversions/frolova_e_implicit_conversions.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ImplicitConvPlugin_Frolova_Elizaveta_FIIT3_ClangAST%pluginext -plugin ImplicitConvPlugin -fsyntax-only %s 2>&1 | FileCheck %s +using ll = long long; +#define long long ll + +// CHECK: Function: sum +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 +double sum(int a, float b) { + return a + b; // 'a' (int) -> 'b' (float) -> 'double' +} + +// CHECK: Function: mul +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function: checkCondition +// CHECK-NEXT: int -> bool: 1 +// CHECK-NEXT: int -> double: 1 +double checkCondition() { + int x = 1; + if (x) { x++; } + return x; +} + +// CHECK: Function: convertAndReturn +// CHECK-NEXT: double -> float: 1 +// CHECK-NEXT: float -> int: 1 +int convertAndReturn() { + double x = 1.2; + float y = x; + return y; +} + +// CHECK: Function: convertLongLongToInt +// CHECK-NEXT: ll -> int: 1 +int convertLongLongToInt() { + ll x = 10000000000LL; + int y = x; + return y; +} + +// CHECK: Function: charToIntAndDouble +// CHECK-NEXT: char -> int: 1 +// CHECK-NEXT: int -> double: 1 +double charToIntAndDouble() { + char c = 'A'; + int i = c; + double d = i; + return d; +} + +// CHECK: Function: callProcessPointer +// CHECK-NEXT: int * -> const int *: 1 +void processPointer(const int*); +void callProcessPointer() { + int x = 42; + processPointer(&x); +} + +// CHECK: Function: createAndReturnObject +// CHECK-NEXT: int -> MyClass: 1 +class MyClass { + int x; + public: + MyClass(int); +}; + +MyClass createAndReturnObject() { + return 10; +} + +// CHECK:Function: foo +// CHECK-NEXT:int[3] -> int *: 1 +int foo(int a) { + static int aa[] = {1, 2, 3}; + return aa[a]; +} \ No newline at end of file diff --git a/clang/test/compiler-course/grudzin_k_unused_vars_ast/test.cpp b/clang/test/compiler-course/grudzin_k_unused_vars_ast/test.cpp new file mode 100644 index 0000000000000..5b5d5da553601 --- /dev/null +++ b/clang/test/compiler-course/grudzin_k_unused_vars_ast/test.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/UnusedVars_Grudzin_Konstantin_FIIT1_ClangAST%pluginext -plugin grudzin_k_UnVars_plugin -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: \[\[maybe_unused\]\] int ntd=-1; +int ntd=-1; +// CHECK: int baz(int p, int q, \[\[maybe_unused\]\] int r) { +// CHECK: int a=5; +// CHECK: int b=17; +// CHECK: \[\[maybe_unused\]\]int c = a+b; +// CHECK: \[\[maybe_unused\]\] int temp = 42; +// CHECK: return p + q; +int baz(int p, int q, int r) { + int a=5; + int b=17; + int c = a+b; + int temp = 42; + return p + q; + } + +// CHECK: void qux(double a, double b, \[\[maybe_unused\]\] double c = 5.0) { +// CHECK: \[\[maybe_unused\]\] double result = a * b; +void qux(double a, double b, double c = 5.0) { + double result = a * b; + } diff --git a/clang/test/compiler-course/grudzin_k_unused_vars_ast/test_help.cpp b/clang/test/compiler-course/grudzin_k_unused_vars_ast/test_help.cpp new file mode 100644 index 0000000000000..522ccdb239d95 --- /dev/null +++ b/clang/test/compiler-course/grudzin_k_unused_vars_ast/test_help.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/UnusedVars_Grudzin_Konstantin_FIIT1_ClangAST%pluginext -plugin grudzin_k_UnVars_plugin 2>&1 | FileCheck %s --help + +// CHECK:This plugin marks unused variables with \[\[maybe_unused\]\] attribute diff --git a/clang/test/compiler-course/ionova_ekaterina_lab_1/test.cpp b/clang/test/compiler-course/ionova_ekaterina_lab_1/test.cpp new file mode 100644 index 0000000000000..47ad82d542470 --- /dev/null +++ b/clang/test/compiler-course/ionova_ekaterina_lab_1/test.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClassInfoVisitorPlugin_Ionova_Ekaterina_FIIT1_ClangAST%pluginext -plugin ClassInfoVisitorPlugin_Ionova_Ekaterina_FIIT1_ClangAST %s 1>&1 | FileCheck %s + +// CHECK: Point3D +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ m_x (double|public) +// CHECK-NEXT: | |_ m_y (double|public) +// CHECK-NEXT: | |_ m_z (double|public) +struct Point3D { + double m_x{}; + double m_y{}; + double m_z{}; +}; + +// CHECK: Pair +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ first (T1|public) +// CHECK-NEXT: | |_ second (T2|public) +template +struct Pair { + T1 first{}; + T2 second{}; +}; + +// CHECK: EmptyClass +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +class EmptyClass {}; + +// CHECK: NodeList +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ data (T|public) +// CHECK-NEXT: | |_ next (NodeList *|public) +template +struct NodeList { + T data{}; + NodeList *next{}; +}; + +// CHECK: CheckSpecifiers +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ publicMember (Point3D|public) +// CHECK-NEXT: | |_ protectedMember (Pair > >|protected) +// CHECK-NEXT: | |_ privateMember (EmptyClass|private) +class CheckSpecifiers { +public: + Point3D publicMember{}; +protected: + Pair>> protectedMember{}; +private: + EmptyClass privateMember{}; +}; + +// CHECK: User +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ m_id (int|public) +// CHECK-NEXT: | |_ m_human (Human|public) +// CHECK: Human +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ m_age (int|public) +// CHECK-NEXT: | |_ m_cash (int|public) +struct User { + struct Human { + int m_age{}; + int m_cash{}; + }; + int m_id{}; + Human m_human{}; +}; + +// CHECK: CheckStatic +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ m_staticMember (float|private|static) +class CheckStatic { + static float m_staticMember; +}; +float CheckStatic::m_staticMember = 0.0f; + +// CHECK: CheckConst +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ m_constMember (const char|private) +class CheckConst { + const char m_constMember{}; +}; + +// CHECK: CheckStaticConstTemplate +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ m_member (const T|private|static) +template +class CheckStaticConstTemplate { + static const T m_member; +}; +template +const T CheckStaticConstTemplate::m_member{}; + +// CHECK: MultipleInheritance +// CHECK-NEXT: |_Base Classes: Base1, Base2, Base3 +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ m_value (int|public) +class Base1 { +public: + int base1Value{}; +}; + +class Base2 { +public: + double base2Value{}; +}; + +class Base3 { +public: + char base3Value{}; +}; + +class MultipleInheritance : public Base1, public Base2, private Base3 { +public: + int m_value{}; +}; diff --git a/clang/test/compiler-course/ivanov_m_prefix_4_test/ivanov_m_prefix_test.cpp b/clang/test/compiler-course/ivanov_m_prefix_4_test/ivanov_m_prefix_test.cpp new file mode 100644 index 0000000000000..528c994be444d --- /dev/null +++ b/clang/test/compiler-course/ivanov_m_prefix_4_test/ivanov_m_prefix_test.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/Prefix_Plugin_Ivanov_Mikhail_FIIT1_ClangAST%pluginext -plugin Prefix_Plugin_Ivanov_Mikhail_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s -dump-input=always + +// CHECK: int global_var1 = 1; +// CHECK-NEXT: int foo(int param_a, int param_b){ +// CHECK-NEXT: int local_var2 = 0; +// CHECK-NEXT: static int static_var3 = 10; +// CHECK-NEXT: ++local_var2; +// CHECK-NEXT: return param_a + param_b; +// CHECK-NEXT: } +// CHECK-NEXT: static int global_var4 = foo(global_var1, 10); +// CHECK-NEXT: extern double global_dvar1 = 0; +// CHECK-NEXT: static double global_dvar2 = 1; + +int var1 = 1; +int foo(int a, int b){ + int var2 = 0; + static int var3 = 10; + ++var2; + return a + b; +} +static int var4 = foo(var1, 10); +extern double dvar1 = 0; +static double dvar2 = 1; diff --git a/clang/test/compiler-course/kabalova_testClangAST/kabalova_testClangAST.cpp b/clang/test/compiler-course/kabalova_testClangAST/kabalova_testClangAST.cpp new file mode 100644 index 0000000000000..48a059b128378 --- /dev/null +++ b/clang/test/compiler-course/kabalova_testClangAST/kabalova_testClangAST.cpp @@ -0,0 +1,24 @@ + +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_Kabalova_Valeria_FIIT1_ClangAST%pluginext -plugin ClangAST_Kabalova_Valeria_FIIT1_ClangAST %s -fsyntax-only 2>&1 | FileCheck %s + +// CHECK:\[\[maybe_unused\]\] int f = 0; + +// CHECK:int foo(int a, int b, \[\[maybe_unused\]\] int c) { +// CHECK-NEXT:\[\[maybe_unused\]\] double value = 0.0; +// CHECK-NEXT: double tmp = 1.0; +// CHECK-NEXT: return a + b + tmp; +// CHECK: \[\[maybe_unused\]\] int d = 0; + +int f = 0; + +int example(int a, int b, int c) { + double value = 0.0; + double tmp = 1.0; + return a + b + tmp; +} + +[[maybe_unused]] int d = 0; + +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_Kabalova_Valeria_FIIT1_ClangAST%pluginext -plugin ClangAST_Kabalova_Valeria_FIIT1_ClangAST -plugin-arg-ClangAST_Kabalova_Valeria_FIIT1_ClangAST --help %s -fsyntax-only 2>&1 | FileCheck %s + +// CHECK: This plugin searches for unused variables or unused parameters of functions and marks them with attribute \[\[maybe__unused\]\] diff --git a/clang/test/compiler-course/kolodkin_g_lab_1_var_1/kolodkin_g_lab1_test.cpp b/clang/test/compiler-course/kolodkin_g_lab_1_var_1/kolodkin_g_lab1_test.cpp new file mode 100644 index 0000000000000..0da4e3b8cf262 --- /dev/null +++ b/clang/test/compiler-course/kolodkin_g_lab_1_var_1/kolodkin_g_lab1_test.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/LabPlugin_KolodkinGrigorii_FIIT3_ClangAST%pluginext -plugin LabPlugin_KolodkinGrigorii_FIIT3_ClangAST -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: Shape +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ (no friends) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ area (double()|public|virtual|pure) + +struct Shape { + virtual double area() = 0; +}; + +// CHECK: Circle -> Shape +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ (no friends) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ radius (double|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ area (double()|public|override) + +struct Circle : Shape { +public: + double radius; + + double area() override { + return 3.14 * radius * radius; + } +}; + +// CHECK: Rectangle -> Shape +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ (no friends) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ width (double|public) +// CHECK-NEXT: | |_ height (double|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ area (double()|public|override) + +struct Rectangle : Shape { +public: + double width, height; + + double area() override { + return width * height; + } +}; + +// CHECK: ShapeA +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ (no friends) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ valueA (int|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ displayA (void()|public) + +struct ShapeA { +public: + int valueA; + + void displayA() {} +}; + +// CHECK: ShapeB +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ (no friends) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ valueB (int|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ displayB (void()|public) + +struct ShapeB { +public: + int valueB; + + void displayB() {} +}; + +// CHECK: EmptyClass +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ (no friends) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (no methods) + +class EmptyClass{}; + +// CHECK: CombinedShape -> ShapeA, ShapeB +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ (no friends) +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ valueA (int|public) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ displayB (void()|public) + +class CombinedShape : public ShapeA, public ShapeB { +public: + int valueA; + + void displayB() {} +}; + +void FriendFunc(); + +// CHECK: FriendClass +// CHECK-NEXT: |_Friends +// CHECK-NEXT: | |_ FriendFunc +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (no methods) + +class FriendClass { + friend void FriendFunc(); +}; diff --git a/clang/test/compiler-course/komshina_d_num_implicit_conversions/komshina_d_num_implicit_conversions.cpp b/clang/test/compiler-course/komshina_d_num_implicit_conversions/komshina_d_num_implicit_conversions.cpp new file mode 100644 index 0000000000000..e2429b70d6a9b --- /dev/null +++ b/clang/test/compiler-course/komshina_d_num_implicit_conversions/komshina_d_num_implicit_conversions.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/Implicit_Conversions_Komshina_Daria_FIIT1_ClangAST%pluginext -plugin Implicit_Conversions_Komshina_Daria_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck %s +// CHECK: Function sum +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 + +double sum(int a, float b) { + return a + b; +} + +// CHECK: Function mul +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 + +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function createX +// CHECK-NEXT: int -> class X: 1 + +class X { + int x; +public: + X(int val) : x(val) {} +}; + +X createX() { + return 10; +} + +// CHECK: Function foo +// CHECK-NEXT: int -> float: 1 +// CHECK-NEXT: float -> int: 1 + +using Abrakadabra = float; +using Boom = int; + +void foo() { + Abrakadabra x = Boom(); + Boom y = x; +} + +// CHECK: Function boo +// CHECK-NEXT: int -> _Bool: 1 + +void boo() { + int x = 3; + bool b = x; +} + +// CHECK: Function goo +// CHECK-NEXT: int * -> void *: 1 + +void loo(void*); + +void goo() { + int x = 20; + loo(&x); +} + +// CHECK: Total implicit conversions: 10 diff --git a/clang/test/compiler-course/kozlova_e_var_4_test/test.cpp b/clang/test/compiler-course/kozlova_e_var_4_test/test.cpp new file mode 100644 index 0000000000000..39735d7750974 --- /dev/null +++ b/clang/test/compiler-course/kozlova_e_var_4_test/test.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/FirstPlugin_KozlovaEkaterina_FIIT3_ClangAST%pluginext -plugin FirstPlugin_KozlovaEkaterina_FIIT3_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s + + +// CHECK: int global_var1 = 0; +// CHECK-NEXT: int foo(int param_a, int param_b) { +// CHECK-NEXT: static int static_var2 = 0; +// CHECK-NEXT: int local_var3 = 123; +// CHECK-NEXT: ++static_var2; +// CHECK-NEXT: return param_a + param_b + global_var1 + static_var2 + local_var3; +// CHECK-NEXT: } +// CHECK-NEXT: int static static_global_var4 = 1; +// CHECK-NEXT: int static static_global_var5 = foo(1, static_global_var4); +// CHECK-NEXT: int foo2(int param_a, int param_b_default_10) { +// CHECK-NEXT: return param_a * param_b_default_10; +// CHECK-NEXT: } +// CHECK-NEXT: int global_var6 = foo2(1); +// CHECK-NEXT: int global_var7 = foo2(1, 2); + + +int var1 = 0; +int foo(int a, int b) { + static int var2 = 0; + int var3 = 123; + ++var2; + return a + b + var1 + var2 + var3; +} +int static var4 = 1; +int static var5 = foo(1, var4); +int foo2(int a, int b = 10) { + return a * b; +} +int var6 = foo2(1); +int var7 = foo2(1, 2); diff --git a/clang/test/compiler-course/kudryashova_i_test_clangast/kudryashova_i_clangast_test.cpp b/clang/test/compiler-course/kudryashova_i_test_clangast/kudryashova_i_clangast_test.cpp new file mode 100644 index 0000000000000..2cc026d98dcde --- /dev/null +++ b/clang/test/compiler-course/kudryashova_i_test_clangast/kudryashova_i_clangast_test.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/Implicit_Conv_Kudryashova_Irina_FIIT3_ClangAST%pluginext -plugin ImplicitConvPlugin %s -fsyntax-only 2>&1 | FileCheck %s + +// CHECK: Function `sum` +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 + +double sum(int a, float b) { + return a + b; +} + +// CHECK-NEXT: Function `mul` +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 + +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function `foo` +// CHECK-NEXT: float -> int: 1 +// CHECK-NEXT: int -> float: 1 + +using Abrakadabra = float; +using Boom = int; + +void foo() { + Abrakadabra x = Boom(); + Boom y = x; +} + +// CHECK: Function `moo` +// CHECK-NEXT: int* -> void*: 1 +void moo() { + int x; + void* vp = &x; +} + +// CHECK: Function `goo` +// CHECK-NEXT: int* -> bool: 1 +void goo(int* p) { + if (p) {} +} + +// CHECK: Function `boo` +// CHECK-NEXT: int -> bool: 1 +void boo() { + int x = 7; + bool b = x; +} + +// CHECK: Total implicit conversions: 10 diff --git a/clang/test/compiler-course/kurakin_user_data_type/kurakin_user_data_type_test.cpp b/clang/test/compiler-course/kurakin_user_data_type/kurakin_user_data_type_test.cpp new file mode 100644 index 0000000000000..86ec55876783d --- /dev/null +++ b/clang/test/compiler-course/kurakin_user_data_type/kurakin_user_data_type_test.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/UserDataTypePlugin_Kurakin_Matvey_FIIT1_ClangAST%pluginext -plugin UserDataTypePlugin_Kurakin_Matvey_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck %s + +//CHECK: Human +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ age (unsigned int|public) +//CHECK-NEXT: | |_ height (unsigned int|public) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ sleep (void()|public|virtual|pure) +//CHECK-NEXT: | |_ eat (void()|public|virtual|pure) + +struct Human { + unsigned age; + unsigned height; + virtual void sleep() = 0; + virtual void eat() = 0; +}; + +//CHECK: Engineer -> Human +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ salary (unsigned int|public) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ sleep (void()|public|override) +//CHECK-NEXT: | |_ eat (void()|public|override) +//CHECK-NEXT: | |_ work (void()|public) + +struct Engineer : Human { + unsigned salary; + void sleep() override { /* something */ } + void eat() override { /* something */ } + void work() { /* something */ } +}; + +//CHECK: A +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ a1 (int|private) +//CHECK-NEXT: | |_ a2 (float|private) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ somefunc (int(float)|private) + +class A { + int a1; + float a2; + int somefunc(float); +}; + +//CHECK: B +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ (has no fields) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ b1 (void(int,int)|private|virtual) + +class B { + virtual void b1(int b2, int b3); +}; + +//CHECK: C -> A,B +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ (has no fields) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ b1 (void(int,int)|private|override) +//CHECK-NEXT: | |_ somefunc (int(float)|private) + +class C : A,B{ + void b1(int b2, int b3) override; + int somefunc(float); +}; + +//CHECK: D +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ d1 (int[5]|private) +//CHECK-NEXT: | |_ d2 (T|protected) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ d3 (T(T,int)|public|virtual|pure) + +template +struct D{ +private: + int d1[5]; +protected: + T d2; +public: + virtual T d3(T d4, int d5) = 0; +}; + + +//CHECK: E +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ (has no fields) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ e2 (char(char)|public|static) + +struct E{ + static char e2(char); +}; + +//CHECK: F +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ f1 (int|private) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ (has no methods) + +class F{ + int f1; +}; diff --git a/clang/test/compiler-course/lopatin_i_user_data_type/lopatin_i_user_data_type_test.cpp b/clang/test/compiler-course/lopatin_i_user_data_type/lopatin_i_user_data_type_test.cpp new file mode 100644 index 0000000000000..409f28d4ad729 --- /dev/null +++ b/clang/test/compiler-course/lopatin_i_user_data_type/lopatin_i_user_data_type_test.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/UserDataTypePlugin_LopatinIlya_FIIT3_ClangAST%pluginext -plugin UserDataTypePlugin_LopatinIlya_FIIT3_ClangAST %s -fsyntax-only 2>&1 | FileCheck %s + +// CHECK: Base1 +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ virtualMethod (void()|public|virtual|pure) + +// CHECK: Base2 +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ baseMethod (void()|public|virtual) + +// CHECK: Derived -> Base1, Base2 +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ publicField (int|public) +// CHECK-NEXT: | |_ protectedField (float|protected) +// CHECK-NEXT: | |_ privateField (char|private) +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ virtualMethod (void()|public|override) +// CHECK-NEXT: | |_ baseMethod (void()|public|override) +// CHECK-NEXT: | |_ constMethod (int()|private|const) +// CHECK-NEXT: | |_ anotherMethod (void(int)|protected) + +// CHECK: Array +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ ptr (T[SZ]|public) + + +struct Base1 { + virtual void virtualMethod() = 0; +}; + +struct Base2 { + virtual void baseMethod() {} +}; + +struct Derived : Base1, Base2 { +public: + int publicField; +protected: + float protectedField; +private: + char privateField; + +public: + void virtualMethod() override {} + void baseMethod() override {} + +private: + int constMethod() const { return 0; } + +protected: + void anotherMethod(int) {} +}; + +template +struct Array { + T ptr[SZ]{}; +}; + diff --git a/clang/test/compiler-course/lysov_ivan_1stLabsTests/test.cpp b/clang/test/compiler-course/lysov_ivan_1stLabsTests/test.cpp new file mode 100644 index 0000000000000..db092444581c0 --- /dev/null +++ b/clang/test/compiler-course/lysov_ivan_1stLabsTests/test.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/unUsedVarPlugin_LysovIvan_FIIT3_ClangAST%pluginext -plugin unUsedVarPlugin_LysovIvan_FIIT3_ClangAST %s -fsyntax-only 2>&1 | FileCheck %s + +//CHECK: int FunctionFromTheProblemStatement(int a, int b, int c) { +//CHECK: \[\[maybe_unused\]\] double value = 0.0; +//CHECK: return a + b; +int FunctionFromTheProblemStatement(int a, int b, int c) { + double value = 0.0; + return a + b; +} + +//CHECK: void test_params(int used, \[\[maybe_unused\]\] int unused) { +//CHECK: int x = used; +//CHECK: return x; +int test_params(int used, int unused) { + int x = used; + return x; +} + +//CHECK: \[\[maybe_unused\]\] int globalVar = 6; +int globalVar = 6; + +//CHECK: void checkWithoutReturn(int a, \[\[maybe_unused\]\] long d){ +//CHECK: \[\[maybe_unused\]\] int g = a; +void checkWithoutReturn(int a, long d){ + int g = a; +} + +//CHECK: void checkConstantParamsFunction(\[\[maybe_unused\]\] const int x, float j){ +//CHECK: \[\[maybe_unused\]\] float y = j ; +void checkConstantParamsFunction(const int x, float j){ + float y = j; +} + +//CHECK: void funcforReview(){ +//CHECK: int x __attribute__((unused)); +//CHECK: \[\[maybe_unused\]\] int y; +void funcforReview() { + int x __attribute__((unused)); + int y; +} diff --git a/clang/test/compiler-course/mironov_a_lab1/test.cpp b/clang/test/compiler-course/mironov_a_lab1/test.cpp new file mode 100644 index 0000000000000..52442821ecb3b --- /dev/null +++ b/clang/test/compiler-course/mironov_a_lab1/test.cpp @@ -0,0 +1,84 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/Lab1_AST_Mironov_Arseniy_FIIT1_ClangAST%pluginext -plugin Lab1_AST_Mironov_Arseniy_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck %s -dump-input=always + +// CHECK: In global scope +// CHECK-NEXT: int -> float: 1 +float global_scope_test = 4; + + +// CHECK: In function: mul +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 + +// CHECK: In function: sum +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 + +double sum(int a, float b) { + return a + b; +} + +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: In function: test_casts1 +// CHECK-NEXT: double -> _Bool +// CHECK-NEXT: double -> float +// CHECK-NEXT: double -> int +// CHECK-NEXT: int -> _Bool: 1 +// CHECK-NEXT: int -> double: 1 + +void test_casts1(){ + bool f1 = 1; + bool f2 = 1.0; + int x = 1.0; + float y = 1.0; + double c = 1; +} + +// CHECK: In function: test_casts2 +// CHECK-NEXT: _Bool -> char: 1 +// CHECK-NEXT: _Bool -> double: 2 +// CHECK-NEXT: _Bool -> float: 1 +// CHECK-NEXT: _Bool -> int: 1 + +void test_casts2(){ + int c = true; + double c1 = true; + double c2 = false; + float c3 = false; + char c4= true; +} + +class X{ +private: + int created; +public: + X(int val): created(val) {} +}; + +// CHECK: In function: test_casts3 +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: int -> class X: 1 + +void test_casts3(){ + X sample(1.0); +} + +// CHECK: In function: test_casts4 +// CHECK-NEXT: _Bool -> int: 1 +// CHECK-NEXT: int -> class X: 1 + +X test_casts4(){ + return true; +} + +// CHECK: In function: test_casts5 +// CHECK-NEXT: int * -> void *: 1 + +void test_casts5(){ + int obj = 5; + int *ptr = &obj; + void* cp = ptr; +} diff --git a/clang/test/compiler-course/plekhanov_unused_variables/test.cpp b/clang/test/compiler-course/plekhanov_unused_variables/test.cpp new file mode 100644 index 0000000000000..73bbe19eebd7e --- /dev/null +++ b/clang/test/compiler-course/plekhanov_unused_variables/test.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/FindUnused_Plekhanov_Daniil_FIIT2_ClangAST%pluginext -plugin FindUnused -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: \[\[maybe_unused\]\] int global_param=10; +int global_param=10; + +// CHECK: int baz(int a, int b, \[\[maybe_unused\]\] int c) { +// CHECK: \[\[maybe_unused\]\] double value=0.0; +// CHECK: return a + b; + +int foo(int a, int b, int c) { + double value = 0.0; + return a + b; +} + +// CHECK: double foo(double tmp, double tmp1, \[\[maybe_unused\]\] double tmp2) { +// CHECK: \[\[maybe_unused\]\] double c = tmp + tmp1; +double foo(double tmp, double tmp1, double tmp2) { + double c = tmp + tmp1; +} diff --git a/clang/test/compiler-course/rezantseva_a_prefixes/rezantseva_a_prefixes_test.cpp b/clang/test/compiler-course/rezantseva_a_prefixes/rezantseva_a_prefixes_test.cpp new file mode 100644 index 0000000000000..b30b5d531298c --- /dev/null +++ b/clang/test/compiler-course/rezantseva_a_prefixes/rezantseva_a_prefixes_test.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST%pluginext -plugin PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s + +// CHECK: int global_var1 = 0; +// CHECK-NEXT: int foo(int param_a, int param_b) { +// CHECK-NEXT: static int static_var2 = 0; +// CHECK-NEXT: int local_var3 = 123; +// CHECK-NEXT: ++static_var2; +// CHECK-NEXT: return param_a + param_b + global_var1 + static_var2 + local_var3; +// CHECK-NEXT: } +// CHECK-NEXT: int static global_var4 = 3; +// CHECK-NEXT: int static global_var5 = foo(1, global_var4); + +int var1 = 0; +int foo(int a, int b) { + static int var2 = 0; + int var3 = 123; + ++var2; + return a + b + var1 + var2 + var3; +} +int static var4 = 3; +int static var5 = foo(1, var4); + +// RUN: %clang_cc1 -load %llvmshlibdir/PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST%pluginext -plugin PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST -plugin-arg-PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST --help -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s --check-prefix=CHECK-HELP +// CHECK-HELP: PrefixesPlugin_RezantsevaAnastasia_FIIT1_ClangAST: +// CHECK-HELP-NEXT: This plugin adds appropriate prefixes to variables and parameters in the code. + \ No newline at end of file diff --git a/clang/test/compiler-course/savchenko_m_l1_v2_tests/savchenko_m_l1_v2_tests.cpp b/clang/test/compiler-course/savchenko_m_l1_v2_tests/savchenko_m_l1_v2_tests.cpp new file mode 100644 index 0000000000000..9d75f9c444358 --- /dev/null +++ b/clang/test/compiler-course/savchenko_m_l1_v2_tests/savchenko_m_l1_v2_tests.cpp @@ -0,0 +1,34 @@ +//// --help arg test //// +// RUN: %clang_cc1 -load %llvmshlibdir/UnusedVariables_Savchenko_Maxim_FIIT1_ClangAST%pluginext -plugin savchenko_m_UnusedVars_plugin -plugin-arg-savchenko_m_UnusedVars_plugin --help 2>&1 | FileCheck --check-prefix=HELP %s +// HELP: The plugin adds the {{\[\[maybe_unused\]\]}} flag to variables and parameters that are not in use. + + +//// main tests //// +// RUN: %clang_cc1 -load %llvmshlibdir/UnusedVariables_Savchenko_Maxim_FIIT1_ClangAST%pluginext -plugin savchenko_m_UnusedVars_plugin -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: double used = 3.0; +// CHECK-NEXT: \[\[maybe_unused\]\] double unused = 2.0; +double used = 3.0; +double unused = 2.0; + +// CHECK: int foo1(int a, int b, \[\[maybe_unused\]\] int c) { +// CHECK-NEXT: \[\[maybe_unused\]\] int tmp = 47; +// CHECK-NEXT: int x = 24; +// CHECK-NEXT: int y = 54; +// CHECK-NEXT: \[\[maybe_unused\]\] int xy = x + y; +// CHECK-NEXT: return a + b; +int foo1(int a, int b, int c) { + int tmp = 47; + int x = 24; + int y = 54; + int xy = x + y; + return a + b; +} + +// CHECK: double mult(double a, double b, \[\[maybe_unused\]\] double c) { +// CHECK-NEXT: \[\[maybe_unused\]\] double result = a * b; +// CHECK-NEXT: return a * b * used; +double mult(double a, double b, double c) { + double result = a * b; + return a * b * used; +} diff --git a/clang/test/compiler-course/shkurinskaya_e_var_renaming/shkurinskaya_e_var_renaming_test.cpp b/clang/test/compiler-course/shkurinskaya_e_var_renaming/shkurinskaya_e_var_renaming_test.cpp new file mode 100644 index 0000000000000..c76e2e0bac320 --- /dev/null +++ b/clang/test/compiler-course/shkurinskaya_e_var_renaming/shkurinskaya_e_var_renaming_test.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_4_Shkurinskaya_Elena_FIIT2_ClangAST%pluginext -plugin ClangAST_4 -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: int global_var = 42; +// CHECK-NEXT: float global_pi = 3.1415; +// CHECK-NEXT: static double global_static_value = 2.71828; +// CHECK-NEXT: void process(int param_a, float param_b, char param_c) { +// CHECK-NEXT: int local_sum = param_a + param_b; +// CHECK-NEXT: static int static_counter = 0; +// CHECK-NEXT: for (int local_i = 0; local_i < 5; ++local_i) { +// CHECK-NEXT: char local_buf[10]; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: void anotherFunction() { +// CHECK-NEXT: static int static_flag = 1; +// CHECK-NEXT: int local_value = static_flag + 10; +// CHECK-NEXT: } +// CHECK-NEXT: void testLoop() { +// CHECK-NEXT: for (int local_j = 0; local_j < 3; ++local_j) { +// CHECK-NEXT: int local_temp = local_j * 2; +// CHECK-NEXT: } +// CHECK-NEXT: } + +int var = 42; +float pi = 3.1415; +static double static_value = 2.71828; + +void process(int a, float b, char c) { + int sum = a + b; + static int counter = 0; + + for (int i = 0; i < 5; ++i) { + char buf[10]; + buf[0] = c; + } +} + +void anotherFunction() { + static int flag = 1; + int value = flag + 10; +} + +void testLoop() { + for (int j = 0; j < 3; ++j) { + int temp = j * 2; + } +} diff --git a/clang/test/compiler-course/shulpin_i_implicit_conversion/shulpin_i_ClangAST_lab_tests.cpp b/clang/test/compiler-course/shulpin_i_implicit_conversion/shulpin_i_ClangAST_lab_tests.cpp new file mode 100644 index 0000000000000..bb472f276c23c --- /dev/null +++ b/clang/test/compiler-course/shulpin_i_implicit_conversion/shulpin_i_ClangAST_lab_tests.cpp @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_Lab_ShulpinIlya_FIIT1_ClangAST%pluginext -plugin ClangAST_Lab_ShulpinIlya_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s + +// CHECK: Function sum +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: int -> float: 1 + +double sum(int a, float b) { + return a + b; +} + +// CHECK: Function mul +// CHECK-NEXT: double -> int: 1 +// CHECK-NEXT: float -> double: 1 +// CHECK-NEXT: float -> int: 1 + +int mul(float a, float b) { + return a + sum(a, b); +} + +// CHECK: Function structConversion +// CHECK-NEXT: const Base -> Base: 1 +// CHECK-NEXT: const struct Derived -> const struct Base: 1 + +struct Base {}; +struct Derived : Base {}; + +void structConversion() { + Derived d; + Base b = d; +} + +// CHECK: Function testPointers +// CHECK-NEXT: char * -> void *: 1 +// CHECK-NEXT: int * -> void *: 1 + +void testPointers() { + char* cptr; + int* iptr; + void* v1 = cptr; + void* v2 = iptr; +} + +// CHECK: Function foo +// CHECK-NEXT: int -> float: 1 +// CHECK-NEXT: float -> int: 1 +// CHECK-NEXT: int * -> void *: 1 + +using Abra = float; +using Kadabra = int; + +void Alakazam(void*); + +void foo() { + Abra x = Kadabra(); + Kadabra y = x; + Alakazam(&y); +} + +// CHECK: Function createX +// CHECK-NEXT: int -> X: 1 + +class X { + int x; +public: + X(int val) : x(val) {} +}; + +X createX() { + return 10; +} + +// CHECK: Function multCast +// CHECK-NEXT: int -> float: 5 +// CHECK-NEXT: float -> int: 5 + +void multCast() { + float f1 = 1; + float f2 = 2; + float f3 = 3; + float f4 = 4; + float f5 = 5; + + int i1 = f1; + int i2 = f2; + int i3 = f3; + int i4 = f4; + int i5 = f5; +} + +// CHECK: Summary of total conversions: 23 diff --git a/clang/test/compiler-course/solovev_a_test/solovev_a_test.cpp b/clang/test/compiler-course/solovev_a_test/solovev_a_test.cpp new file mode 100644 index 0000000000000..6cc3ed0247b48 --- /dev/null +++ b/clang/test/compiler-course/solovev_a_test/solovev_a_test.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClangAST_1_Solovev_a_FIIT1_ClangAST%pluginext -plugin ClangAST_1_Solovev_a_FIIT1_ClangAST -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s + +// CHECK: int global_a = 0; +// CHECK-NEXT: static int static_global_b = 3; +// CHECK-NEXT: int sum(int param_a, int param_b) { +// CHECK-NEXT: static int static_d = param_a + param_b; +// CHECK-NEXT: return static_d; +// CHECK-NEXT: } +// CHECK-NEXT: int minus(int param_c) { +// CHECK-NEXT: int local_d = -param_c; +// CHECK-NEXT: return local_d; +// CHECK-NEXT: } +// CHECK-NEXT: void func_1(int param_val_1, int param_val_2, int param_val_3) { +// CHECK-NEXT: int local_mult = param_val_1 * param_val_2; +// CHECK-NEXT: for (int local_i = 0; local_i < local_mult; local_i++) { +// CHECK-NEXT: param_val_3 += local_i; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: void func_2(int param_val_4, int param_val_5) { +// CHECK-NEXT: static int static_x = param_val_4 / param_val_5; +// CHECK-NEXT: static int static_y = param_val_5 / param_val_4; +// CHECK-NEXT: int local_res = static_x + static_y; +// CHECK-NEXT: } + +int a = 0; +static int b = 3; +int sum(int a, int b) { + static int d = a + b; + return d; +} +int minus(int c) { + int d = -c; + return d; +} +void func_1(int val_1, int val_2, int val_3) { + int mult = val_1 * val_2; + for (int i = 0; i < mult; i++) { + val_3 += i; + } +} +void func_2(int val_4, int val_5) { + static int x = val_4 / val_5; + static int y = val_5 / val_4; + int res = x + y; +} diff --git a/clang/test/compiler-course/solovyev_d_unused_variable/solovyev_d_unused_variable_test.cpp b/clang/test/compiler-course/solovyev_d_unused_variable/solovyev_d_unused_variable_test.cpp new file mode 100644 index 0000000000000..bde48c12b042e --- /dev/null +++ b/clang/test/compiler-course/solovyev_d_unused_variable/solovyev_d_unused_variable_test.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/UnusedVariable_Solovyev_Danila_FIIT3_ClangAST%pluginext -plugin unused_variable_plugin -fsyntax-only %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -load %llvmshlibdir/UnusedVariable_Solovyev_Danila_FIIT3_ClangAST%pluginext -plugin unused_variable_plugin -plugin-arg-unused_variable_plugin --help 2>&1 | FileCheck --check-prefix=HELP %s + +//HELP:Marking unused variables and function parameters as {{\[\[maybe_unused\]\]}} + +//CHECK: int foo(int a, int b, \[\[maybe_unused\]\] int c) { +//CHECK: \[\[maybe_unused\]\] double value = 0.0; + +int foo(int a, int b, int c) { + double value = 0.0; + return a + b; +} + +//CHECK: bool bar(int a, bool b, \[\[maybe_unused\]\] double c=3.0){ + +bool bar(int a, bool b, double c=3.0){ + b=a++; + return true; +} + +//CHECK: \[\[maybe_unused\]\] int test; +//CHECK: \[\[maybe_unused\]\] bool c=b; + +int test; +int b=1; +bool c=b; + +//CHECK: A(int a,\[\[maybe_unused\]\] int b){ + +class A{ + A(int a,int b){ + a=1; + } +}; diff --git a/clang/test/compiler-course/sozonov_i_user_defined_data_type/sozonov_i_user_defined_data_type_test.cpp b/clang/test/compiler-course/sozonov_i_user_defined_data_type/sozonov_i_user_defined_data_type_test.cpp new file mode 100644 index 0000000000000..e6ce883d63944 --- /dev/null +++ b/clang/test/compiler-course/sozonov_i_user_defined_data_type/sozonov_i_user_defined_data_type_test.cpp @@ -0,0 +1,115 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/UserDefinedDataTypePlugin_SozonovIlya_FIIT3_ClangAST%pluginext -plugin user_defined_data_type_plugin -fsyntax-only %s 2>&1 | FileCheck %s + +//CHECK: Human +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ age (unsigned int|public) +//CHECK-NEXT: | |_ height (unsigned int|public) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ sleep (void()|public|virtual|pure) +//CHECK-NEXT: | |_ eat (void()|public|virtual|pure) + +struct Human { + unsigned age; + unsigned height; + virtual void sleep() = 0; + virtual void eat() = 0; +}; + +//CHECK: Engineer -> Human +//CHECK-NEXT: |_Fields +//CHECK-NEXT: | |_ salary (unsigned int|public) +//CHECK-NEXT: | +//CHECK-NEXT: |_Methods +//CHECK-NEXT: | |_ sleep (void()|public|override) +//CHECK-NEXT: | |_ eat (void()|public|override) +//CHECK-NEXT: | |_ work (void()|public) + +struct Engineer : Human { + unsigned salary; + void sleep() override { /* something */ } + void eat() override { /* something */ } + void work() { /* something */ } +}; + +// CHECK: EmptyStruct +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: | +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (no methods) + +struct EmptyStruct {}; + +// CHECK: Data +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ publicField (int|public) +// CHECK-NEXT: | |_ protectedField (double|protected) +// CHECK-NEXT: | |_ privateField (char|private) +// CHECK-NEXT: | +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (no methods) + +struct Data { + int publicField; +protected: + double protectedField; +private: + char privateField; +}; + +// CHECK: MethodsExample +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: | +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ foo (void()|public) +// CHECK-NEXT: | |_ bar (int(int, double)|public) +// CHECK-NEXT: | |_ baz (void()|public|const) + +struct MethodsExample { + void foo() {} + int bar(int x, double y) { return x; } + void baz() const {} +}; + +// CHECK: Base +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: | +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ virtualFunc (void()|public|virtual|pure) + +struct Base { + virtual void virtualFunc() = 0; +}; + +// CHECK: Derived -> Base +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ (no fields) +// CHECK-NEXT: | +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ virtualFunc (void()|public|override) + +struct Derived : Base { + void virtualFunc() override {} +}; + +// CHECK: A + +struct A {}; + +// CHECK: B -> A +// CHECK-NEXT: |_Fields +// CHECK-NEXT: | |_ value (A|public) +// CHECK-NEXT: | +// CHECK-NEXT: |_Methods +// CHECK-NEXT: | |_ (no methods) +// CHECK-NEXT: | +// CHECK-NEXT: |_Nested Types +// CHECK-NEXT: | |_ A + +struct B : public A { + struct A {}; + A value; +}; diff --git a/clang/test/compiler-course/suvorov_d_lab1_var4/suvorov_d_adding_prefs_test.cpp b/clang/test/compiler-course/suvorov_d_lab1_var4/suvorov_d_adding_prefs_test.cpp new file mode 100644 index 0000000000000..08ca0961c1538 --- /dev/null +++ b/clang/test/compiler-course/suvorov_d_lab1_var4/suvorov_d_adding_prefs_test.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST%pluginext -plugin AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST %s -fsyntax-only 2>&1 | FileCheck --match-full-lines %s + +// CHECK: int global_v1 = -10; +// CHECK-NEXT: extern float global_v3; +// CHECK-NEXT: long long global_ll = 1L; +// CHECK-NEXT: int static global_v4 = 52; +// CHECK-NEXT: int test_func(int param_a, int param_b) { +// CHECK-NEXT: static int static_v2 = 0; +// CHECK-NEXT: int local_v3 = 1; +// CHECK-NEXT: static_v2 = local_v3 - ++static_v2; +// CHECK-NEXT: return global_v1 + param_a + param_b + static_v2 + local_v3 + global_ll; +// CHECK-NEXT: } +// CHECK-NEXT: int static global_v5 = test_func(43, global_v4); + +int v1 = -10; +extern float v3; +long long ll = 1L; +int static v4 = 52; +int test_func(int a, int b) { + static int v2 = 0; + int v3 = 1; + v2 = v3 - ++v2; + return v1 + a + b + v2 + v3 + ll; +} +int static v5 = test_func(43, v4); + +// RUN: %clang_cc1 -load %llvmshlibdir/AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST%pluginext -plugin AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST %s -fsyntax-only 2>&1 | FileCheck -v %s -check-prefix=CHECK-LOGS + +// CHECK-LOGS: Renamed variable at test.cpp:15:5: v1 -> global_v1 +// CHECK-LOGS-NEXT: Renamed variable at test.cpp:16:14: v3 -> global_v3 +// CHECK-LOGS-NEXT: Renamed variable at test.cpp:17:13: ll -> global_ll +// CHECK-LOGS-NEXT: Renamed variable at test.cpp:18:12: v4 -> static_v4 +// CHECK-LOGS-NEXT: Renamed parameter at test.cpp:19:16: a -> param_a +// CHECK-LOGS-NEXT: Renamed parameter at test.cpp:19:23: b -> param_b +// CHECK-LOGS-NEXT: Renamed variable at test.cpp:20:14: v2 -> static_v2 +// CHECK-LOGS-NEXT: Renamed variable at test.cpp:21:7: v3 -> local_v3 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:22:5: v2 -> static_v2 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:22:10: v3 -> local_v3 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:22:16: v2 -> static_v2 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:23:10: v1 -> global_v1 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:23:15: a -> param_a +// CHECK-LOGS-NEXT: Updated reference at test.cpp:23:19: b -> param_b +// CHECK-LOGS-NEXT: Updated reference at test.cpp:23:23: v2 -> static_v2 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:23:27: v3 -> local_v3 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:23:31: ll -> global_ll +// CHECK-LOGS-NEXT: Renamed variable at test.cpp:25:12: v5 -> static_v5 +// CHECK-LOGS-NEXT: Updated reference at test.cpp:25:35: v4 -> static_v4 + +// RUN: %clang_cc1 -load %llvmshlibdir/AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST%pluginext -plugin AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST -plugin-arg-AddingPrefixesPlugin_Suvorov_Dmitrii_FIIT1_ClangAST --help -fsyntax-only %s 2>&1 | FileCheck --match-full-lines %s --check-prefix=CHECK-HELP-ARG +// CHECK-HELP-ARG: Rename Plugin - Adds prefixes to variables and parameters. +// CHECK-HELP-ARG-NEXT: Usage: +// CHECK-HELP-ARG-NEXT: --no-log Disable logging of changes +// CHECK-HELP-ARG-NEXT: --help Show this help message diff --git a/llvm/compiler-course/backend/sozonov_i_logical_combiner/CMakeLists.txt b/llvm/compiler-course/backend/sozonov_i_logical_combiner/CMakeLists.txt new file mode 100644 index 0000000000000..8970c72ab9cec --- /dev/null +++ b/llvm/compiler-course/backend/sozonov_i_logical_combiner/CMakeLists.txt @@ -0,0 +1,17 @@ +set(Title "LogicalCombinerPass") +set(Student "Sozonov_Ilya") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_BACKEND") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) + +add_llvm_pass_plugin(${TARGET_NAME} + ${SOURCES} + DEPENDS + intrinsics_gen + X86 + BUILDTREE_ONLY +) + +target_include_directories(${TARGET_NAME} PUBLIC ${PATH_TO_X86}) +set(LLVM_TEST_DEPENDS ${TARGET_NAME} ${LLVM_TEST_DEPENDS} PARENT_SCOPE) diff --git a/llvm/compiler-course/backend/sozonov_i_logical_combiner/LogicalCombinerPass.cpp b/llvm/compiler-course/backend/sozonov_i_logical_combiner/LogicalCombinerPass.cpp new file mode 100644 index 0000000000000..8f02ffbe10c76 --- /dev/null +++ b/llvm/compiler-course/backend/sozonov_i_logical_combiner/LogicalCombinerPass.cpp @@ -0,0 +1,98 @@ +#include "X86.h" +#include "X86InstrInfo.h" +#include "X86Subtarget.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +class LogicalCombinerPass : public MachineFunctionPass { +public: + static char ID; + LogicalCombinerPass() : MachineFunctionPass(ID) {} + bool runOnMachineFunction(MachineFunction &MF) override; +}; + +char LogicalCombinerPass::ID = 0; + +bool LogicalCombinerPass::runOnMachineFunction(MachineFunction &MF) { + llvm::outs() << MF.getName() << '\n'; + + const X86Subtarget &STI = MF.getSubtarget(); + const X86InstrInfo *TII = STI.getInstrInfo(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + bool Changed = false; + + for (auto &MBB : MF) { + for (auto MI = MBB.begin(); MI != MBB.end();) { + MachineInstr &AndInstr = *MI; + unsigned AndOpc = AndInstr.getOpcode(); + + if (AndOpc != X86::ANDPSrr && AndOpc != X86::VPANDrr) { + ++MI; + continue; + } + + if (!AndInstr.getOperand(0).isReg() || !AndInstr.getOperand(1).isReg() || + !AndInstr.getOperand(2).isReg()) { + ++MI; + continue; + } + + Register AndDst = AndInstr.getOperand(0).getReg(); + Register AndOp1 = AndInstr.getOperand(1).getReg(); + Register AndOp2 = AndInstr.getOperand(2).getReg(); + + auto NextMI = std::next(MI); + if (NextMI == MBB.end()) { + ++MI; + continue; + } + + MachineInstr &OrInstr = *NextMI; + unsigned OrOpc = OrInstr.getOpcode(); + + if ((OrOpc != X86::ORPSrr && OrOpc != X86::VPORrr) || + !OrInstr.getOperand(1).isReg() || + OrInstr.getOperand(1).getReg() != AndDst || + !OrInstr.getOperand(0).isReg() || !OrInstr.getOperand(2).isReg()) { + ++MI; + continue; + } + + Register OrDst = OrInstr.getOperand(0).getReg(); + Register OrOther = OrInstr.getOperand(2).getReg(); + + DebugLoc DL = AndInstr.getDebugLoc(); + + const TargetRegisterClass *RC = MRI.getRegClass(AndOp1); + if (!RC) + RC = MRI.getRegClass(AndOp2); + if (!RC) + continue; + + Register TmpReg = MRI.createVirtualRegister(RC); + + BuildMI(MBB, AndInstr, DL, TII->get(X86::VPANDrr), TmpReg) + .addReg(AndOp1) + .addReg(AndOp2); + + BuildMI(MBB, OrInstr, DL, TII->get(X86::VPORrr), OrDst) + .addReg(TmpReg) + .addReg(OrOther); + + MI = MBB.erase(MI); + MBB.erase(NextMI); + + Changed = true; + } + } + + return Changed; +} +} // namespace + +static RegisterPass + X("logical-combiner-x86", "Combine logical ops into AVX", false, false); diff --git a/llvm/compiler-course/llvm-ir/Kholin_K_DivOpt/CMakeLists.txt b/llvm/compiler-course/llvm-ir/Kholin_K_DivOpt/CMakeLists.txt new file mode 100644 index 0000000000000..70d1991f42b3d --- /dev/null +++ b/llvm/compiler-course/llvm-ir/Kholin_K_DivOpt/CMakeLists.txt @@ -0,0 +1,15 @@ +set(Title "DivOptPass") +set(Student "KholinKirill") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_LLVM_IR") + +if (NOT WIN32 AND NOT CYGWIN) + file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) + add_llvm_pass_plugin(${TARGET_NAME} ${SOURCES} + DEPENDS + intrinsics_gen + BUILDTREE_ONLY + ) + set(LLVM_TEST_DEPENDS ${TARGET_NAME} ${LLVM_TEST_DEPENDS} PARENT_SCOPE) +endif() + diff --git a/llvm/compiler-course/llvm-ir/Kholin_K_DivOpt/Kholin_K_DivOpt_pass.cpp b/llvm/compiler-course/llvm-ir/Kholin_K_DivOpt/Kholin_K_DivOpt_pass.cpp new file mode 100644 index 0000000000000..fff67f6d53644 --- /dev/null +++ b/llvm/compiler-course/llvm-ir/Kholin_K_DivOpt/Kholin_K_DivOpt_pass.cpp @@ -0,0 +1,89 @@ +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +void visitor(llvm::Function &F) { + for (auto &BB : F) { // function cycle block// + llvm::SmallVector DivsToReplace; + for (auto &I : BB) { // instruction cycle block + if (auto *BinOp = llvm::dyn_cast(&I)) { + if (BinOp->getOpcode() == llvm::Instruction::SDiv || + BinOp->getOpcode() == llvm::Instruction::UDiv) { + llvm::Value *Divisor = BinOp->getOperand( + 1); // get right operand from result = lhs op rhs + if (llvm::ConstantInt *ConstantDivisor = + llvm::dyn_cast(Divisor)) { + if (ConstantDivisor->getValue() == 0) { // value of rhs + continue; + } + if (ConstantDivisor->getValue().isPowerOf2()) { // check degree 2 + if (BinOp->getOpcode() == llvm::Instruction::SDiv && + ConstantDivisor->isNegative()) { // negative case + continue; + } + DivsToReplace.push_back(BinOp); + } + } + } + } + } + + for (auto *BinOp : DivsToReplace) { // replace div with shift + uint32_t ShiftAmount = llvm::cast(BinOp->getOperand(1)) + ->getValue() + .exactLogBase2(); + + llvm::IRBuilder<> Builder(BinOp); // initialize builder + + llvm::Value *Shift = nullptr; + + if (BinOp->getOpcode() == llvm::Instruction::SDiv) { // signed + Shift = Builder.CreateAShr(BinOp->getOperand(0), ShiftAmount); + } else { // unsigned + Shift = Builder.CreateLShr(BinOp->getOperand(0), ShiftAmount); + } + + BinOp->replaceAllUsesWith(Shift); // replace + + BinOp->eraseFromParent(); // remove old + } + } +} + +struct DivOptPass : llvm::PassInfoMixin { + llvm::PreservedAnalyses run(llvm::Function &F, + llvm::FunctionAnalysisManager &) { + visitor(F); + return llvm::PreservedAnalyses::all(); // preserve all passes + } + + static bool isRequired() { return true; } +}; + +} // namespace + +llvm::PassPluginLibraryInfo getDivToShiftPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "DivOptPass", LLVM_VERSION_STRING, + [](llvm::PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](llvm::StringRef Name, llvm::FunctionPassManager &FPM, + llvm::ArrayRef) { + if (Name == "div-opt-pass") { + FPM.addPass(DivOptPass()); + return true; + } + return false; + }); + }}; +} + +extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return getDivToShiftPluginInfo(); +} diff --git a/llvm/compiler-course/llvm-ir/beskhmelnova_k_replace_add/CMakeLists.txt b/llvm/compiler-course/llvm-ir/beskhmelnova_k_replace_add/CMakeLists.txt new file mode 100644 index 0000000000000..fb3c03a2d461c --- /dev/null +++ b/llvm/compiler-course/llvm-ir/beskhmelnova_k_replace_add/CMakeLists.txt @@ -0,0 +1,14 @@ +set(Title "ReplaceAddPass") +set(Student "Beskhmelnova_Kseniya") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_LLVM_IR") + +if (NOT WIN32 AND NOT CYGWIN) + file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) + add_llvm_pass_plugin(${TARGET_NAME} ${SOURCES} + DEPENDS + intrinsics_gen + BUILDTREE_ONLY + ) + set(LLVM_TEST_DEPENDS ${TARGET_NAME} ${LLVM_TEST_DEPENDS} PARENT_SCOPE) +endif() diff --git a/llvm/compiler-course/llvm-ir/beskhmelnova_k_replace_add/ReplaceAddPass.cpp b/llvm/compiler-course/llvm-ir/beskhmelnova_k_replace_add/ReplaceAddPass.cpp new file mode 100644 index 0000000000000..4decc906e3928 --- /dev/null +++ b/llvm/compiler-course/llvm-ir/beskhmelnova_k_replace_add/ReplaceAddPass.cpp @@ -0,0 +1,84 @@ +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace { +struct ReplaceAddPass : llvm::PassInfoMixin { + llvm::SmallDenseMap opToFunc = { + {llvm::Instruction::Add, "add"}, + {llvm::Instruction::Sub, "sub"}, + {llvm::Instruction::Mul, "mul"}, + {llvm::Instruction::SDiv, "div"}}; + + llvm::PreservedAnalyses run(llvm::Function &F, + llvm::FunctionAnalysisManager &) { + if (llvm::any_of(opToFunc, [&](const auto &entry) { + return F.getName() == entry.second; + })) { + return llvm::PreservedAnalyses::all(); + } + + bool changed = false; + llvm::Module *M = F.getParent(); + + std::map funcMap; + for (llvm::Function &Func : M->functions()) { + for (const auto &[opcode, funcName] : opToFunc) { + if (Func.getName().contains(funcName) && Func.arg_size() == 2) { + funcMap[opcode] = &Func; + } + } + } + + if (funcMap.empty()) { + return llvm::PreservedAnalyses::all(); + } + + for (llvm::BasicBlock &BB : F) { + for (llvm::Instruction &I : llvm::make_early_inc_range(BB)) { + if (auto *binOp = llvm::dyn_cast(&I)) { + auto it = funcMap.find(binOp->getOpcode()); + if (it != funcMap.end()) { + llvm::Function *replacementFunction = it->second; + llvm::IRBuilder<> builder(binOp); + + llvm::Value *call = + builder.CreateCall(replacementFunction, {binOp->getOperand(0), + binOp->getOperand(1)}); + + call->setName(binOp->getName()); + binOp->replaceAllUsesWith(call); + binOp->eraseFromParent(); + changed = true; + } + } + } + } + return changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); + } + + static bool isRequired() { return true; } +}; +} // namespace + +extern "C" LLVM_ATTRIBUTE_WEAK llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "ReplaceAddPass", "0.1", + [](llvm::PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](llvm::StringRef name, llvm::FunctionPassManager &FPM, + llvm::ArrayRef) -> bool { + if (name == "ReplaceAddPass") { + FPM.addPass(ReplaceAddPass{}); + return true; + } + return false; + }); + }}; +} diff --git a/llvm/compiler-course/llvm-ir/ionova_ekaterina_lab_2/CMakeLists.txt b/llvm/compiler-course/llvm-ir/ionova_ekaterina_lab_2/CMakeLists.txt new file mode 100644 index 0000000000000..549f286c07685 --- /dev/null +++ b/llvm/compiler-course/llvm-ir/ionova_ekaterina_lab_2/CMakeLists.txt @@ -0,0 +1,14 @@ +set(Title "FMAPass") +set(Student "Ionova_Ekaterina") +set(Group "FIIT1") +set(TARGET_NAME "${Title}_${Student}_${Group}_LLVM_IR") + +if (NOT WIN32 AND NOT CYGWIN) + file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) + add_llvm_pass_plugin(${TARGET_NAME} ${SOURCES} + DEPENDS + intrinsics_gen + BUILDTREE_ONLY + ) + set(LLVM_TEST_DEPENDS ${TARGET_NAME} ${LLVM_TEST_DEPENDS} PARENT_SCOPE) +endif() diff --git a/llvm/compiler-course/llvm-ir/ionova_ekaterina_lab_2/FMAPass.cpp b/llvm/compiler-course/llvm-ir/ionova_ekaterina_lab_2/FMAPass.cpp new file mode 100644 index 0000000000000..3d16a3316bc4a --- /dev/null +++ b/llvm/compiler-course/llvm-ir/ionova_ekaterina_lab_2/FMAPass.cpp @@ -0,0 +1,80 @@ +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" + +namespace { +struct FMAPass : llvm::PassInfoMixin { + llvm::PreservedAnalyses run(llvm::Function &F, + llvm::FunctionAnalysisManager &) { + bool Changed = false; + + for (llvm::BasicBlock &BB : F) { + for (llvm::Instruction &I : llvm::make_early_inc_range(BB)) { + if (auto *AddOp = llvm::dyn_cast(&I)) { + if (AddOp->getOpcode() != llvm::Instruction::FAdd) { + continue; + } + + for (unsigned i = 0; i < 2; ++i) { + if (auto *MultiplyOp = llvm::dyn_cast( + AddOp->getOperand(i))) { + if (MultiplyOp->getOpcode() == llvm::Instruction::FMul && + canReplaceFMul(MultiplyOp, AddOp)) { + llvm::Value *Addend = AddOp->getOperand(1 - i); + replaceWithFMA(AddOp, MultiplyOp, Addend); + Changed = true; + + break; + } + } + } + } + } + } + + return Changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); + } + + static bool isRequired() { return true; } + +private: + bool canReplaceFMul(llvm::BinaryOperator *MultiplyOp, + llvm::BinaryOperator *AddOp) { + return MultiplyOp->getOpcode() == llvm::Instruction::FMul && + MultiplyOp->hasOneUse(); + } + + void replaceWithFMA(llvm::BinaryOperator *AddOp, + llvm::BinaryOperator *MultiplyOp, llvm::Value *Addend) { + llvm::IRBuilder<> Builder(AddOp); + llvm::Value *FMA = Builder.CreateIntrinsic( + llvm::Intrinsic::fmuladd, {MultiplyOp->getType()}, + {MultiplyOp->getOperand(0), MultiplyOp->getOperand(1), Addend}, nullptr, + "fma"); + + AddOp->replaceAllUsesWith(FMA); + AddOp->eraseFromParent(); + + if (MultiplyOp->use_empty()) { + MultiplyOp->eraseFromParent(); + } + } +}; +} // namespace + +extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "FMAPass", "0.1", [](llvm::PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](llvm::StringRef name, llvm::FunctionPassManager &FPM, + llvm::ArrayRef) -> bool { + if (name == "fmapass") { + FPM.addPass(FMAPass{}); + return true; + } + return false; + }); + }}; +} diff --git a/llvm/compiler-course/llvm-ir/lopatin_fmul_fadd/CMakeLists.txt b/llvm/compiler-course/llvm-ir/lopatin_fmul_fadd/CMakeLists.txt new file mode 100644 index 0000000000000..67b0a19e150a3 --- /dev/null +++ b/llvm/compiler-course/llvm-ir/lopatin_fmul_fadd/CMakeLists.txt @@ -0,0 +1,14 @@ +set(Title "FmulFaddMergePass") +set(Student "LopatinIlya") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_LLVM_IR") + +if (NOT WIN32 AND NOT CYGWIN) + file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) + add_llvm_pass_plugin(${TARGET_NAME} ${SOURCES} + DEPENDS + intrinsics_gen + BUILDTREE_ONLY + ) + set(LLVM_TEST_DEPENDS ${TARGET_NAME} ${LLVM_TEST_DEPENDS} PARENT_SCOPE) +endif() diff --git a/llvm/compiler-course/llvm-ir/lopatin_fmul_fadd/fmulFaddMergePass.cpp b/llvm/compiler-course/llvm-ir/lopatin_fmul_fadd/fmulFaddMergePass.cpp new file mode 100644 index 0000000000000..961b8ea78dbe2 --- /dev/null +++ b/llvm/compiler-course/llvm-ir/lopatin_fmul_fadd/fmulFaddMergePass.cpp @@ -0,0 +1,91 @@ +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +struct FmulFaddMergePass : llvm::PassInfoMixin { + llvm::PreservedAnalyses run(llvm::Function &Func, + llvm::FunctionAnalysisManager &) { + bool Changed = false; + + struct ReplacementStruct { + llvm::BinaryOperator *FAdd; + llvm::BinaryOperator *FMul; + llvm::Value *ThirdOperand; + }; + + for (llvm::BasicBlock &BB : Func) { + std::vector ToReplace; + + auto CheckOperand = + [](llvm::Value *Operand, + llvm::Value *OtherOperand) -> llvm::BinaryOperator * { + if (auto *FMul = llvm::dyn_cast(Operand)) { + if (FMul->getOpcode() == llvm::Instruction::FMul) { + return FMul; + } + } + return nullptr; + }; + + // 1st pass: Collect replacements + for (llvm::Instruction &Inst : BB) { + if (auto *FAdd = llvm::dyn_cast(&Inst)) { + if (FAdd->getOpcode() == llvm::Instruction::FAdd) { + llvm::Value *Op0 = FAdd->getOperand(0); + llvm::Value *Op1 = FAdd->getOperand(1); + + if (auto *FMul = CheckOperand(Op0, Op1)) { + ToReplace.push_back({FAdd, FMul, Op1}); + } else if (auto *FMul = CheckOperand(Op1, Op0)) { + ToReplace.push_back({FAdd, FMul, Op0}); + } + } + } + } + + // 2nd pass, replacing + for (const auto &Info : ToReplace) { + llvm::IRBuilder<> Builder(Info.FAdd); + llvm::Value *FMulAdd = Builder.CreateIntrinsic( + llvm::Intrinsic::fmuladd, Info.FMul->getType(), + {Info.FMul->getOperand(0), Info.FMul->getOperand(1), + Info.ThirdOperand}); + + Info.FAdd->replaceAllUsesWith(FMulAdd); + Info.FAdd->eraseFromParent(); + + if (Info.FMul->use_empty()) { + Info.FMul->eraseFromParent(); + } + + Changed = true; + } + } + + return Changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); + } + + static bool isRequired() { return true; } +}; +} // namespace + +extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "FmulFaddMergePass", "0.1", + [](llvm::PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](llvm::StringRef Name, llvm::FunctionPassManager &FPM, + llvm::ArrayRef) -> bool { + if (Name == "FmulFaddMergePass") { + FPM.addPass(FmulFaddMergePass{}); + return true; + } + return false; + }); + }}; +} diff --git a/llvm/compiler-course/llvm-ir/sozonov_i_llvm_fmuladd/CMakeLists.txt b/llvm/compiler-course/llvm-ir/sozonov_i_llvm_fmuladd/CMakeLists.txt new file mode 100644 index 0000000000000..66abbe57e5044 --- /dev/null +++ b/llvm/compiler-course/llvm-ir/sozonov_i_llvm_fmuladd/CMakeLists.txt @@ -0,0 +1,14 @@ +set(Title "FmulFaddPass") +set(Student "Sozonov_Ilya") +set(Group "FIIT3") +set(TARGET_NAME "${Title}_${Student}_${Group}_LLVM_IR") + +if (NOT WIN32 AND NOT CYGWIN) + file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) + add_llvm_pass_plugin(${TARGET_NAME} ${SOURCES} + DEPENDS + intrinsics_gen + BUILDTREE_ONLY + ) + set(LLVM_TEST_DEPENDS ${TARGET_NAME} ${LLVM_TEST_DEPENDS} PARENT_SCOPE) +endif() diff --git a/llvm/compiler-course/llvm-ir/sozonov_i_llvm_fmuladd/FmulFaddPass.cpp b/llvm/compiler-course/llvm-ir/sozonov_i_llvm_fmuladd/FmulFaddPass.cpp new file mode 100644 index 0000000000000..a191b019ce221 --- /dev/null +++ b/llvm/compiler-course/llvm-ir/sozonov_i_llvm_fmuladd/FmulFaddPass.cpp @@ -0,0 +1,85 @@ +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +struct FmulFaddPass : llvm::PassInfoMixin { + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &) { + bool isModified = false; + llvm::SmallVector instructionsToRemove; + + for (llvm::BasicBlock &BB : func) { + for (llvm::Instruction &I : llvm::make_early_inc_range(BB)) { + if (I.getOpcode() != llvm::Instruction::FAdd) + continue; + + llvm::Value *Op1 = I.getOperand(0); + llvm::Value *Op2 = I.getOperand(1); + + llvm::Instruction *MulInst = nullptr; + llvm::Value *A = nullptr, *B = nullptr, *C = nullptr; + + llvm::Value *Operands[2] = {Op1, Op2}; + + for (int i = 0; i < 2; ++i) { + if (auto *Mul = llvm::dyn_cast(Operands[i])) { + if (Mul->getOpcode() == llvm::Instruction::FMul) { + A = Mul->getOperand(0); + B = Mul->getOperand(1); + C = Operands[1 - i]; + MulInst = Mul; + break; //hasOneUse + } + } + } + + if (MulInst) { + if (!MulInst->hasOneUse()) + continue; + + llvm::IRBuilder<> builder(&I); + llvm::Function *FmaFunc = llvm::Intrinsic::getDeclaration( + func.getParent(), llvm::Intrinsic::fmuladd, I.getType()); + + llvm::Value *Fma = builder.CreateCall(FmaFunc, {A, B, C}); + I.replaceAllUsesWith(Fma); + instructionsToRemove.push_back(&I); + instructionsToRemove.push_back(MulInst); + + isModified = true; + } + } + } + + for (llvm::Instruction *I : instructionsToRemove) + I->eraseFromParent(); + + return isModified ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); + } + + static bool isRequired() { return true; } +}; +} // namespace + +extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "FmulFaddPass", "0.1", + [](llvm::PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](llvm::StringRef name, llvm::FunctionPassManager &FPM, + llvm::ArrayRef) -> bool { + if (name == "FmulFaddPass") { + FPM.addPass(FmulFaddPass{}); + return true; + } + return false; + }); + }}; +} diff --git a/llvm/test/compiler-course/Kholin_K_DivOpt/test.ll b/llvm/test/compiler-course/Kholin_K_DivOpt/test.ll new file mode 100644 index 0000000000000..9b915f4671460 --- /dev/null +++ b/llvm/test/compiler-course/Kholin_K_DivOpt/test.ll @@ -0,0 +1,164 @@ +; RUN: opt -load-pass-plugin %llvmshlibdir/DivOptPass_KholinKirill_FIIT3_LLVM_IR%pluginext -passes=div-opt-pass -S %s | FileCheck %s + +; CHECK-LABEL: define dso_local noundef i32 @_Z18unsigned_part_testjj(i32 noundef %lhs1, i32 noundef %lhs2) { +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = lshr i32 %lhs1, 1 +; CHECK-NEXT: %div1 = udiv i32 %lhs1, -2 +; CHECK-NEXT: %1 = lshr i32 %lhs2, 3 +; CHECK-NEXT: %add = add i32 %0, %div1 +; CHECK-NEXT: %add3 = add i32 %add, %1 + + +define dso_local noundef i32 @_Z18unsigned_part_testjj(i32 noundef %lhs1, i32 noundef %lhs2) #0 { +entry: + %div = udiv i32 %lhs1, 2 + %div1 = udiv i32 %lhs1, -2 + %div2 = udiv i32 %lhs2, 8 + %add = add i32 %div, %div1 + %add3 = add i32 %add, %div2 + ret i32 %add3 +} + +;unsigned unsigned_part_test(unsigned lhs1, unsigned lhs2) { +; unsigned int result_type_OK1 = lhs1 / 2; +; unsigned int UB1 = lhs1 / (-2); +; unsigned int result_type_OK2 = lhs2 / 8u; +; +; return result_type_OK1 + UB1 + result_type_OK2; +;} + +; CHECK-LABEL: define dso_local noundef i32 @_Z17signed_part1_testii(i32 noundef %lhs1, i32 noundef %lhs2) { +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = ashr i32 %lhs1, 6 +; CHECK-NEXT: %div1 = sdiv i32 %lhs1, -64 +; CHECK: %1 = ashr i32 %sub, 6 +; CHECK-NEXT: %div4 = sdiv i32 %sub, -64 +; CHECK-NEXT: %2 = lshr i32 %lhs2, 5 +; CHECK: %3 = lshr i32 %sub6, 5 +; CHECK-NEXT: %add = add nsw i32 %0, %div1 +; CHECK-NEXT: %add8 = add nsw i32 %add, %1 +; CHECK-NEXT: %add9 = add nsw i32 %add8, %div4 +; CHECK-NEXT: %add10 = add nsw i32 %add9, %2 +; CHECK-NEXT: %add11 = add nsw i32 %add10, %3 + +define dso_local noundef i32 @_Z17signed_part1_testii(i32 noundef %lhs1, i32 noundef %lhs2) #0 { +entry: + %div = sdiv i32 %lhs1, 64 + %div1 = sdiv i32 %lhs1, -64 + %sub = sub nsw i32 0, %lhs1 + %div2 = sdiv i32 %sub, 64 + %div4 = sdiv i32 %sub, -64 + %div5 = udiv i32 %lhs2, 32 + %sub6 = sub nsw i32 0, %lhs2 + %div7 = udiv i32 %sub6, 32 + %add = add nsw i32 %div, %div1 + %add8 = add nsw i32 %add, %div2 + %add9 = add nsw i32 %add8, %div4 + %add10 = add nsw i32 %add9, %div5 + %add11 = add nsw i32 %add10, %div7 + ret i32 %add11 +} + +;signed int signed_part1_test(signed int lhs1, signed int lhs2) { +; signed int result_type_OK3 = lhs1 / 64; +; signed int Not_UB1 = lhs1 / (-64); +; signed int result_type_OK4 = (-lhs1) / 64; +; signed int Not_UB2 = (-lhs1) / (-64); +; signed int result_type_OK5 = lhs2 / 32u; +; signed int UB2 = (-lhs2) / 32u; +; +; return result_type_OK3 + Not_UB1 + result_type_OK4 + +; Not_UB2 + result_type_OK5 + UB2; +;} + +; CHECK-LABEL: define dso_local noundef i32 @_Z17signed_part2_testii(i32 noundef %lhs1, i32 noundef %lhs2) { +; CHECK-NEXT: entry: +; CHECK-NEXT: %div = udiv i32 %lhs1, 3 +; CHECK: %div1 = udiv i32 %sub, 3 +; CHECK-NEXT: %0 = ashr i32 %lhs2, 2 +; CHECK: %1 = lshr i32 %sub3, 2 +; CHECK-NEXT: %add = add nsw i32 %div, %div1 +; CHECK-NEXT: %add5 = add nsw i32 %add, %0 +; CHECK-NEXT: %add6 = add nsw i32 %add5, %1 + +define dso_local noundef i32 @_Z17signed_part2_testii(i32 noundef %lhs1, i32 noundef %lhs2) #0 { +entry: + %div = udiv i32 %lhs1, 3 + %sub = sub nsw i32 0, %lhs1 + %div1 = udiv i32 %sub, 3 + %div2 = sdiv i32 %lhs2, 4 + %sub3 = sub nsw i32 0, %lhs2 + %div4 = udiv i32 %sub3, 4 + %add = add nsw i32 %div, %div1 + %add5 = add nsw i32 %add, %div2 + %add6 = add nsw i32 %add5, %div4 + ret i32 %add6 +} + +;signed int signed_part2_test(signed int lhs1, signed int lhs2) { +; signed int result_type_OK7 = lhs1 / 3u; +; signed int UB3 = (-lhs1) / 3u; +; signed int result_type_OK9 = lhs2 / 4; +; signed int UB4 = (-lhs2) / 4u; +; +; return result_type_OK7 + UB3 + result_type_OK9 + UB4; +;} + +; CHECK-LABEL: define dso_local noundef i32 @_Z11other_typesdix(double noundef %lhs1, i32 noundef %lhs2, i64 noundef %lhs3) { +; CHECK-NEXT: entry: +; CHECK-NEXT: %div = fdiv double %lhs1, 4.000000e+00 +; CHECK-NEXT: %div1 = fdiv double %lhs1, -4.000000e+00 +; CHECK-NEXT: %conv = sitofp i32 %lhs2 to float +; CHECK-NEXT: %div2 = fdiv float %conv, 0x4042BC2900000000 +; CHECK-NEXT: %conv3 = fptosi float %div2 to i32 +; CHECK-NEXT: %div5 = fdiv float %conv, 0xC042BC2900000000 +; CHECK-NEXT: %conv6 = fptosi float %div5 to i32 +; CHECK-NEXT: %0 = ashr i64 %lhs3, 5 +; CHECK-NEXT: %div8 = sdiv i64 %lhs3, -32 +; CHECK-NEXT: %add = fadd double %div, %div1 +; CHECK-NEXT: %conv9 = sitofp i32 %conv3 to double +; CHECK-NEXT: %add10 = fadd double %add, %conv9 +; CHECK-NEXT: %conv11 = sitofp i32 %conv6 to double +; CHECK-NEXT: %add12 = fadd double %add10, %conv11 +; CHECK-NEXT: %conv13 = sitofp i64 %0 to double +; CHECK-NEXT: %add14 = fadd double %add12, %conv13 +; CHECK-NEXT: %conv15 = sitofp i64 %div8 to double +; CHECK-NEXT: %add16 = fadd double %add14, %conv15 +; CHECK-NEXT: %conv17 = fptosi double %add16 to i32 + +define dso_local noundef i32 @_Z11other_typesdix(double noundef %lhs1, i32 noundef %lhs2, i64 noundef %lhs3) #0 { +entry: + %div = fdiv double %lhs1, 4.000000e+00 + %div1 = fdiv double %lhs1, -4.000000e+00 + %conv = sitofp i32 %lhs2 to float + %div2 = fdiv float %conv, 0x4042BC2900000000 + %conv3 = fptosi float %div2 to i32 + %div5 = fdiv float %conv, 0xC042BC2900000000 + %conv6 = fptosi float %div5 to i32 + %div7 = sdiv i64 %lhs3, 32 + %div8 = sdiv i64 %lhs3, -32 + %add = fadd double %div, %div1 + %conv9 = sitofp i32 %conv3 to double + %add10 = fadd double %add, %conv9 + %conv11 = sitofp i32 %conv6 to double + %add12 = fadd double %add10, %conv11 + %conv13 = sitofp i64 %div7 to double + %add14 = fadd double %add12, %conv13 + %conv15 = sitofp i64 %div8 to double + %add16 = fadd double %add14, %conv15 + %conv17 = fptosi double %add16 to i32 + ret i32 %conv17 +} + +;int other_types(double lhs1, int lhs2, long long lhs3) { +; double result_type_OK11 = lhs1 / 4; +; double result_type_OK12 = lhs1 / (-4); +; int result_type_OK13 = lhs2 / 37.47f; +; int result_type_OK14 = lhs2 / (-37.47f); +; long long result_type_OK15 = lhs3 / 32; +; long long result_type_OK16 = lhs3 / (-32); +; int over_bits = 32 / 64; +; +; return result_type_OK11 + result_type_OK12 + result_type_OK13 + +; result_type_OK14 + result_type_OK15 + result_type_OK16; +;} diff --git a/llvm/test/compiler-course/beskhmelnova_k_replace_add/litTestReplaceAdd.ll b/llvm/test/compiler-course/beskhmelnova_k_replace_add/litTestReplaceAdd.ll new file mode 100644 index 0000000000000..245660cf96798 --- /dev/null +++ b/llvm/test/compiler-course/beskhmelnova_k_replace_add/litTestReplaceAdd.ll @@ -0,0 +1,46 @@ +; RUN: opt -load-pass-plugin %llvmshlibdir/ReplaceAddPass_Beskhmelnova_Kseniya_FIIT1_LLVM_IR%pluginext \ +; RUN: -passes="ReplaceAddPass" -S %s | FileCheck %s + +; CHECK: define i32 @add(i32 %a, i32 %b) +; CHECK: %result = add i32 %a, %b +; CHECK: ret i32 %result + +; CHECK: define i32 @foo(i32 %x, i32 %y) +; CHECK: call i32 @add(i32 %x, i32 %y) +; CHECK: ret i32 %sum + +; CHECK-NOT: add i32 + +define i32 @add(i32 %a, i32 %b) { +entry: + %result = add i32 %a, %b + ret i32 %result +} + +define i32 @foo(i32 %x, i32 %y) { +entry: + %sum = add i32 %x, %y + ret i32 %sum +} + +; CHECK: define i32 @boo(i32 %x, i32 %y) +; CHECK: call i32 @sub(i32 %x, i32 %y) +; CHECK: ret i32 %sum + +; CHECK: define i32 @sub(i32 %a, i32 %b) +; CHECK: %result = sub i32 %a, %b +; CHECK: ret i32 %result + +; CHECK-NOT: sub i32 + +define i32 @boo(i32 %x, i32 %y) { +entry: + %sum = sub i32 %x, %y + ret i32 %sum +} + +define i32 @sub(i32 %a, i32 %b) { +entry: + %result = sub i32 %a, %b + ret i32 %result +} diff --git a/llvm/test/compiler-course/ionova_ekaterina_lab_2/test.ll b/llvm/test/compiler-course/ionova_ekaterina_lab_2/test.ll new file mode 100644 index 0000000000000..5ac6585349113 --- /dev/null +++ b/llvm/test/compiler-course/ionova_ekaterina_lab_2/test.ll @@ -0,0 +1,194 @@ +; RUN: opt -load-pass-plugin %llvmshlibdir/FMAPass_Ionova_Ekaterina_FIIT1_LLVM_IR%pluginext \ +; RUN: -passes="fmapass" -S %s | FileCheck %s + +; double f1(double a, double b, double c) { +; return a * b + c; +; } + +; CHECK-LABEL: @_Z2f1ddd +; CHECK-NEXT: %fma = call double @llvm.fmuladd.f64(double %0, double %1, double %2) +; CHECK-NEXT: ret double %fma + +define dso_local noundef double @_Z2f1ddd(double noundef %0, double noundef %1, double noundef %2) local_unnamed_addr { + %4 = fmul double %0, %1 + %5 = fadd double %4, %2 + ret double %5 +} + + +; double f2(double a, double b, double c, double d, double e) { +; double result1 = a * b + c; +; double result2 = d * e + result1; +; return result2; +; } + +; CHECK-LABEL: @_Z2f2ddddd +; CHECK-NEXT: %fma = call double @llvm.fmuladd.f64(double %0, double %1, double %2) +; CHECK-NEXT: %fma1 = call double @llvm.fmuladd.f64(double %3, double %4, double %fma) +; CHECK-NEXT: ret double %fma1 + +define dso_local noundef double @_Z2f2ddddd(double noundef %0, double noundef %1, double noundef %2, double noundef %3, double noundef %4) local_unnamed_addr { + %6 = fmul double %0, %1 + %7 = fadd double %6, %2 + %8 = fmul double %3, %4 + %9 = fadd double %7, %8 + ret double %9 +} + + +; double f3(double a, double b, double c, double d) { +; double result1 = a * b; +; double result3 = result1 + c; +; double result4 = result1 + d; +; return result3 + result4; +; } + +; CHECK-LABEL: @_Z2f3dddd +; CHECK: %5 = fmul double %0, %1 +; CHECK-NEXT: %6 = fadd double %5, %2 +; CHECK-NEXT: %7 = fadd double %5, %3 +; CHECK-NEXT: %8 = fadd double %6, %7 +; CHECK-NEXT: ret double %8 + +define dso_local noundef double @_Z2f3dddd(double noundef %0, double noundef %1, double noundef %2, double noundef %3) local_unnamed_addr { + %5 = fmul double %0, %1 + %6 = fadd double %5, %2 + %7 = fadd double %5, %3 + %8 = fadd double %6, %7 + ret double %8 +} + + +; double f4(double a, double b, double c) { +; double result1 = a * b; +; double result2 = c + 1.0; +; return result1 + result2; +; } + +; CHECK-LABEL: @_Z2f4ddd +; CHECK: %4 = fadd double %2, 1.000000e+00 +; CHECK-NEXT: %fma = call double @llvm.fmuladd.f64(double %0, double %1, double %4) +; CHECK-NEXT: ret double %fma + +define dso_local noundef double @_Z2f4ddd(double noundef %0, double noundef %1, double noundef %2) local_unnamed_addr { + %4 = fmul double %0, %1 + %5 = fadd double %2, 1.000000e+00 + %6 = fadd double %4, %5 + ret double %6 +} + + +; double f5(double a, double b, double c, double d) { +; double result1 = a * b + c; +; double result2 = result1 * d + c; +; return result2; +; } + +; CHECK-LABEL: @_Z2f5dddd +; CHECK-NEXT: %fma = call double @llvm.fmuladd.f64(double %0, double %1, double %2) +; CHECK-NEXT: %fma1 = call double @llvm.fmuladd.f64(double %fma, double %3, double %2) +; CHECK-NEXT: ret double %fma1 + +define dso_local noundef double @_Z2f5dddd(double noundef %0, double noundef %1, double noundef %2, double noundef %3) local_unnamed_addr { + %5 = fmul double %0, %1 + %6 = fadd double %5, %2 + %7 = fmul double %6, %3 + %8 = fadd double %7, %2 + ret double %8 +} + + +; float f6(float a, float b, float c) { +; return a * b + c; +; } + +; CHECK-LABEL: @_Z2f6fff +; CHECK-NEXT: %fma = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +; CHECK-NEXT: ret float %fma + +define dso_local noundef float @_Z2f6fff(float noundef %0, float noundef %1, float noundef %2) local_unnamed_addr { + %4 = fmul float %0, %1 + %5 = fadd float %4, %2 + ret float %5 +} + + +; float f7(float a, float b, float c, float d, float e) { +; float result1 = a * b + c; +; float result2 = d * e + result1; +; return result2; +; } + +; CHECK-LABEL: @_Z2f7fffff +; CHECK-NEXT: %fma = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +; CHECK-NEXT: %fma1 = call float @llvm.fmuladd.f32(float %3, float %4, float %fma) +; CHECK-NEXT: ret float %fma1 + +define dso_local noundef float @_Z2f7fffff(float noundef %0, float noundef %1, float noundef %2, float noundef %3, float noundef %4) local_unnamed_addr { + %6 = fmul float %0, %1 + %7 = fadd float %6, %2 + %8 = fmul float %3, %4 + %9 = fadd float %7, %8 + ret float %9 +} + + +; int f8(int a, int b, int c) { +; return a * b + c; +; } + +; CHECK-LABEL: @_Z2f8iii +; CHECK: %4 = mul nsw i32 %0, %1 +; CHECK-NEXT: %5 = add nsw i32 %4, %2 +; CHECK-NEXT: ret i32 %5 + +define dso_local noundef i32 @_Z2f8iii(i32 noundef %0, i32 noundef %1, i32 noundef %2) local_unnamed_addr { + %4 = mul nsw i32 %0, %1 + %5 = add nsw i32 %4, %2 + ret i32 %5 +} + + +; int f9(int a, int b, int c, int d, int e) { +; int result1 = a * b + c; +; int result2 = d * e + result1; +; return result2; +; } + +; CHECK-LABEL: @_Z2f9iiiii +; CHECK: %6 = mul nsw i32 %0, %1 +; CHECK-NEXT: %7 = add nsw i32 %6, %2 +; CHECK-NEXT: %8 = mul nsw i32 %3, %4 +; CHECK-NEXT: %9 = add nsw i32 %7, %8 +; CHECK-NEXT: ret i32 %9 + +define dso_local noundef i32 @_Z2f9iiiii(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, i32 noundef %4) local_unnamed_addr { + %6 = mul nsw i32 %0, %1 + %7 = add nsw i32 %6, %2 + %8 = mul nsw i32 %3, %4 + %9 = add nsw i32 %7, %8 + ret i32 %9 +} + + +; float foo(float a, float b, float c) { +; float t1 = a * b; +; float t2 = t1 + c; +; float t3 = t2 / t1 + 1; +; return t3; +; } + +; CHECK-LABEL: @_Z3foofff +; CHECK: %4 = fmul float %0, %1 +; CHECK-NEXT: %5 = fadd float %4, %2 +; CHECK-NEXT: %6 = fdiv float %5, %4 +; CHECK-NEXT: %7 = fadd float %6, 1.000000e+00 +; CHECK-NEXT: ret float %7 + +define dso_local noundef float @_Z3foofff(float noundef %0, float noundef %1, float noundef %2) local_unnamed_addr { + %4 = fmul float %0, %1 + %5 = fadd float %4, %2 + %6 = fdiv float %5, %4 + %7 = fadd float %6, 1.000000e+00 + ret float %7 +} diff --git a/llvm/test/compiler-course/lopatin_fmul_fadd/litTestFmulFaddMerge.ll b/llvm/test/compiler-course/lopatin_fmul_fadd/litTestFmulFaddMerge.ll new file mode 100644 index 0000000000000..ff56f4d2fa5f2 --- /dev/null +++ b/llvm/test/compiler-course/lopatin_fmul_fadd/litTestFmulFaddMerge.ll @@ -0,0 +1,53 @@ +; RUN: opt -load-pass-plugin %llvmshlibdir/FmulFaddMergePass_LopatinIlya_FIIT3_LLVM_IR%pluginext \ +; RUN: -passes="FmulFaddMergePass" -S %s | FileCheck %s + +; CHECK-LABEL: @fmaDouble +; CHECK: call double @llvm.fmuladd.f64(double %A, double %B, double %C) +; CHECK-NOT: fmul double +; CHECK-NOT: fadd double +define dso_local noundef double @fmaDouble(double %A, double %B, double %C) { +entry: + %mul = fmul double %A, %B + %add = fadd double %mul, %C + ret double %add +} + +; CHECK-LABEL: @fmaFloat +; CHECK: call float @llvm.fmuladd.f32(float %A, float %B, float %C) +; CHECK-NOT: fmul float +; CHECK-NOT: fadd float +define dso_local noundef float @fmaFloat(float %A, float %B, float %C) { +entry: + %mul = fmul float %A, %B + %add = fadd float %mul, %C + ret float %add +} + +; CHECK-LABEL: @recursiveTest +; CHECK: fadd float %B, %C +; CHECK: fadd float %A, %B +; CHECK: call float @llvm.fmuladd.f32(float %add1, float %B, float %add) +define dso_local noundef float @recursiveTest(float %A, float %B, float %C) { +entry: + %add = fadd float %B, %C + %add1 = fadd float %A, %B + %mul = fmul float %add1, %B + %add2 = fadd float %add, %mul + ret float %add2 +} + +; CHECK-LABEL: @foo +; CHECK: call float @llvm.fmuladd.f32(float %A, float %B, float %C) +; CHECK: call float @llvm.fmuladd.f32(float %A, float %B, float 1.000000e+00) +; CHECK: fdiv float %0, %1 +; CHECK-NOT: fmul float +; CHECK-NOT: fadd float +define float @foo(float %A, float %B, float %C) { +entry: + %mul = fmul float %A, %B + %add = fadd float %mul, %C + %add1 = fadd float %mul, 1.000000e+00 + %div = fdiv float %add, %add1 + ret float %div +} + diff --git a/llvm/test/compiler-course/sozonov_i_llvm_fmuladd/lit_test_llvm_ir_.ll b/llvm/test/compiler-course/sozonov_i_llvm_fmuladd/lit_test_llvm_ir_.ll new file mode 100644 index 0000000000000..d61de55262c17 --- /dev/null +++ b/llvm/test/compiler-course/sozonov_i_llvm_fmuladd/lit_test_llvm_ir_.ll @@ -0,0 +1,151 @@ +; RUN: opt -load-pass-plugin %llvmshlibdir/FmulFaddPass_Sozonov_Ilya_FIIT3_LLVM_IR%pluginext -passes=FmulFaddPass -S %s | FileCheck %s + +; Test 1: (a * b) + c - should be replaced with llvm.fmuladd(a, b, c) +; CHECK-LABEL: @fmul_fadd_ab_c +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) +; CHECK-NEXT: ret float %0 +define float @fmul_fadd_ab_c(float %a, float %b, float %c) { +entry: + %mul = fmul float %a, %b + %add = fadd float %mul, %c + ret float %add +} + +; Test 2: c + (a * b) - should also be replaced with llvm.fmuladd(a, b, c) +; CHECK-LABEL: @fadd_c_fmul_ab +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) +; CHECK-NEXT: ret float %0 +define float @fadd_c_fmul_ab(float %a, float %b, float %c) { +entry: + %mul = fmul float %a, %b + %add = fadd float %c, %mul + ret float %add +} + +; Test 3: a * (c + b) - addition first (no matching pattern) +; CHECK-LABEL: @no_match_fadd_then_fmul +; CHECK-NEXT: entry: +; CHECK-NEXT: %add = fadd float %c, %b +; CHECK-NEXT: %mul = fmul float %a, %add +; CHECK-NEXT: ret float %mul +define float @no_match_fadd_then_fmul(float %a, float %b, float %c) { +entry: + %add = fadd float %c, %b + %mul = fmul float %a, %add + ret float %mul +} + +; Test 4: (a + b) * c — addition comes first (should not match) +; CHECK-LABEL: @no_match_add_then_mul +; CHECK-NEXT: entry: +; CHECK-NEXT: %add = fadd float %a, %b +; CHECK-NEXT: %mul = fmul float %add, %c +; CHECK-NEXT: ret float %mul +define float @no_match_add_then_mul(float %a, float %b, float %c) { +entry: + %add = fadd float %a, %b + %mul = fmul float %add, %c + ret float %mul +} + +; Test 5: (a * a) + a - same operand used in multiple places (should still replace) +; CHECK-LABEL: @fmul_fadd_reuse +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = call float @llvm.fmuladd.f32(float %a, float %a, float %a) +; CHECK-NEXT: ret float %0 +define float @fmul_fadd_reuse(float %a) { +entry: + %mul = fmul float %a, %a + %add = fadd float %mul, %a + ret float %add +} + +; Test 6: ((a * b) + c) + d - nested expression (should replace inner only) +; CHECK-LABEL: @nested_fmul_fadd_then_add +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) +; CHECK-NEXT: %add2 = fadd float %0, %d +; CHECK-NEXT: ret float %add2 +define float @nested_fmul_fadd_then_add(float %a, float %b, float %c, float %d) { +entry: + %mul = fmul float %a, %b + %add1 = fadd float %mul, %c + %add2 = fadd float %add1, %d + ret float %add2 +} + +; Test 7: (a * b) + c — double precision (should replace) +; CHECK-LABEL: @fmul_fadd_double +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = call double @llvm.fmuladd.f64(double %a, double %b, double %c) +; CHECK-NEXT: ret double %0 +define double @fmul_fadd_double(double %a, double %b, double %c) { +entry: + %mul = fmul double %a, %b + %add = fadd double %mul, %c + ret double %add +} + +; Test 8: (2.0 * a) + 1.0 - used constants (should replace) +; CHECK-LABEL: @fmul_fadd_with_constants +; CHECK-NEXT: entry: +; CHECK-NOT: %mul = fmul float 2.0, %a +; CHECK-NOT: %add = fadd float %mul, 1.0 +; CHECK-NEXT: %0 = call float @llvm.fmuladd.f32(float 2.000000e+00, float %a, float 1.000000e+00) +; CHECK-NEXT: ret float %0 +define float @fmul_fadd_with_constants(float %a) { +entry: + %mul = fmul float 2.0, %a + %add = fadd float %mul, 1.0 + ret float %add +} + +; Test 9: (x * x) + y - one operand used multiple times (should replace) +; CHECK-LABEL: @fmul_fadd_duplicate_operand +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = call float @llvm.fmuladd.f32(float %x, float %x, float %y) +; CHECK-NEXT: ret float %0 +define float @fmul_fadd_duplicate_operand(float %x, float %y) { +entry: + %mul = fmul float %x, %x + %add = fadd float %mul, %y + ret float %add +} + +; Test 10: (x = a * b; y = x + c; return x + y) - use of intermediate result +; CHECK-LABEL: @fmul_used_multiple_times +; CHECK-NEXT: entry: +; CHECK-NEXT: %mul = fmul float %a, %b +; CHECK-NEXT: %add = fadd float %mul, %c +; CHECK-NEXT: %add2 = fadd float %mul, %add +; CHECK-NEXT: ret float %add2 +define float @fmul_used_multiple_times(float %a, float %b, float %c) { +entry: + %mul = fmul float %a, %b + %add = fadd float %mul, %c + %add2 = fadd float %mul, %add + ret float %add2 +} + +; Test 11: already fused with llvm.fmuladd +; CHECK-LABEL: @already_fused_fmuladd +; CHECK-NEXT: entry: +; CHECK-NEXT: %fma = call float @llvm.fmuladd.f32(float %a, float %b, float %c) +; CHECK-NEXT: ret float %fma +define float @already_fused_fmuladd(float %a, float %b, float %c) { +entry: + %fma = call float @llvm.fmuladd.f32(float %a, float %b, float %c) + ret float %fma +} + + +define float @fmul_used_multiple_times_3(float %a, float %b, float %c, float %d) { +entry: + %mul1 = fmul float %a, %b + %mul2 = fmul float %c, %d + %add = fadd float %mul1, %mul2 + %add2 = fadd float %mul1, %add + ret float %add2 +} \ No newline at end of file diff --git a/llvm/test/compiler-course/sozonov_i_logical_combiner/test_backend.mir b/llvm/test/compiler-course/sozonov_i_logical_combiner/test_backend.mir new file mode 100644 index 0000000000000..4b2414cb7e9a9 --- /dev/null +++ b/llvm/test/compiler-course/sozonov_i_logical_combiner/test_backend.mir @@ -0,0 +1,1461 @@ +# RUN: llc -mtriple x86_64-unknown-linux-gnu --load=%llvmshlibdir/LogicalCombinerPass_Sozonov_Ilya_FIIT3_BACKEND%shlibext \ +# RUN: -run-pass=logical-combiner-x86 %s -o - | FileCheck %s + +--- | + ; ModuleID = 'llvm/test/compiler-course/sozonov_i_logical_combiner/test.ll' + source_filename = "test.cpp" + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + target triple = "x86_64-pc-linux-gnu" + + module asm ".globl _ZSt21ios_base_library_initv" + + %"class.std::basic_ostream" = type { ptr, %"class.std::basic_ios" } + %"class.std::basic_ios" = type { %"class.std::ios_base", ptr, i8, i8, ptr, ptr, ptr, ptr } + %"class.std::ios_base" = type { ptr, i64, i64, i32, i32, i32, ptr, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, ptr, %"class.std::locale" } + %"struct.std::ios_base::_Words" = type { ptr, i64 } + %"class.std::locale" = type { ptr } + %"class.std::ctype" = type <{ %"class.std::locale::facet.base", [4 x i8], ptr, i8, [7 x i8], ptr, ptr, ptr, i8, [256 x i8], [256 x i8], i8, [6 x i8] }> + %"class.std::locale::facet.base" = type <{ ptr, i32 }> + + @_ZSt4cout = external global %"class.std::basic_ostream", align 8 + + ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable + define dso_local noundef zeroext i1 @_Z11and_or_testiii(i32 noundef %0, i32 noundef %1, i32 noundef %2) local_unnamed_addr #0 { + %4 = and i32 %1, %0 + %5 = icmp ne i32 %4, 0 + %6 = zext i1 %5 to i32 + %7 = or i32 %6, %2 + %8 = icmp ne i32 %7, 0 + ret i1 %8 + } + + ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable + define dso_local noundef zeroext i1 @_Z11or_xor_testiii(i32 noundef %0, i32 noundef %1, i32 noundef %2) local_unnamed_addr #0 { + %4 = or i32 %1, %0 + %5 = icmp ne i32 %4, 0 + %6 = zext i1 %5 to i32 + %7 = icmp ne i32 %6, %2 + ret i1 %7 + } + + ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable + define dso_local noundef zeroext i1 @_Z12and_xor_testiii(i32 noundef %0, i32 noundef %1, i32 noundef %2) local_unnamed_addr #0 { + %4 = and i32 %1, %0 + %5 = icmp ne i32 %4, 0 + %6 = zext i1 %5 to i32 + %7 = icmp ne i32 %6, %2 + ret i1 %7 + } + + ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable + define dso_local noundef zeroext i1 @_Z15and_or_xor_testiiii(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3) local_unnamed_addr #0 { + %5 = and i32 %1, %0 + %6 = icmp ne i32 %5, 0 + %7 = zext i1 %6 to i32 + %8 = or i32 %7, %2 + %9 = icmp ne i32 %8, 0 + %10 = zext i1 %9 to i32 + %11 = icmp ne i32 %10, %3 + ret i1 %11 + } + + ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable + define dso_local noundef zeroext i1 @_Z12and_and_testiii(i32 noundef %0, i32 noundef %1, i32 noundef %2) local_unnamed_addr #0 { + %4 = and i32 %1, %0 + %5 = icmp ne i32 %4, 0 + %6 = and i32 %2, 1 + %7 = icmp ne i32 %6, 0 + %8 = and i1 %5, %7 + ret i1 %8 + } + + ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable + define dso_local noundef zeroext i1 @_Z12xor_xor_testiii(i32 noundef %0, i32 noundef %1, i32 noundef %2) local_unnamed_addr #0 { + %4 = icmp ne i32 %0, %1 + %5 = zext i1 %4 to i32 + %6 = icmp ne i32 %5, %2 + ret i1 %6 + } + + ; Function Attrs: mustprogress norecurse uwtable + define dso_local noundef i32 @main() local_unnamed_addr #1 { + %1 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo9_M_insertIbEERSoT_(ptr noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i1 noundef zeroext true) + %2 = load ptr, ptr %1, align 8, !tbaa !5 + %3 = getelementptr i8, ptr %2, i64 -24 + %4 = load i64, ptr %3, align 8 + %5 = getelementptr inbounds i8, ptr %1, i64 %4 + %6 = getelementptr inbounds %"class.std::basic_ios", ptr %5, i64 0, i32 5 + %7 = load ptr, ptr %6, align 8, !tbaa !8 + %8 = icmp eq ptr %7, null + br i1 %8, label %9, label %10 + + 9: ; preds = %0 + tail call void @_ZSt16__throw_bad_castv() #4 + unreachable + + 10: ; preds = %0 + %11 = getelementptr inbounds %"class.std::ctype", ptr %7, i64 0, i32 8 + %12 = load i8, ptr %11, align 8, !tbaa !20 + %13 = icmp eq i8 %12, 0 + br i1 %13, label %17, label %14 + + 14: ; preds = %10 + %15 = getelementptr inbounds %"class.std::ctype", ptr %7, i64 0, i32 9, i64 10 + %16 = load i8, ptr %15, align 1, !tbaa !23 + br label %22 + + 17: ; preds = %10 + tail call void @_ZNKSt5ctypeIcE13_M_widen_initEv(ptr noundef nonnull align 8 dereferenceable(570) %7) + %18 = load ptr, ptr %7, align 8, !tbaa !5 + %19 = getelementptr inbounds ptr, ptr %18, i64 6 + %20 = load ptr, ptr %19, align 8 + %21 = tail call noundef signext i8 %20(ptr noundef nonnull align 8 dereferenceable(570) %7, i8 noundef signext 10) + br label %22 + + 22: ; preds = %17, %14 + %23 = phi i8 [ %16, %14 ], [ %21, %17 ] + %24 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo3putEc(ptr noundef nonnull align 8 dereferenceable(8) %1, i8 noundef signext %23) + %25 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo5flushEv(ptr noundef nonnull align 8 dereferenceable(8) %24) + %26 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo9_M_insertIbEERSoT_(ptr noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i1 noundef zeroext false) + %27 = load ptr, ptr %26, align 8, !tbaa !5 + %28 = getelementptr i8, ptr %27, i64 -24 + %29 = load i64, ptr %28, align 8 + %30 = getelementptr inbounds i8, ptr %26, i64 %29 + %31 = getelementptr inbounds %"class.std::basic_ios", ptr %30, i64 0, i32 5 + %32 = load ptr, ptr %31, align 8, !tbaa !8 + %33 = icmp eq ptr %32, null + br i1 %33, label %34, label %35 + + 34: ; preds = %22 + tail call void @_ZSt16__throw_bad_castv() #4 + unreachable + + 35: ; preds = %22 + %36 = getelementptr inbounds %"class.std::ctype", ptr %32, i64 0, i32 8 + %37 = load i8, ptr %36, align 8, !tbaa !20 + %38 = icmp eq i8 %37, 0 + br i1 %38, label %42, label %39 + + 39: ; preds = %35 + %40 = getelementptr inbounds %"class.std::ctype", ptr %32, i64 0, i32 9, i64 10 + %41 = load i8, ptr %40, align 1, !tbaa !23 + br label %47 + + 42: ; preds = %35 + tail call void @_ZNKSt5ctypeIcE13_M_widen_initEv(ptr noundef nonnull align 8 dereferenceable(570) %32) + %43 = load ptr, ptr %32, align 8, !tbaa !5 + %44 = getelementptr inbounds ptr, ptr %43, i64 6 + %45 = load ptr, ptr %44, align 8 + %46 = tail call noundef signext i8 %45(ptr noundef nonnull align 8 dereferenceable(570) %32, i8 noundef signext 10) + br label %47 + + 47: ; preds = %42, %39 + %48 = phi i8 [ %41, %39 ], [ %46, %42 ] + %49 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo3putEc(ptr noundef nonnull align 8 dereferenceable(8) %26, i8 noundef signext %48) + %50 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo5flushEv(ptr noundef nonnull align 8 dereferenceable(8) %49) + %51 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo9_M_insertIbEERSoT_(ptr noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i1 noundef zeroext true) + %52 = load ptr, ptr %51, align 8, !tbaa !5 + %53 = getelementptr i8, ptr %52, i64 -24 + %54 = load i64, ptr %53, align 8 + %55 = getelementptr inbounds i8, ptr %51, i64 %54 + %56 = getelementptr inbounds %"class.std::basic_ios", ptr %55, i64 0, i32 5 + %57 = load ptr, ptr %56, align 8, !tbaa !8 + %58 = icmp eq ptr %57, null + br i1 %58, label %59, label %60 + + 59: ; preds = %47 + tail call void @_ZSt16__throw_bad_castv() #4 + unreachable + + 60: ; preds = %47 + %61 = getelementptr inbounds %"class.std::ctype", ptr %57, i64 0, i32 8 + %62 = load i8, ptr %61, align 8, !tbaa !20 + %63 = icmp eq i8 %62, 0 + br i1 %63, label %67, label %64 + + 64: ; preds = %60 + %65 = getelementptr inbounds %"class.std::ctype", ptr %57, i64 0, i32 9, i64 10 + %66 = load i8, ptr %65, align 1, !tbaa !23 + br label %72 + + 67: ; preds = %60 + tail call void @_ZNKSt5ctypeIcE13_M_widen_initEv(ptr noundef nonnull align 8 dereferenceable(570) %57) + %68 = load ptr, ptr %57, align 8, !tbaa !5 + %69 = getelementptr inbounds ptr, ptr %68, i64 6 + %70 = load ptr, ptr %69, align 8 + %71 = tail call noundef signext i8 %70(ptr noundef nonnull align 8 dereferenceable(570) %57, i8 noundef signext 10) + br label %72 + + 72: ; preds = %67, %64 + %73 = phi i8 [ %66, %64 ], [ %71, %67 ] + %74 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo3putEc(ptr noundef nonnull align 8 dereferenceable(8) %51, i8 noundef signext %73) + %75 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo5flushEv(ptr noundef nonnull align 8 dereferenceable(8) %74) + %76 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo9_M_insertIbEERSoT_(ptr noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i1 noundef zeroext true) + %77 = load ptr, ptr %76, align 8, !tbaa !5 + %78 = getelementptr i8, ptr %77, i64 -24 + %79 = load i64, ptr %78, align 8 + %80 = getelementptr inbounds i8, ptr %76, i64 %79 + %81 = getelementptr inbounds %"class.std::basic_ios", ptr %80, i64 0, i32 5 + %82 = load ptr, ptr %81, align 8, !tbaa !8 + %83 = icmp eq ptr %82, null + br i1 %83, label %84, label %85 + + 84: ; preds = %72 + tail call void @_ZSt16__throw_bad_castv() #4 + unreachable + + 85: ; preds = %72 + %86 = getelementptr inbounds %"class.std::ctype", ptr %82, i64 0, i32 8 + %87 = load i8, ptr %86, align 8, !tbaa !20 + %88 = icmp eq i8 %87, 0 + br i1 %88, label %92, label %89 + + 89: ; preds = %85 + %90 = getelementptr inbounds %"class.std::ctype", ptr %82, i64 0, i32 9, i64 10 + %91 = load i8, ptr %90, align 1, !tbaa !23 + br label %97 + + 92: ; preds = %85 + tail call void @_ZNKSt5ctypeIcE13_M_widen_initEv(ptr noundef nonnull align 8 dereferenceable(570) %82) + %93 = load ptr, ptr %82, align 8, !tbaa !5 + %94 = getelementptr inbounds ptr, ptr %93, i64 6 + %95 = load ptr, ptr %94, align 8 + %96 = tail call noundef signext i8 %95(ptr noundef nonnull align 8 dereferenceable(570) %82, i8 noundef signext 10) + br label %97 + + 97: ; preds = %92, %89 + %98 = phi i8 [ %91, %89 ], [ %96, %92 ] + %99 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo3putEc(ptr noundef nonnull align 8 dereferenceable(8) %76, i8 noundef signext %98) + %100 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo5flushEv(ptr noundef nonnull align 8 dereferenceable(8) %99) + %101 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo9_M_insertIbEERSoT_(ptr noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i1 noundef zeroext false) + %102 = load ptr, ptr %101, align 8, !tbaa !5 + %103 = getelementptr i8, ptr %102, i64 -24 + %104 = load i64, ptr %103, align 8 + %105 = getelementptr inbounds i8, ptr %101, i64 %104 + %106 = getelementptr inbounds %"class.std::basic_ios", ptr %105, i64 0, i32 5 + %107 = load ptr, ptr %106, align 8, !tbaa !8 + %108 = icmp eq ptr %107, null + br i1 %108, label %109, label %110 + + 109: ; preds = %97 + tail call void @_ZSt16__throw_bad_castv() #4 + unreachable + + 110: ; preds = %97 + %111 = getelementptr inbounds %"class.std::ctype", ptr %107, i64 0, i32 8 + %112 = load i8, ptr %111, align 8, !tbaa !20 + %113 = icmp eq i8 %112, 0 + br i1 %113, label %117, label %114 + + 114: ; preds = %110 + %115 = getelementptr inbounds %"class.std::ctype", ptr %107, i64 0, i32 9, i64 10 + %116 = load i8, ptr %115, align 1, !tbaa !23 + br label %122 + + 117: ; preds = %110 + tail call void @_ZNKSt5ctypeIcE13_M_widen_initEv(ptr noundef nonnull align 8 dereferenceable(570) %107) + %118 = load ptr, ptr %107, align 8, !tbaa !5 + %119 = getelementptr inbounds ptr, ptr %118, i64 6 + %120 = load ptr, ptr %119, align 8 + %121 = tail call noundef signext i8 %120(ptr noundef nonnull align 8 dereferenceable(570) %107, i8 noundef signext 10) + br label %122 + + 122: ; preds = %117, %114 + %123 = phi i8 [ %116, %114 ], [ %121, %117 ] + %124 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo3putEc(ptr noundef nonnull align 8 dereferenceable(8) %101, i8 noundef signext %123) + %125 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo5flushEv(ptr noundef nonnull align 8 dereferenceable(8) %124) + %126 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo9_M_insertIbEERSoT_(ptr noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i1 noundef zeroext false) + %127 = load ptr, ptr %126, align 8, !tbaa !5 + %128 = getelementptr i8, ptr %127, i64 -24 + %129 = load i64, ptr %128, align 8 + %130 = getelementptr inbounds i8, ptr %126, i64 %129 + %131 = getelementptr inbounds %"class.std::basic_ios", ptr %130, i64 0, i32 5 + %132 = load ptr, ptr %131, align 8, !tbaa !8 + %133 = icmp eq ptr %132, null + br i1 %133, label %134, label %135 + + 134: ; preds = %122 + tail call void @_ZSt16__throw_bad_castv() #4 + unreachable + + 135: ; preds = %122 + %136 = getelementptr inbounds %"class.std::ctype", ptr %132, i64 0, i32 8 + %137 = load i8, ptr %136, align 8, !tbaa !20 + %138 = icmp eq i8 %137, 0 + br i1 %138, label %142, label %139 + + 139: ; preds = %135 + %140 = getelementptr inbounds %"class.std::ctype", ptr %132, i64 0, i32 9, i64 10 + %141 = load i8, ptr %140, align 1, !tbaa !23 + br label %147 + + 142: ; preds = %135 + tail call void @_ZNKSt5ctypeIcE13_M_widen_initEv(ptr noundef nonnull align 8 dereferenceable(570) %132) + %143 = load ptr, ptr %132, align 8, !tbaa !5 + %144 = getelementptr inbounds ptr, ptr %143, i64 6 + %145 = load ptr, ptr %144, align 8 + %146 = tail call noundef signext i8 %145(ptr noundef nonnull align 8 dereferenceable(570) %132, i8 noundef signext 10) + br label %147 + + 147: ; preds = %142, %139 + %148 = phi i8 [ %141, %139 ], [ %146, %142 ] + %149 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo3putEc(ptr noundef nonnull align 8 dereferenceable(8) %126, i8 noundef signext %148) + %150 = tail call noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo5flushEv(ptr noundef nonnull align 8 dereferenceable(8) %149) + ret i32 0 + } + + declare noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo9_M_insertIbEERSoT_(ptr noundef nonnull align 8 dereferenceable(8), i1 noundef zeroext) local_unnamed_addr #2 + + declare noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo3putEc(ptr noundef nonnull align 8 dereferenceable(8), i8 noundef signext) local_unnamed_addr #2 + + declare noundef nonnull align 8 dereferenceable(8) ptr @_ZNSo5flushEv(ptr noundef nonnull align 8 dereferenceable(8)) local_unnamed_addr #2 + + ; Function Attrs: noreturn + declare void @_ZSt16__throw_bad_castv() local_unnamed_addr #3 + + declare void @_ZNKSt5ctypeIcE13_M_widen_initEv(ptr noundef nonnull align 8 dereferenceable(570)) local_unnamed_addr #2 + + attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + attributes #1 = { mustprogress norecurse uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + attributes #3 = { noreturn "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + attributes #4 = { noreturn } + + !llvm.module.flags = !{!0, !1, !2, !3} + !llvm.ident = !{!4} + + !0 = !{i32 1, !"wchar_size", i32 4} + !1 = !{i32 8, !"PIC Level", i32 2} + !2 = !{i32 7, !"PIE Level", i32 2} + !3 = !{i32 7, !"uwtable", i32 2} + !4 = !{!"Ubuntu clang version 18.1.3 (1ubuntu1)"} + !5 = !{!6, !6, i64 0} + !6 = !{!"vtable pointer", !7, i64 0} + !7 = !{!"Simple C++ TBAA"} + !8 = !{!9, !15, i64 240} + !9 = !{!"_ZTSSt9basic_iosIcSt11char_traitsIcEE", !10, i64 0, !15, i64 216, !12, i64 224, !19, i64 225, !15, i64 232, !15, i64 240, !15, i64 248, !15, i64 256} + !10 = !{!"_ZTSSt8ios_base", !11, i64 8, !11, i64 16, !13, i64 24, !14, i64 28, !14, i64 32, !15, i64 40, !16, i64 48, !12, i64 64, !17, i64 192, !15, i64 200, !18, i64 208} + !11 = !{!"long", !12, i64 0} + !12 = !{!"omnipotent char", !7, i64 0} + !13 = !{!"_ZTSSt13_Ios_Fmtflags", !12, i64 0} + !14 = !{!"_ZTSSt12_Ios_Iostate", !12, i64 0} + !15 = !{!"any pointer", !12, i64 0} + !16 = !{!"_ZTSNSt8ios_base6_WordsE", !15, i64 0, !11, i64 8} + !17 = !{!"int", !12, i64 0} + !18 = !{!"_ZTSSt6locale", !15, i64 0} + !19 = !{!"bool", !12, i64 0} + !20 = !{!21, !12, i64 56} + !21 = !{!"_ZTSSt5ctypeIcE", !22, i64 0, !15, i64 16, !19, i64 24, !15, i64 32, !15, i64 40, !15, i64 48, !12, i64 56, !12, i64 57, !12, i64 313, !12, i64 569} + !22 = !{!"_ZTSNSt6locale5facetE", !17, i64 8} + !23 = !{!12, !12, i64 0} + +... +--- +name: _Z11and_or_testiii +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: true +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: gr32, preferred-register: '' } + - { id: 1, class: gr32, preferred-register: '' } + - { id: 2, class: gr32, preferred-register: '' } + - { id: 3, class: gr8, preferred-register: '' } + - { id: 4, class: gr32, preferred-register: '' } + - { id: 5, class: gr32, preferred-register: '' } + - { id: 6, class: gr8, preferred-register: '' } +liveins: + - { reg: '$edi', virtual-reg: '%0' } + - { reg: '$esi', virtual-reg: '%1' } + - { reg: '$edx', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + amxProgModel: None +body: | + bb.0 (%ir-block.3): + liveins: $edi, $esi, $edx + + ; CHECK: %2:gr32 = COPY $edx + ; CHECK-NEXT: %1:gr32 = COPY $esi + ; CHECK-NEXT: %0:gr32 = COPY $edi + ; CHECK-NEXT: TEST32rr %1, %0, implicit-def $eflags + ; CHECK-NEXT: %3:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: %4:gr32 = MOVZX32rr8 killed %3 + ; CHECK-NEXT: %5:gr32 = OR32rr %4, %2, implicit-def $eflags + ; CHECK-NEXT: %6:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: $al = COPY %6 + ; CHECK-NEXT: RET 0, $al + + %2:gr32 = COPY $edx + %1:gr32 = COPY $esi + %0:gr32 = COPY $edi + TEST32rr %1, %0, implicit-def $eflags + %3:gr8 = SETCCr 5, implicit $eflags + %4:gr32 = MOVZX32rr8 killed %3 + %5:gr32 = OR32rr %4, %2, implicit-def $eflags + %6:gr8 = SETCCr 5, implicit $eflags + $al = COPY %6 + RET 0, $al + +... +--- +name: _Z11or_xor_testiii +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: true +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: gr32, preferred-register: '' } + - { id: 1, class: gr32, preferred-register: '' } + - { id: 2, class: gr32, preferred-register: '' } + - { id: 3, class: gr32, preferred-register: '' } + - { id: 4, class: gr8, preferred-register: '' } + - { id: 5, class: gr32, preferred-register: '' } + - { id: 6, class: gr32, preferred-register: '' } + - { id: 7, class: gr8, preferred-register: '' } +liveins: + - { reg: '$edi', virtual-reg: '%0' } + - { reg: '$esi', virtual-reg: '%1' } + - { reg: '$edx', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + amxProgModel: None +body: | + bb.0 (%ir-block.3): + liveins: $edi, $esi, $edx + + ; CHECK: %2:gr32 = COPY $edx + ; CHECK-NEXT: %1:gr32 = COPY $esi + ; CHECK-NEXT: %0:gr32 = COPY $edi + ; CHECK-NEXT: %3:gr32 = OR32rr %1, %0, implicit-def $eflags + ; CHECK-NEXT: %4:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: %5:gr32 = MOVZX32rr8 killed %4 + ; CHECK-NEXT: %6:gr32 = SUB32rr %5, %2, implicit-def $eflags + ; CHECK-NEXT: %7:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: $al = COPY %7 + ; CHECK-NEXT: RET 0, $al + + %2:gr32 = COPY $edx + %1:gr32 = COPY $esi + %0:gr32 = COPY $edi + %3:gr32 = OR32rr %1, %0, implicit-def $eflags + %4:gr8 = SETCCr 5, implicit $eflags + %5:gr32 = MOVZX32rr8 killed %4 + %6:gr32 = SUB32rr %5, %2, implicit-def $eflags + %7:gr8 = SETCCr 5, implicit $eflags + $al = COPY %7 + RET 0, $al + +... +--- +name: _Z12and_xor_testiii +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: true +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: gr32, preferred-register: '' } + - { id: 1, class: gr32, preferred-register: '' } + - { id: 2, class: gr32, preferred-register: '' } + - { id: 3, class: gr8, preferred-register: '' } + - { id: 4, class: gr32, preferred-register: '' } + - { id: 5, class: gr32, preferred-register: '' } + - { id: 6, class: gr8, preferred-register: '' } +liveins: + - { reg: '$edi', virtual-reg: '%0' } + - { reg: '$esi', virtual-reg: '%1' } + - { reg: '$edx', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + amxProgModel: None +body: | + bb.0 (%ir-block.3): + liveins: $edi, $esi, $edx + + ; CHECK: %2:gr32 = COPY $edx + ; CHECK-NEXT: %1:gr32 = COPY $esi + ; CHECK-NEXT: %0:gr32 = COPY $edi + ; CHECK-NEXT: TEST32rr %1, %0, implicit-def $eflags + ; CHECK-NEXT: %3:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: %4:gr32 = MOVZX32rr8 killed %3 + ; CHECK-NEXT: %5:gr32 = SUB32rr %4, %2, implicit-def $eflags + ; CHECK-NEXT: %6:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: $al = COPY %6 + ; CHECK-NEXT: RET 0, $al + + %2:gr32 = COPY $edx + %1:gr32 = COPY $esi + %0:gr32 = COPY $edi + TEST32rr %1, %0, implicit-def $eflags + %3:gr8 = SETCCr 5, implicit $eflags + %4:gr32 = MOVZX32rr8 killed %3 + %5:gr32 = SUB32rr %4, %2, implicit-def $eflags + %6:gr8 = SETCCr 5, implicit $eflags + $al = COPY %6 + RET 0, $al + +... +--- +name: _Z15and_or_xor_testiiii +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: true +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: gr32, preferred-register: '' } + - { id: 1, class: gr32, preferred-register: '' } + - { id: 2, class: gr32, preferred-register: '' } + - { id: 3, class: gr32, preferred-register: '' } + - { id: 4, class: gr8, preferred-register: '' } + - { id: 5, class: gr32, preferred-register: '' } + - { id: 6, class: gr32, preferred-register: '' } + - { id: 7, class: gr8, preferred-register: '' } + - { id: 8, class: gr32, preferred-register: '' } + - { id: 9, class: gr32, preferred-register: '' } + - { id: 10, class: gr8, preferred-register: '' } +liveins: + - { reg: '$edi', virtual-reg: '%0' } + - { reg: '$esi', virtual-reg: '%1' } + - { reg: '$edx', virtual-reg: '%2' } + - { reg: '$ecx', virtual-reg: '%3' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + amxProgModel: None +body: | + bb.0 (%ir-block.4): + liveins: $edi, $esi, $edx, $ecx + + ; CHECK: %3:gr32 = COPY $ecx + ; CHECK-NEXT: %2:gr32 = COPY $edx + ; CHECK-NEXT: %1:gr32 = COPY $esi + ; CHECK-NEXT: %0:gr32 = COPY $edi + ; CHECK-NEXT: TEST32rr %1, %0, implicit-def $eflags + ; CHECK-NEXT: %4:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: %5:gr32 = MOVZX32rr8 killed %4 + ; CHECK-NEXT: %6:gr32 = OR32rr %5, %2, implicit-def $eflags + ; CHECK-NEXT: %7:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: %8:gr32 = MOVZX32rr8 killed %7 + ; CHECK-NEXT: %9:gr32 = SUB32rr %8, %3, implicit-def $eflags + ; CHECK-NEXT: %10:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: $al = COPY %10 + ; CHECK-NEXT: RET 0, $al + + %3:gr32 = COPY $ecx + %2:gr32 = COPY $edx + %1:gr32 = COPY $esi + %0:gr32 = COPY $edi + TEST32rr %1, %0, implicit-def $eflags + %4:gr8 = SETCCr 5, implicit $eflags + %5:gr32 = MOVZX32rr8 killed %4 + %6:gr32 = OR32rr %5, %2, implicit-def $eflags + %7:gr8 = SETCCr 5, implicit $eflags + %8:gr32 = MOVZX32rr8 killed %7 + %9:gr32 = SUB32rr %8, %3, implicit-def $eflags + %10:gr8 = SETCCr 5, implicit $eflags + $al = COPY %10 + RET 0, $al + +... +--- +name: _Z12and_and_testiii +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: true +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: gr32, preferred-register: '' } + - { id: 1, class: gr32, preferred-register: '' } + - { id: 2, class: gr32, preferred-register: '' } + - { id: 3, class: gr8, preferred-register: '' } + - { id: 4, class: gr8, preferred-register: '' } + - { id: 5, class: gr8, preferred-register: '' } +liveins: + - { reg: '$edi', virtual-reg: '%0' } + - { reg: '$esi', virtual-reg: '%1' } + - { reg: '$edx', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + amxProgModel: None +body: | + bb.0 (%ir-block.3): + liveins: $edi, $esi, $edx + + ; CHECK: %2:gr32 = COPY $edx + ; CHECK-NEXT: %1:gr32 = COPY $esi + ; CHECK-NEXT: %0:gr32 = COPY $edi + ; CHECK-NEXT: TEST32rr %1, %0, implicit-def $eflags + ; CHECK-NEXT: %3:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: %4:gr8 = COPY %2.sub_8bit + ; CHECK-NEXT: %5:gr8 = AND8rr %3, killed %4, implicit-def dead $eflags + ; CHECK-NEXT: $al = COPY %5 + ; CHECK-NEXT: RET 0, $al + + %2:gr32 = COPY $edx + %1:gr32 = COPY $esi + %0:gr32 = COPY $edi + TEST32rr %1, %0, implicit-def $eflags + %3:gr8 = SETCCr 5, implicit $eflags + %4:gr8 = COPY %2.sub_8bit + %5:gr8 = AND8rr %3, killed %4, implicit-def dead $eflags + $al = COPY %5 + RET 0, $al + +... +--- +name: _Z12xor_xor_testiii +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: true +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: gr32, preferred-register: '' } + - { id: 1, class: gr32, preferred-register: '' } + - { id: 2, class: gr32, preferred-register: '' } + - { id: 3, class: gr32, preferred-register: '' } + - { id: 4, class: gr8, preferred-register: '' } + - { id: 5, class: gr32, preferred-register: '' } + - { id: 6, class: gr32, preferred-register: '' } + - { id: 7, class: gr8, preferred-register: '' } +liveins: + - { reg: '$edi', virtual-reg: '%0' } + - { reg: '$esi', virtual-reg: '%1' } + - { reg: '$edx', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + amxProgModel: None +body: | + bb.0 (%ir-block.3): + liveins: $edi, $esi, $edx + + ; CHECK: %2:gr32 = COPY $edx + ; CHECK-NEXT: %1:gr32 = COPY $esi + ; CHECK-NEXT: %0:gr32 = COPY $edi + ; CHECK-NEXT: %3:gr32 = SUB32rr %0, %1, implicit-def $eflags + ; CHECK-NEXT: %4:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: %5:gr32 = MOVZX32rr8 killed %4 + ; CHECK-NEXT: %6:gr32 = SUB32rr %5, %2, implicit-def $eflags + ; CHECK-NEXT: %7:gr8 = SETCCr 5, implicit $eflags + ; CHECK-NEXT: $al = COPY %7 + ; CHECK-NEXT: RET 0, $al + + %2:gr32 = COPY $edx + %1:gr32 = COPY $esi + %0:gr32 = COPY $edi + %3:gr32 = SUB32rr %0, %1, implicit-def $eflags + %4:gr8 = SETCCr 5, implicit $eflags + %5:gr32 = MOVZX32rr8 killed %4 + %6:gr32 = SUB32rr %5, %2, implicit-def $eflags + %7:gr8 = SETCCr 5, implicit $eflags + $al = COPY %7 + RET 0, $al + +... +--- +name: main +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: true +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: gr64, preferred-register: '' } + - { id: 2, class: gr8, preferred-register: '' } + - { id: 3, class: gr8, preferred-register: '' } + - { id: 4, class: gr8, preferred-register: '' } + - { id: 5, class: gr64, preferred-register: '' } + - { id: 6, class: gr64, preferred-register: '' } + - { id: 7, class: gr8, preferred-register: '' } + - { id: 8, class: gr8, preferred-register: '' } + - { id: 9, class: gr8, preferred-register: '' } + - { id: 10, class: gr64, preferred-register: '' } + - { id: 11, class: gr64, preferred-register: '' } + - { id: 12, class: gr8, preferred-register: '' } + - { id: 13, class: gr8, preferred-register: '' } + - { id: 14, class: gr8, preferred-register: '' } + - { id: 15, class: gr64, preferred-register: '' } + - { id: 16, class: gr64, preferred-register: '' } + - { id: 17, class: gr8, preferred-register: '' } + - { id: 18, class: gr8, preferred-register: '' } + - { id: 19, class: gr8, preferred-register: '' } + - { id: 20, class: gr64, preferred-register: '' } + - { id: 21, class: gr64, preferred-register: '' } + - { id: 22, class: gr8, preferred-register: '' } + - { id: 23, class: gr8, preferred-register: '' } + - { id: 24, class: gr8, preferred-register: '' } + - { id: 25, class: gr64, preferred-register: '' } + - { id: 26, class: gr64, preferred-register: '' } + - { id: 27, class: gr8, preferred-register: '' } + - { id: 28, class: gr8, preferred-register: '' } + - { id: 29, class: gr8, preferred-register: '' } + - { id: 30, class: gr64, preferred-register: '' } + - { id: 31, class: gr32, preferred-register: '' } + - { id: 32, class: gr64, preferred-register: '' } + - { id: 33, class: gr64, preferred-register: '' } + - { id: 34, class: gr64_nosp, preferred-register: '' } + - { id: 35, class: gr64, preferred-register: '' } + - { id: 36, class: gr32, preferred-register: '' } + - { id: 37, class: gr8, preferred-register: '' } + - { id: 38, class: gr32, preferred-register: '' } + - { id: 39, class: gr64, preferred-register: '' } + - { id: 40, class: gr64, preferred-register: '' } + - { id: 41, class: gr64, preferred-register: '' } + - { id: 42, class: gr32, preferred-register: '' } + - { id: 43, class: gr64, preferred-register: '' } + - { id: 44, class: gr64, preferred-register: '' } + - { id: 45, class: gr64_nosp, preferred-register: '' } + - { id: 46, class: gr64, preferred-register: '' } + - { id: 47, class: gr32, preferred-register: '' } + - { id: 48, class: gr8, preferred-register: '' } + - { id: 49, class: gr32, preferred-register: '' } + - { id: 50, class: gr64, preferred-register: '' } + - { id: 51, class: gr64, preferred-register: '' } + - { id: 52, class: gr64, preferred-register: '' } + - { id: 53, class: gr32, preferred-register: '' } + - { id: 54, class: gr64, preferred-register: '' } + - { id: 55, class: gr64, preferred-register: '' } + - { id: 56, class: gr64_nosp, preferred-register: '' } + - { id: 57, class: gr64, preferred-register: '' } + - { id: 58, class: gr32, preferred-register: '' } + - { id: 59, class: gr8, preferred-register: '' } + - { id: 60, class: gr32, preferred-register: '' } + - { id: 61, class: gr64, preferred-register: '' } + - { id: 62, class: gr64, preferred-register: '' } + - { id: 63, class: gr64, preferred-register: '' } + - { id: 64, class: gr32, preferred-register: '' } + - { id: 65, class: gr64, preferred-register: '' } + - { id: 66, class: gr64, preferred-register: '' } + - { id: 67, class: gr64_nosp, preferred-register: '' } + - { id: 68, class: gr64, preferred-register: '' } + - { id: 69, class: gr32, preferred-register: '' } + - { id: 70, class: gr8, preferred-register: '' } + - { id: 71, class: gr32, preferred-register: '' } + - { id: 72, class: gr64, preferred-register: '' } + - { id: 73, class: gr64, preferred-register: '' } + - { id: 74, class: gr64, preferred-register: '' } + - { id: 75, class: gr32, preferred-register: '' } + - { id: 76, class: gr64, preferred-register: '' } + - { id: 77, class: gr64, preferred-register: '' } + - { id: 78, class: gr64_nosp, preferred-register: '' } + - { id: 79, class: gr64, preferred-register: '' } + - { id: 80, class: gr32, preferred-register: '' } + - { id: 81, class: gr8, preferred-register: '' } + - { id: 82, class: gr32, preferred-register: '' } + - { id: 83, class: gr64, preferred-register: '' } + - { id: 84, class: gr64, preferred-register: '' } + - { id: 85, class: gr64, preferred-register: '' } + - { id: 86, class: gr32, preferred-register: '' } + - { id: 87, class: gr64, preferred-register: '' } + - { id: 88, class: gr64, preferred-register: '' } + - { id: 89, class: gr64_nosp, preferred-register: '' } + - { id: 90, class: gr64, preferred-register: '' } + - { id: 91, class: gr32, preferred-register: '' } + - { id: 92, class: gr8, preferred-register: '' } + - { id: 93, class: gr32, preferred-register: '' } + - { id: 94, class: gr64, preferred-register: '' } + - { id: 95, class: gr64, preferred-register: '' } + - { id: 96, class: gr32, preferred-register: '' } +liveins: [] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: true + hasCalls: true + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + amxProgModel: None +body: | + bb.0 (%ir-block.0): + successors: %bb.1(0x00000800), %bb.2(0x7ffff800) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %30:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @_ZSt4cout, $noreg :: (load (s64) from got) + %31:gr32 = MOV32ri 1 + $rdi = COPY %30 + $esi = COPY %31 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo9_M_insertIbEERSoT_, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %32:gr64 = COPY $rax + %0:gr64 = COPY %32 + %33:gr64 = MOV64rm %32, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.1, !tbaa !5) + %34:gr64_nosp = MOV64rm killed %33, 1, $noreg, -24, $noreg :: (load (s64) from %ir.3) + %1:gr64 = MOV64rm %32, 1, killed %34, 240, $noreg :: (load (s64) from %ir.6, !tbaa !8) + TEST64rr %1, %1, implicit-def $eflags + JCC_1 %bb.2, 5, implicit $eflags + JMP_1 %bb.1 + + bb.1 (%ir-block.9): + successors: + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 target-flags(x86-plt) @_ZSt16__throw_bad_castv, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + bb.2 (%ir-block.10): + successors: %bb.4(0x30000000), %bb.3(0x50000000) + + CMP8mi %1, 1, $noreg, 56, $noreg, 0, implicit-def $eflags :: (load (s8) from %ir.11, align 8, !tbaa !20) + JCC_1 %bb.4, 4, implicit $eflags + JMP_1 %bb.3 + + bb.3 (%ir-block.14): + successors: %bb.5(0x80000000) + + %2:gr8 = MOV8rm %1, 1, $noreg, 67, $noreg :: (load (s8) from %ir.15, !tbaa !23) + JMP_1 %bb.5 + + bb.4 (%ir-block.17): + successors: %bb.5(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %1 + CALL64pcrel32 target-flags(x86-plt) @_ZNKSt5ctypeIcE13_M_widen_initEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %35:gr64 = MOV64rm %1, 1, $noreg, 0, $noreg :: (load (s64) from %ir.7, !tbaa !5) + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %36:gr32 = MOV32ri 10 + $rdi = COPY %1 + $esi = COPY %36 + CALL64m killed %35, 1, $noreg, 48, $noreg, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $al :: (load (s64) from %ir.19) + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %37:gr8 = COPY $al + %3:gr8 = COPY %37 + + bb.5 (%ir-block.22): + successors: %bb.6(0x00000800), %bb.7(0x7ffff800) + + %4:gr8 = PHI %2, %bb.3, %3, %bb.4 + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %38:gr32 = MOVSX32rr8 %4 + $rdi = COPY %0 + $esi = COPY %38 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo3putEc, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %39:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %39 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo5flushEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %40:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %41:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @_ZSt4cout, $noreg :: (load (s64) from got) + %42:gr32 = MOV32r0 implicit-def dead $eflags + $rdi = COPY %41 + $esi = COPY %42 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo9_M_insertIbEERSoT_, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %43:gr64 = COPY $rax + %5:gr64 = COPY %43 + %44:gr64 = MOV64rm %43, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.26, !tbaa !5) + %45:gr64_nosp = MOV64rm killed %44, 1, $noreg, -24, $noreg :: (load (s64) from %ir.28) + %6:gr64 = MOV64rm %43, 1, killed %45, 240, $noreg :: (load (s64) from %ir.31, !tbaa !8) + TEST64rr %6, %6, implicit-def $eflags + JCC_1 %bb.7, 5, implicit $eflags + JMP_1 %bb.6 + + bb.6 (%ir-block.34): + successors: + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 target-flags(x86-plt) @_ZSt16__throw_bad_castv, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + bb.7 (%ir-block.35): + successors: %bb.9(0x30000000), %bb.8(0x50000000) + + CMP8mi %6, 1, $noreg, 56, $noreg, 0, implicit-def $eflags :: (load (s8) from %ir.36, align 8, !tbaa !20) + JCC_1 %bb.9, 4, implicit $eflags + JMP_1 %bb.8 + + bb.8 (%ir-block.39): + successors: %bb.10(0x80000000) + + %7:gr8 = MOV8rm %6, 1, $noreg, 67, $noreg :: (load (s8) from %ir.40, !tbaa !23) + JMP_1 %bb.10 + + bb.9 (%ir-block.42): + successors: %bb.10(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %6 + CALL64pcrel32 target-flags(x86-plt) @_ZNKSt5ctypeIcE13_M_widen_initEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %46:gr64 = MOV64rm %6, 1, $noreg, 0, $noreg :: (load (s64) from %ir.32, !tbaa !5) + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %47:gr32 = MOV32ri 10 + $rdi = COPY %6 + $esi = COPY %47 + CALL64m killed %46, 1, $noreg, 48, $noreg, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $al :: (load (s64) from %ir.44) + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %48:gr8 = COPY $al + %8:gr8 = COPY %48 + + bb.10 (%ir-block.47): + successors: %bb.11(0x00000800), %bb.12(0x7ffff800) + + %9:gr8 = PHI %7, %bb.8, %8, %bb.9 + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %49:gr32 = MOVSX32rr8 %9 + $rdi = COPY %5 + $esi = COPY %49 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo3putEc, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %50:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %50 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo5flushEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %51:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %52:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @_ZSt4cout, $noreg :: (load (s64) from got) + %53:gr32 = MOV32ri 1 + $rdi = COPY %52 + $esi = COPY %53 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo9_M_insertIbEERSoT_, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %54:gr64 = COPY $rax + %10:gr64 = COPY %54 + %55:gr64 = MOV64rm %54, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.51, !tbaa !5) + %56:gr64_nosp = MOV64rm killed %55, 1, $noreg, -24, $noreg :: (load (s64) from %ir.53) + %11:gr64 = MOV64rm %54, 1, killed %56, 240, $noreg :: (load (s64) from %ir.56, !tbaa !8) + TEST64rr %11, %11, implicit-def $eflags + JCC_1 %bb.12, 5, implicit $eflags + JMP_1 %bb.11 + + bb.11 (%ir-block.59): + successors: + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 target-flags(x86-plt) @_ZSt16__throw_bad_castv, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + bb.12 (%ir-block.60): + successors: %bb.14(0x30000000), %bb.13(0x50000000) + + CMP8mi %11, 1, $noreg, 56, $noreg, 0, implicit-def $eflags :: (load (s8) from %ir.61, align 8, !tbaa !20) + JCC_1 %bb.14, 4, implicit $eflags + JMP_1 %bb.13 + + bb.13 (%ir-block.64): + successors: %bb.15(0x80000000) + + %12:gr8 = MOV8rm %11, 1, $noreg, 67, $noreg :: (load (s8) from %ir.65, !tbaa !23) + JMP_1 %bb.15 + + bb.14 (%ir-block.67): + successors: %bb.15(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %11 + CALL64pcrel32 target-flags(x86-plt) @_ZNKSt5ctypeIcE13_M_widen_initEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %57:gr64 = MOV64rm %11, 1, $noreg, 0, $noreg :: (load (s64) from %ir.57, !tbaa !5) + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %58:gr32 = MOV32ri 10 + $rdi = COPY %11 + $esi = COPY %58 + CALL64m killed %57, 1, $noreg, 48, $noreg, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $al :: (load (s64) from %ir.69) + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %59:gr8 = COPY $al + %13:gr8 = COPY %59 + + bb.15 (%ir-block.72): + successors: %bb.16(0x00000800), %bb.17(0x7ffff800) + + %14:gr8 = PHI %12, %bb.13, %13, %bb.14 + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %60:gr32 = MOVSX32rr8 %14 + $rdi = COPY %10 + $esi = COPY %60 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo3putEc, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %61:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %61 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo5flushEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %62:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %63:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @_ZSt4cout, $noreg :: (load (s64) from got) + %64:gr32 = MOV32ri 1 + $rdi = COPY %63 + $esi = COPY %64 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo9_M_insertIbEERSoT_, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %65:gr64 = COPY $rax + %15:gr64 = COPY %65 + %66:gr64 = MOV64rm %65, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.76, !tbaa !5) + %67:gr64_nosp = MOV64rm killed %66, 1, $noreg, -24, $noreg :: (load (s64) from %ir.78) + %16:gr64 = MOV64rm %65, 1, killed %67, 240, $noreg :: (load (s64) from %ir.81, !tbaa !8) + TEST64rr %16, %16, implicit-def $eflags + JCC_1 %bb.17, 5, implicit $eflags + JMP_1 %bb.16 + + bb.16 (%ir-block.84): + successors: + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 target-flags(x86-plt) @_ZSt16__throw_bad_castv, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + bb.17 (%ir-block.85): + successors: %bb.19(0x30000000), %bb.18(0x50000000) + + CMP8mi %16, 1, $noreg, 56, $noreg, 0, implicit-def $eflags :: (load (s8) from %ir.86, align 8, !tbaa !20) + JCC_1 %bb.19, 4, implicit $eflags + JMP_1 %bb.18 + + bb.18 (%ir-block.89): + successors: %bb.20(0x80000000) + + %17:gr8 = MOV8rm %16, 1, $noreg, 67, $noreg :: (load (s8) from %ir.90, !tbaa !23) + JMP_1 %bb.20 + + bb.19 (%ir-block.92): + successors: %bb.20(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %16 + CALL64pcrel32 target-flags(x86-plt) @_ZNKSt5ctypeIcE13_M_widen_initEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %68:gr64 = MOV64rm %16, 1, $noreg, 0, $noreg :: (load (s64) from %ir.82, !tbaa !5) + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %69:gr32 = MOV32ri 10 + $rdi = COPY %16 + $esi = COPY %69 + CALL64m killed %68, 1, $noreg, 48, $noreg, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $al :: (load (s64) from %ir.94) + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %70:gr8 = COPY $al + %18:gr8 = COPY %70 + + bb.20 (%ir-block.97): + successors: %bb.21(0x00000800), %bb.22(0x7ffff800) + + %19:gr8 = PHI %17, %bb.18, %18, %bb.19 + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %71:gr32 = MOVSX32rr8 %19 + $rdi = COPY %15 + $esi = COPY %71 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo3putEc, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %72:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %72 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo5flushEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %73:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %74:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @_ZSt4cout, $noreg :: (load (s64) from got) + %75:gr32 = MOV32r0 implicit-def dead $eflags + $rdi = COPY %74 + $esi = COPY %75 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo9_M_insertIbEERSoT_, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %76:gr64 = COPY $rax + %20:gr64 = COPY %76 + %77:gr64 = MOV64rm %76, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.101, !tbaa !5) + %78:gr64_nosp = MOV64rm killed %77, 1, $noreg, -24, $noreg :: (load (s64) from %ir.103) + %21:gr64 = MOV64rm %76, 1, killed %78, 240, $noreg :: (load (s64) from %ir.106, !tbaa !8) + TEST64rr %21, %21, implicit-def $eflags + JCC_1 %bb.22, 5, implicit $eflags + JMP_1 %bb.21 + + bb.21 (%ir-block.109): + successors: + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 target-flags(x86-plt) @_ZSt16__throw_bad_castv, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + bb.22 (%ir-block.110): + successors: %bb.24(0x30000000), %bb.23(0x50000000) + + CMP8mi %21, 1, $noreg, 56, $noreg, 0, implicit-def $eflags :: (load (s8) from %ir.111, align 8, !tbaa !20) + JCC_1 %bb.24, 4, implicit $eflags + JMP_1 %bb.23 + + bb.23 (%ir-block.114): + successors: %bb.25(0x80000000) + + %22:gr8 = MOV8rm %21, 1, $noreg, 67, $noreg :: (load (s8) from %ir.115, !tbaa !23) + JMP_1 %bb.25 + + bb.24 (%ir-block.117): + successors: %bb.25(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %21 + CALL64pcrel32 target-flags(x86-plt) @_ZNKSt5ctypeIcE13_M_widen_initEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %79:gr64 = MOV64rm %21, 1, $noreg, 0, $noreg :: (load (s64) from %ir.107, !tbaa !5) + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %80:gr32 = MOV32ri 10 + $rdi = COPY %21 + $esi = COPY %80 + CALL64m killed %79, 1, $noreg, 48, $noreg, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $al :: (load (s64) from %ir.119) + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %81:gr8 = COPY $al + %23:gr8 = COPY %81 + + bb.25 (%ir-block.122): + successors: %bb.26(0x00000800), %bb.27(0x7ffff800) + + %24:gr8 = PHI %22, %bb.23, %23, %bb.24 + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %82:gr32 = MOVSX32rr8 %24 + $rdi = COPY %20 + $esi = COPY %82 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo3putEc, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %83:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %83 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo5flushEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %84:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %85:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @_ZSt4cout, $noreg :: (load (s64) from got) + %86:gr32 = MOV32r0 implicit-def dead $eflags + $rdi = COPY %85 + $esi = COPY %86 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo9_M_insertIbEERSoT_, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %87:gr64 = COPY $rax + %25:gr64 = COPY %87 + %88:gr64 = MOV64rm %87, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.126, !tbaa !5) + %89:gr64_nosp = MOV64rm killed %88, 1, $noreg, -24, $noreg :: (load (s64) from %ir.128) + %26:gr64 = MOV64rm %87, 1, killed %89, 240, $noreg :: (load (s64) from %ir.131, !tbaa !8) + TEST64rr %26, %26, implicit-def $eflags + JCC_1 %bb.27, 5, implicit $eflags + JMP_1 %bb.26 + + bb.26 (%ir-block.134): + successors: + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 target-flags(x86-plt) @_ZSt16__throw_bad_castv, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + bb.27 (%ir-block.135): + successors: %bb.29(0x30000000), %bb.28(0x50000000) + + CMP8mi %26, 1, $noreg, 56, $noreg, 0, implicit-def $eflags :: (load (s8) from %ir.136, align 8, !tbaa !20) + JCC_1 %bb.29, 4, implicit $eflags + JMP_1 %bb.28 + + bb.28 (%ir-block.139): + successors: %bb.30(0x80000000) + + %27:gr8 = MOV8rm %26, 1, $noreg, 67, $noreg :: (load (s8) from %ir.140, !tbaa !23) + JMP_1 %bb.30 + + bb.29 (%ir-block.142): + successors: %bb.30(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %26 + CALL64pcrel32 target-flags(x86-plt) @_ZNKSt5ctypeIcE13_M_widen_initEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %90:gr64 = MOV64rm %26, 1, $noreg, 0, $noreg :: (load (s64) from %ir.132, !tbaa !5) + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %91:gr32 = MOV32ri 10 + $rdi = COPY %26 + $esi = COPY %91 + CALL64m killed %90, 1, $noreg, 48, $noreg, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $al :: (load (s64) from %ir.144) + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %92:gr8 = COPY $al + %28:gr8 = COPY %92 + + bb.30 (%ir-block.147): + %29:gr8 = PHI %27, %bb.28, %28, %bb.29 + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %93:gr32 = MOVSX32rr8 %29 + $rdi = COPY %25 + $esi = COPY %93 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo3putEc, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %94:gr64 = COPY $rax + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %94 + CALL64pcrel32 target-flags(x86-plt) @_ZNSo5flushEv, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %95:gr64 = COPY $rax + %96:gr32 = MOV32r0 implicit-def dead $eflags + $eax = COPY %96 + RET 0, $eax + +...