Skip to content

Commit

Permalink
Merge branch 'course-spring-2024' of https://github.com/KrYackI/llvm-…
Browse files Browse the repository at this point in the history
…nnsu-2024 into course-spring-2024
  • Loading branch information
KrYackI committed May 21, 2024
2 parents 4320e44 + 2015cb5 commit c976621
Show file tree
Hide file tree
Showing 45 changed files with 2,966 additions and 0 deletions.
14 changes: 14 additions & 0 deletions clang/labs/lab1/lebedeva_ksenia/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
add_llvm_library(LebedevaRenamePlugin MODULE LebedevaRenameId.cpp PLUGIN_TOOL clang)

if(WIN32 OR CYGWIN)
set(LLVM_LINK_COMPONENTS
Support
)
clang_target_link_libraries(LebedevaRenamePlugin PRIVATE
clangAST
clangBasic
clangFrontend
)
endif()

set(CLANG_TEST_DEPS "LebedevaRenamePlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE)
123 changes: 123 additions & 0 deletions clang/labs/lab1/lebedeva_ksenia/LebedevaRenameId.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#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/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"

class RenameVisitor : public clang::RecursiveASTVisitor<RenameVisitor> {
private:
clang::Rewriter rewriter;
std::string oldName;
std::string newName;

public:
explicit RenameVisitor(clang::Rewriter rewriter, std::string oldName,
std::string newName)
: rewriter(rewriter), oldName(oldName), newName(newName){};

bool VisitFunctionDecl(clang::FunctionDecl *FuncDecl) {
std::string name = FuncDecl->getNameAsString();
if (name == oldName) {
rewriter.ReplaceText(FuncDecl->getNameInfo().getSourceRange(), newName);
rewriter.overwriteChangedFiles();
}
return true;
}

bool VisitDeclRefExpr(clang::DeclRefExpr *DRE) {
std::string name = DRE->getNameInfo().getAsString();
if (name == oldName) {
rewriter.ReplaceText(DRE->getNameInfo().getSourceRange(), newName);
rewriter.overwriteChangedFiles();
}
return true;
}

bool VisitVarDecl(clang::VarDecl *declVar) {
std::string name = declVar->getNameAsString();
if (name == oldName) {
rewriter.ReplaceText(declVar->getLocation(), name.size(), newName);
rewriter.overwriteChangedFiles();
}
if (declVar->getType().getAsString() == oldName + " *" ||
declVar->getType().getAsString() == oldName) {
rewriter.ReplaceText(
declVar->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), name.size(),
newName);
rewriter.overwriteChangedFiles();
}
return true;
}

bool VisitCXXRecordDecl(clang::CXXRecordDecl *CXXRDecl) {
std::string name = CXXRDecl->getNameAsString();
if (name == oldName) {
rewriter.ReplaceText(CXXRDecl->getLocation(), name.size(), newName);
const clang::CXXDestructorDecl *CXXDD = CXXRDecl->getDestructor();
if (CXXDD)
rewriter.ReplaceText(CXXDD->getLocation(), name.size() + 1,
"~" + newName);
rewriter.overwriteChangedFiles();
}
return true;
}

bool VisitCXXNewExpr(clang::CXXNewExpr *CXXNExpr) {
std::string name = CXXNExpr->getConstructExpr()->getType().getAsString();
if (name == oldName) {
rewriter.ReplaceText(CXXNExpr->getExprLoc(), name.size() + 4,
"new " + newName);
rewriter.overwriteChangedFiles();
}
return true;
}
};

class RenameIdConsumer : public clang::ASTConsumer {
RenameVisitor visitor;

public:
explicit RenameIdConsumer(clang::CompilerInstance &compInst,
std::string oldName, std::string newName)
: visitor(clang::Rewriter(compInst.getSourceManager(),
compInst.getLangOpts()),
oldName, newName) {}
void HandleTranslationUnit(clang::ASTContext &Context) override {
visitor.TraverseDecl(Context.getTranslationUnitDecl());
}
};

class RenameIdPlugin : public clang::PluginASTAction {
private:
std::string oldName;
std::string newName;

protected:
bool ParseArgs(const clang::CompilerInstance &Compiler,
const std::vector<std::string> &args) override {
oldName = args[0];
newName = args[1];
if (oldName.find("=") == 0 || oldName.find("=") == std::string::npos) {
llvm::errs() << "Error in the `oldName` parameter.\n";
}
if (newName.find("=") == 0 || newName.find("=") == std::string::npos) {
llvm::errs() << "Error in the `newName` parameter.\n";
}
oldName = oldName.substr(oldName.find("=") + 1);
newName = newName.substr(newName.find("=") + 1);
return true;
}

public:
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &Compiler,
llvm::StringRef InFile) override {
return std::make_unique<RenameIdConsumer>(Compiler, oldName, newName);
}
};

static clang::FrontendPluginRegistry::Add<RenameIdPlugin>
X("lebedeva-rename-plugin", "Renaming an identifier");
89 changes: 89 additions & 0 deletions clang/test/lab1/lebedeva_ksenia/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// RUN: split-file %s %t

// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="A" -plugin-arg-lebedeva-rename-plugin NewName="B" %t/test1.cpp
// RUN: FileCheck %s < %t/test1.cpp --check-prefix=FIRST-CHECK

// FIRST-CHECK: class B {
// FIRST-CHECK-NEXT: public:
// FIRST-CHECK-NEXT: B() {};
// FIRST-CHECK-NEXT: ~B();
// FIRST-CHECK-NEXT: };

//--- test1.cpp
class A {
public:
A() {};
~A();
};

// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="C" -plugin-arg-lebedeva-rename-plugin NewName="D" %t/test2.cpp
// RUN: FileCheck %s < %t/test2.cpp --check-prefix=SECOND-CHECK

// SECOND-CHECK: class D {
// SECOND-CHECK-NEXT: private:
// SECOND-CHECK-NEXT: int a;
// SECOND-CHECK-NEXT: public:
// SECOND-CHECK-NEXT: D() {}
// SECOND-CHECK-NEXT: D(int a): a(a) {}
// SECOND-CHECK-NEXT: ~D();
// SECOND-CHECK-NEXT: int getA() {
// SECOND-CHECK-NEXT: return a;
// SECOND-CHECK-NEXT: }
// SECOND-CHECK-NEXT: };
// SECOND-CHECK-NEXT: void func() {
// SECOND-CHECK-NEXT: D* c = new D();
// SECOND-CHECK-NEXT: delete c;
// SECOND-CHECK-NEXT: }

//--- test2.cpp
class C {
private:
int a;
public:
C() {}
C(int a): a(a) {}
~C();
int getA() {
return a;
}
};
void func() {
C* c = new C();
delete c;
}

// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="func1" -plugin-arg-lebedeva-rename-plugin NewName="newFunc" %t/test3.cpp
// RUN: FileCheck %s < %t/test3.cpp --check-prefix=THIRD-CHECK

// THIRD-CHECK: double newFunc(int a) {
// THIRD-CHECK-NEXT: int c = a + 10;
// THIRD-CHECK-NEXT: double d = c * 6;
// THIRD-CHECK-NEXT: return c + d;
// THIRD-CHECK-NEXT: };

//--- test3.cpp
double func1(int a) {
int c = a + 10;
double d = c * 6;
return c + d;
};

// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="notFunc" -plugin-arg-lebedeva-rename-plugin NewName="newFunc" %t/test4.cpp
// RUN: FileCheck %s < %t/test4.cpp --check-prefix=FOURTH-CHECK

// FOURTH-CHECK: int func2(int a, int b) {
// FOURTH-CHECK-NEXT: int c = a + 10;
// FOURTH-CHECK-NEXT: int d = c * 10;
// FOURTH-CHECK-NEXT: return c + d;
// FOURTH-CHECK-NEXT: };

//--- test4.cpp
int func2(int a, int b) {
int c = a + 10;
int d = c * 10;
return c + d;
};
11 changes: 11 additions & 0 deletions llvm/labs/lab2/borovkov_sergey/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (NOT WIN32 AND NOT CYGWIN)
set(PluginName MulShiftsBorovkovPlugin)

file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)
add_llvm_pass_plugin(${PluginName}
${ALL_SOURCE_FILES} DEPENDS
intrinsics_gen
BUILDTREE_ONLY )

set(LLVM_TEST_DEPENDS ${PluginName} ${LLVM_TEST_DEPENDS} PARENT_SCOPE)
endif()
114 changes: 114 additions & 0 deletions llvm/labs/lab2/borovkov_sergey/MulWithShift.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Pass.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include <optional>

namespace {
struct MulShifts : llvm::PassInfoMixin<MulShifts> {
public:
llvm::PreservedAnalyses run(llvm::Function &Func,
llvm::FunctionAnalysisManager &FAM) {
std::vector<llvm::Instruction *> toRemove;

for (llvm::BasicBlock &BB : Func) {
for (llvm::Instruction &Inst : BB) {
if (!llvm::BinaryOperator::classof(&Inst)) {
continue;
}
llvm::BinaryOperator *op = llvm::cast<llvm::BinaryOperator>(&Inst);
if (op->getOpcode() != llvm::Instruction::BinaryOps::Mul) {
continue;
}

llvm::Value *lhs = op->getOperand(0);
llvm::Value *rhs = op->getOperand(1);

auto lg1 = getLogBase2(lhs);
auto lg2 = getLogBase2(rhs);
if (!lg1 && !lg2) {
continue;
}
if (lg1 < lg2) {
std::swap(lg1, lg2);
std::swap(lhs, rhs);
}

if (lg1) {
llvm::Value *lg_val = llvm::ConstantInt::get(
llvm::IntegerType::get(Func.getContext(), 32),
llvm::APInt(32, *lg1));

llvm::Value *val = llvm::BinaryOperator::Create(
llvm::Instruction::Shl, rhs, lg_val, op->getName(), op);

op->replaceAllUsesWith(val);
toRemove.push_back(op);
}
}
for (auto *I : toRemove) {
I->eraseFromParent();
}
}

auto PA = llvm::PreservedAnalyses::all();
return PA;
}

private:
std::optional<int> getLogBase2(llvm::Value *val) {
if (llvm::ConstantInt *CI = llvm::dyn_cast<llvm::ConstantInt>(val)) {
if (CI->getValue().isPowerOf2()) {
return CI->getValue().exactLogBase2();
}
}
if (auto *LI = llvm::dyn_cast<llvm::LoadInst>(val)) {
llvm::Value *Op = LI->getPointerOperand();
Op->reverseUseList();
llvm::StoreInst *StInst = nullptr;
for (auto *Inst : Op->users()) {
if (auto *SI = llvm::dyn_cast<llvm::StoreInst>(Inst)) {
StInst = SI;
}
if (Inst == LI) {
break;
}
}
Op->reverseUseList();
if (!StInst) {
return std::nullopt;
}
if (auto *CI =
llvm::dyn_cast<llvm::ConstantInt>(StInst->getValueOperand())) {
if (CI->getValue().isPowerOf2()) {
return CI->getValue().exactLogBase2();
}
}
}
return std::nullopt;
}
};
} // namespace

bool registerPlugin(llvm::StringRef Name, llvm::FunctionPassManager &FPM,
llvm::ArrayRef<llvm::PassBuilder::PipelineElement>) {
if (Name == "borovkovmulshifts") {
FPM.addPass(MulShifts());
return true;
}
return false;
}

llvm::PassPluginLibraryInfo getMulShiftsBorovkovPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "MulShifts", LLVM_VERSION_STRING,
[](llvm::PassBuilder &PB) {
PB.registerPipelineParsingCallback(registerPlugin);
}};
}

extern "C" LLVM_ATTRIBUTE_WEAK llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return getMulShiftsBorovkovPluginInfo();
}
12 changes: 12 additions & 0 deletions llvm/labs/lab2/safarov_nurlan/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
if (NOT WIN32 AND NOT CYGWIN)
set(PluginName replaceMulWithBitShift)

file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)
add_llvm_pass_plugin(${PluginName}
${ALL_SOURCE_FILES}
DEPENDS
intrinsics_gen
BUILDTREE_ONLY)

set(LLVM_TEST_DEPENDS ${PluginName} ${LLVM_TEST_DEPENDS} PARENT_SCOPE)
endif()
Loading

0 comments on commit c976621

Please sign in to comment.