Skip to content
This repository has been archived by the owner on Jan 19, 2025. It is now read-only.

Kuznetsov Artyom lab2 (option 1) #54

2 changes: 2 additions & 0 deletions llvm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,8 @@ if( LLVM_INCLUDE_EXAMPLES )
add_subdirectory(examples)
endif()

add_subdirectory(labs)

if( LLVM_INCLUDE_TESTS )
if(EXISTS ${LLVM_MAIN_SRC_DIR}/projects/test-suite AND TARGET clang)
include(LLVMExternalProjectUtils)
Expand Down
8 changes: 8 additions & 0 deletions llvm/labs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FILE(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
FOREACH(child ${children})
IF(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child})
add_subdirectory(${child})
ENDIF()
ENDFOREACH()

set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} PARENT_SCOPE)
8 changes: 8 additions & 0 deletions llvm/labs/lab2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FILE(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
FOREACH(child ${children})
IF(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child})
add_subdirectory(${child})
ENDIF()
ENDFOREACH()

set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} PARENT_SCOPE)
17 changes: 17 additions & 0 deletions llvm/labs/lab2/kuznetsov_artyom/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
set(Title "Instrument_Functions")
set(Student "Kuznetsov_Artyom")
set(Group "FIIT3")
set(PluginName "${Title}_${Student}_${Group}")

# Result plugin name: Instrument_Functions_Kuznetsov_Artyom_FIIT3

if (NOT WIN32 AND NOT CYGWIN)
message("-- ${PluginName} -- BUILD")

file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.hpp)
add_llvm_pass_plugin(${PluginName} ${ALL_SOURCE_FILES})

set(LLVM_TEST_DEPENDS ${PluginName} ${LLVM_TEST_DEPENDS} PARENT_SCOPE)
else()
message("-- ${PluginName} -- NOT BUILD")
endif()
72 changes: 72 additions & 0 deletions llvm/labs/lab2/kuznetsov_artyom/instrumention_func.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Support/raw_ostream.h"

namespace {
struct InstrumentFunctions : llvm::PassInfoMixin<InstrumentFunctions> {
llvm::PreservedAnalyses run(llvm::Function &func,
llvm::FunctionAnalysisManager &) {
llvm::LLVMContext &context = func.getContext();
llvm::IRBuilder<> builder(context);
auto module = func.getParent();

llvm::FunctionType *funcType =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), false);
llvm::FunctionCallee instrStartFunc =
module->getOrInsertFunction("instrument_start", funcType);
llvm::FunctionCallee instEndFunc =
module->getOrInsertFunction("instrument_end", funcType);

bool startInserted = false;
bool endInserted = false;

for (auto &block : func) {
for (auto &instruction : block) {
if (llvm::isa<llvm::CallInst>(&instruction)) {
llvm::CallInst *callInst = llvm::cast<llvm::CallInst>(&instruction);
if (callInst->getCalledFunction() == instrStartFunc.getCallee()) {
startInserted = true;
} else if (callInst->getCalledFunction() == instEndFunc.getCallee()) {
endInserted = true;
}
}
}
}

if (!startInserted) {
builder.SetInsertPoint(&func.getEntryBlock().front());
builder.CreateCall(instrStartFunc);
}
if (!endInserted) {
for (auto &block : func) {
if (llvm::isa<llvm::ReturnInst>(block.getTerminator())) {
builder.SetInsertPoint(block.getTerminator());
builder.CreateCall(instEndFunc);
}
}
}

return llvm::PreservedAnalyses::all();
}

static bool isRequired() { return true; }
};
} // namespace

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "InstrumentFunctions", "0.1",
[](llvm::PassBuilder &PB) {
PB.registerPipelineParsingCallback(
[](llvm::StringRef name, llvm::FunctionPassManager &FPM,
llvm::ArrayRef<llvm::PassBuilder::PipelineElement>) -> bool {
if (name == "instr_func") {
FPM.addPass(InstrumentFunctions{});
return true;
}
return false;
});
}};
}
2 changes: 1 addition & 1 deletion llvm/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ configure_lit_site_cfg(

# Set the depends list as a variable so that it can grow conditionally.
# NOTE: Sync the substitutions in test/lit.cfg when adding to this list.
set(LLVM_TEST_DEPENDS
set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS}
BugpointPasses
FileCheck
LLVMHello
Expand Down
101 changes: 101 additions & 0 deletions llvm/test/lab2/kuznetsov_artyom/test.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
; RUN: opt -load-pass-plugin %llvmshlibdir/Instrument_Functions_Kuznetsov_Artyom_FIIT3%pluginext\
; RUN: -passes=instr_func -S %s | FileCheck %s

; CHECK-LABEL: @_Z9factoriali
; CHECK: call void @instrument_start()
; CHECL-NEXT: %value.addr = alloca i32, align 4
; CHECK: call void @instrument_end()
; CHECK-NEXT: ret i32 %cond

define dso_local noundef i32 @_Z9factoriali(i32 noundef %value) {
entry:
%value.addr = alloca i32, align 4
store i32 %value, ptr %value.addr, align 4
%0 = load i32, ptr %value.addr, align 4
%cmp = icmp sle i32 %0, 1
br i1 %cmp, label %cond.true, label %cond.false

cond.true:
br label %cond.end

cond.false:
%1 = load i32, ptr %value.addr, align 4
%2 = load i32, ptr %value.addr, align 4
%sub = sub nsw i32 %2, 1
%call = call noundef i32 @_Z9factoriali(i32 noundef %sub)
%mul = mul nsw i32 %1, %call
br label %cond.end

cond.end:
%cond = phi i32 [ 1, %cond.true ], [ %mul, %cond.false ]
ret i32 %cond
}

; CHECK-LABEL: @_Z4funcb
; CHECK: call void @instrument_start()
; CHECK-NEXT: %retval = alloca i32, align 4
; CHECK: call void @instrument_end()
; CHECK-NEXT: ret i32 %3

define dso_local noundef i32 @_Z4funcb(i1 noundef zeroext %pred) {
entry:
%retval = alloca i32, align 4
%pred.addr = alloca i8, align 1
%a = alloca i32, align 4
%b = alloca i32, align 4
%frombool = zext i1 %pred to i8
store i8 %frombool, ptr %pred.addr, align 1
%0 = load i8, ptr %pred.addr, align 1
%tobool = trunc i8 %0 to i1
br i1 %tobool, label %if.then, label %if.end

if.then:
store i32 10, ptr %a, align 4
store i32 20, ptr %b, align 4
%1 = load i32, ptr %a, align 4
%2 = load i32, ptr %b, align 4
%add = add nsw i32 %1, %2
store i32 %add, ptr %retval, align 4
br label %return

if.end:
store i32 0, ptr %retval, align 4
br label %return

return:
%3 = load i32, ptr %retval, align 4
ret i32 %3
}

; CHECK-LABEL: @_Z8voidFuncv
; CHECK: call void @instrument_start()
; CHECK-NEXT: call void @instrument_end()
; CHECK-NEXT: ret void

define dso_local void @_Z8voidFuncv() {
entry:
ret void
}

; CHECK-LABEL: @_Z3sumii
; CHECK: call void @instrument_start()
; CHECK-NEXT: %a.addr = alloca i32, align 4
; CHECK: call void @instrument_end()
; CHECK-NEXT: ret i32 %add

define dso_local noundef i32 @_Z3sumii(i32 noundef %a, i32 noundef %b) {
entry:
call void @instrument_start()
%a.addr = alloca i32, align 4
%b.addr = alloca i32, align 4
store i32 %a, ptr %a.addr, align 4
store i32 %b, ptr %b.addr, align 4
%0 = load i32, ptr %a.addr, align 4
%1 = load i32, ptr %b.addr, align 4
%add = add nsw i32 %0, %1
call void @instrument_end()
ret i32 %add
}

declare void @instrument_start()
declare void @instrument_end()
Loading