forked from NN-complr-tech/llvm-nnsu-2024
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'course-spring-2024' of https://github.com/KrYackI/llvm-…
…nnsu-2024 into course-spring-2024
- Loading branch information
Showing
45 changed files
with
2,966 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Oops, something went wrong.