diff --git a/clambcc/clambc-compiler.py b/clambcc/clambc-compiler.py index fbc3128d35..4e7ee6b78d 100755 --- a/clambcc/clambc-compiler.py +++ b/clambcc/clambc-compiler.py @@ -661,7 +661,7 @@ def createInputSourceFile(clangLLVM: ClangLLVM, name: str, args: list, options: # , 'verify' , 'clambc-extend-phis-to-64-bit' , 'verify' - , 'clambc-convert-memsets-to-32Bit' + , 'clambc-convert-intrinsics-to-32Bit' , 'verify' , 'globalopt' , 'clambc-prepare-geps-for-writer' @@ -689,7 +689,7 @@ def createInputSourceFile(clangLLVM: ClangLLVM, name: str, args: list, options: , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcoutlineendiannesscalls.so" , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcchangemallocargsize.so" , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcextendphisto64bit.so" - , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcconvertmemsetsto32bit.so" + , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcconvertintrinsicsto32bit.so" , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcpreparegepsforwriter.so" , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcanalyzer.so" , f"--load-pass-plugin {SHARED_OBJ_DIR}/libclambcregalloc.so" diff --git a/libclambcc/CMakeLists.txt b/libclambcc/CMakeLists.txt index 6ce9fdd8aa..8070347b2d 100644 --- a/libclambcc/CMakeLists.txt +++ b/libclambcc/CMakeLists.txt @@ -18,7 +18,7 @@ add_subdirectory(ClamBCChangeMallocArgSize) add_subdirectory(ClamBCExtendPHIsTo64Bit) add_subdirectory(ClamBCRebuild) add_subdirectory(ClamBCRegAlloc) -add_subdirectory(ClamBCConvertMemsetsTo32Bit) +add_subdirectory(ClamBCConvertIntrinsicsTo32Bit) add_subdirectory(ClamBCPrepareGEPsForWriter) add_subdirectory(ClamBCRemoveICMPSLE) add_subdirectory(ClamBCRemoveUSUB) diff --git a/libclambcc/ClamBCConvertMemsetsTo32Bit/CMakeLists.txt b/libclambcc/ClamBCConvertIntrinsicsTo32Bit/CMakeLists.txt similarity index 54% rename from libclambcc/ClamBCConvertMemsetsTo32Bit/CMakeLists.txt rename to libclambcc/ClamBCConvertIntrinsicsTo32Bit/CMakeLists.txt index 49847ee586..c09d3bbbf5 100644 --- a/libclambcc/ClamBCConvertMemsetsTo32Bit/CMakeLists.txt +++ b/libclambcc/ClamBCConvertIntrinsicsTo32Bit/CMakeLists.txt @@ -1,15 +1,15 @@ # Copyright (C) 2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved. # -# The clambcconvertmemsetsto32bit object library +# The clambcconvertintrinsicsto32bit object library # -add_library(clambcconvertmemsetsto32bit_obj OBJECT) -target_sources(clambcconvertmemsetsto32bit_obj +add_library(clambcconvertintrinsicsto32bit_obj OBJECT) +target_sources(clambcconvertintrinsicsto32bit_obj PRIVATE - ClamBCConvertMemsetsTo32Bit.cpp + ClamBCConvertIntrinsicsTo32Bit.cpp ) -target_include_directories(clambcconvertmemsetsto32bit_obj +target_include_directories(clambcconvertintrinsicsto32bit_obj PRIVATE ${CMAKE_BINARY_DIR} # For clambc-version.h (generated file) . # For Common/clambc.h @@ -17,35 +17,35 @@ target_include_directories(clambcconvertmemsetsto32bit_obj ${LLVM_INCLUDE_DIRS} ) -set_target_properties(clambcconvertmemsetsto32bit_obj PROPERTIES COMPILE_FLAGS "${WARNCXXFLAGS}") +set_target_properties(clambcconvertintrinsicsto32bit_obj PROPERTIES COMPILE_FLAGS "${WARNCXXFLAGS}") # # For testing # -#target_compile_definitions(clambcconvertmemsetsto32bit_obj -DLOG_BEFORE_AFTER=1) +#target_compile_definitions(clambcconvertintrinsicsto32bit_obj -DLOG_BEFORE_AFTER=1) # -# The clambcconvertmemsetsto32bit shared library. +# The clambcconvertintrinsicsto32bit shared library. # -add_library( clambcconvertmemsetsto32bit SHARED ) -target_link_libraries( clambcconvertmemsetsto32bit +add_library( clambcconvertintrinsicsto32bit SHARED ) +target_link_libraries( clambcconvertintrinsicsto32bit PUBLIC - clambcconvertmemsetsto32bit_obj ) -set_target_properties( clambcconvertmemsetsto32bit PROPERTIES + clambcconvertintrinsicsto32bit_obj ) +set_target_properties( clambcconvertintrinsicsto32bit PROPERTIES VERSION ${LIBCLAMBC_VERSION} SOVERSION ${LIBCLAMBC_SOVERSION} ) -target_link_directories(clambcconvertmemsetsto32bit PRIVATE ${LLVM_LIBRARY_DIRS}) -target_link_libraries(clambcconvertmemsetsto32bit PUBLIC ${LLVM_LIBS}) +target_link_directories(clambcconvertintrinsicsto32bit PRIVATE ${LLVM_LIBRARY_DIRS}) +target_link_libraries(clambcconvertintrinsicsto32bit PUBLIC ${LLVM_LIBS}) if(WIN32) - install(TARGETS clambcconvertmemsetsto32bit DESTINATION .) + install(TARGETS clambcconvertintrinsicsto32bit DESTINATION .) # Also install shared library (DLL) dependencies install(CODE [[ file(GET_RUNTIME_DEPENDENCIES LIBRARIES - $ + $ RESOLVED_DEPENDENCIES_VAR _r_deps UNRESOLVED_DEPENDENCIES_VAR _u_deps DIRECTORIES @@ -65,7 +65,7 @@ if(WIN32) #message("UNRESOLVED_DEPENDENCIES_VAR: ${_u_deps}") ]]) else() - install(TARGETS clambcconvertmemsetsto32bit DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(TARGETS clambcconvertintrinsicsto32bit DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() diff --git a/libclambcc/ClamBCConvertIntrinsicsTo32Bit/ClamBCConvertIntrinsicsTo32Bit.cpp b/libclambcc/ClamBCConvertIntrinsicsTo32Bit/ClamBCConvertIntrinsicsTo32Bit.cpp new file mode 100644 index 0000000000..8e622d8ee7 --- /dev/null +++ b/libclambcc/ClamBCConvertIntrinsicsTo32Bit/ClamBCConvertIntrinsicsTo32Bit.cpp @@ -0,0 +1,219 @@ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "Common/clambc.h" + +#include + +using namespace llvm; + +namespace ClamBCConvertIntrinsicsTo32Bit { + +class ClamBCConvertIntrinsicsTo32Bit : public PassInfoMixin +{ + + public: + static char ID; + + ClamBCConvertIntrinsicsTo32Bit() {} + + virtual ~ClamBCConvertIntrinsicsTo32Bit() {} + + PreservedAnalyses run(Module & mod, ModuleAnalysisManager & MAM) + { + bChanged = false; + pMod = &mod; + + initializeReplacements(); + + for (auto i = pMod->begin(), e = pMod->end(); i != e; i++) { + Function* pFunc = llvm::cast(i); + processFunction(pFunc); + } + + for (size_t i = 0; i < delLst.size(); i++) { + delLst[i]->eraseFromParent(); + } + + if (bChanged){ + return PreservedAnalyses::none(); + } + + return PreservedAnalyses::all(); + } + + protected: + Module* pMod = nullptr; + bool bChanged = false; + std::vector delLst; + + typedef struct { + llvm::Function * oldFunc; + llvm::FunctionCallee newFunc; + const size_t paramIdx; + } Replacement; + std::vector< Replacement> replacements; + + llvm::FunctionType* getMemset32Type() + { + LLVMContext& c = pMod->getContext(); + return FunctionType::get(Type::getVoidTy(c), + {Type::getInt8PtrTy(c), Type::getInt8Ty(c), Type::getInt32Ty(c), Type::getInt1Ty(c)}, + false); + } + + llvm::FunctionType* getMemcpy32Type() + { + LLVMContext& c = pMod->getContext(); + return FunctionType::get(Type::getVoidTy(c), + {Type::getInt8PtrTy(c), Type::getInt8PtrTy(c), Type::getInt32Ty(c), Type::getInt1Ty(c)}, + false); + } + + llvm::FunctionType* getMemmove32Type() + { + LLVMContext& c = pMod->getContext(); + return FunctionType::get(Type::getVoidTy(c), + {Type::getInt8PtrTy(c), Type::getInt8PtrTy(c), Type::getInt32Ty(c), Type::getInt1Ty(c)}, + false); + } + + void initializeReplacements(){ + /*There are different calls when you use the -no-opaque flags.*/ + + /*memsets*/ + FunctionType * ft = getMemset32Type(); + Function * pFunc = pMod->getFunction( "llvm.memset.p0i8.i64"); + if (pFunc){ + FunctionCallee rep = pMod->getOrInsertFunction("llvm.memset.p0i8.i32", ft); + replacements.push_back( {pFunc, rep, 2} ); + } + pFunc = pMod->getFunction( "llvm.memset.p0.i64"); + if (pFunc){ + FunctionCallee rep = pMod->getOrInsertFunction("llvm.memset.p0.i32", ft); + replacements.push_back( {pFunc, rep, 2}); + } + + /*memcpys*/ + ft = getMemcpy32Type(); + pFunc = pMod->getFunction("llvm.memcpy.p0i8.p0i8.i64"); + if (pFunc){ + FunctionCallee rep = pMod->getOrInsertFunction("llvm.memcpy.p0i8.p0i8.i32", ft); + replacements.push_back( {pFunc, rep, 2}); + } + pFunc = pMod->getFunction("llvm.memcpy.p0.p0.i64"); + if (pFunc){ + FunctionCallee rep = pMod->getOrInsertFunction("llvm.memcpy.p0.p0.i32", ft); + replacements.push_back( {pFunc, rep, 2}); + } + + /*memmoves*/ + ft = getMemmove32Type(); + pFunc = pMod->getFunction("llvm.memmove.p0.p0.i64"); + if (pFunc){ + FunctionCallee rep = pMod->getOrInsertFunction("llvm.memmove.p0.p0.i32", ft); + replacements.push_back( {pFunc, rep, 2}); + } + pFunc = pMod->getFunction("llvm.memmove.p0i8.p0i8.i64"); + if (pFunc){ + FunctionCallee rep = pMod->getOrInsertFunction("llvm.memmove.p0i8.p0i8.i32", ft); + replacements.push_back( {pFunc, rep, 2}); + } + + } + + void processFunction(Function* pFunc) + { + for (auto i = pFunc->begin(), e = pFunc->end(); i != e; i++) { + BasicBlock* pBB = llvm::cast(i); + processBasicBlock(pBB); + } + } + + void processBasicBlock(BasicBlock* pBB) + { + for (auto i = pBB->begin(), e = pBB->end(); i != e; i++) { + if (CallInst* pci = llvm::dyn_cast(i)) { + Function * f = pci->getCalledFunction(); + if (nullptr != f) { + for (size_t i = 0; i < replacements.size(); i++){ + if (replacements[i].oldFunc == f) { + convertCall(pci, replacements[i]); + } + } + } + } + } + } + + void convertCall(CallInst* pci, const Replacement & r) + { + std::vector args; + Type* i32Ty = Type::getInt32Ty(pMod->getContext()); + + for (size_t i = 0; i < pci->arg_size(); i++) + { + Value* pv = pci->getArgOperand(i); + if (r.paramIdx == i) { + if (ConstantInt* ci = llvm::dyn_cast(pv)) { + pv = ConstantInt::get(i32Ty, ci->getValue().getLimitedValue()); + } else { + pv = CastInst::CreateTruncOrBitCast(pv, i32Ty, "ClamBCConvertIntrinsicsTo32Bit_trunc_", pci); + } + + pci->setArgOperand(i, pv); + } + +// args.push_back(pv); + } + + + //FunctionCallee f = pMod->getOrInsertFunction(newName, ); + pci->setCalledFunction(r.newFunc); + + +// CallInst * pNew = CallInst::Create(f, args, "", pci); +// pNew->setAttributes(pci->getAttributes()); + +// delLst.push_back(pci); + } + + +}; + +} // end of anonymous namespace + +// This part is the new way of registering your pass +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + return { + LLVM_PLUGIN_API_VERSION, "ClamBCConvertIntrinsicsTo32Bit", "v0.1", + [](PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &FPM, + ArrayRef) { + if(Name == "clambc-convert-intrinsics-to-32Bit"){ + FPM.addPass(ClamBCConvertIntrinsicsTo32Bit::ClamBCConvertIntrinsicsTo32Bit()); + return true; + } + return false; + } + ); + } + }; +} + + diff --git a/libclambcc/ClamBCConvertMemsetsTo32Bit/ClamBCConvertMemsetsTo32Bit.cpp b/libclambcc/ClamBCConvertMemsetsTo32Bit/ClamBCConvertMemsetsTo32Bit.cpp deleted file mode 100644 index a1d8eafaae..0000000000 --- a/libclambcc/ClamBCConvertMemsetsTo32Bit/ClamBCConvertMemsetsTo32Bit.cpp +++ /dev/null @@ -1,143 +0,0 @@ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "Common/clambc.h" - -#include - -using namespace llvm; - -namespace ClamBCConvertMemsetsTo32Bit { - -class ClamBCConvertMemsetsTo32Bit : public PassInfoMixin -{ - - public: - static char ID; - - ClamBCConvertMemsetsTo32Bit() {} - - virtual ~ClamBCConvertMemsetsTo32Bit() {} - - PreservedAnalyses run(Module & mod, ModuleAnalysisManager & MAM) - { - bChanged = false; - pMod = &mod; - - for (auto i = pMod->begin(), e = pMod->end(); i != e; i++) { - Function* pFunc = llvm::cast(i); - processFunction(pFunc); - } - - for (size_t i = 0; i < delLst.size(); i++) { - delLst[i]->eraseFromParent(); - } - - if (bChanged){ - return PreservedAnalyses::none(); - } - - return PreservedAnalyses::all(); - } - - protected: - Module* pMod = nullptr; - bool bChanged = false; - std::vector delLst; - - void processFunction(Function* pFunc) - { - - for (auto i = pFunc->begin(), e = pFunc->end(); i != e; i++) { - BasicBlock* pBB = llvm::cast(i); - processBasicBlock(pBB); - } - } - - void processBasicBlock(BasicBlock* pBB) - { - for (auto i = pBB->begin(), e = pBB->end(); i != e; i++) { - if (CallInst* pci = llvm::dyn_cast(i)) { - Function * f = pci->getCalledFunction(); - if (nullptr != f) { - if ("llvm.memset.p0i8.i64" == f->getName()) { - convertMemset(pci); - } - } - } - } - } - - void convertMemset(CallInst* pci) - { - std::vector args; - Type* i32Ty = Type::getInt32Ty(pMod->getContext()); - - for (size_t i = 0; i < pci->arg_size(); i++) - { - Value* pv = pci->getArgOperand(i); - if (2 == i) { - if (ConstantInt* ci = llvm::dyn_cast(pv)) { - pv = ConstantInt::get(i32Ty, ci->getValue().getLimitedValue()); - } else { - pv = CastInst::CreateTruncOrBitCast(pv, i32Ty, "ClamBCConvertMemsetsTo32Bit_trunc_", pci); - } - } - - args.push_back(pv); - } - - FunctionCallee f = pMod->getOrInsertFunction("llvm.memset.p0i8.i32", getMemsetType()); - CallInst::Create(f, args, "", pci); - delLst.push_back(pci); - } - - llvm::FunctionType* getMemsetType() - { - static FunctionType* retType = nullptr; - if (nullptr == retType) { - LLVMContext& c = pMod->getContext(); - retType = FunctionType::get(Type::getVoidTy(c), - {Type::getInt8PtrTy(c), Type::getInt8Ty(c), Type::getInt32Ty(c), Type::getInt1Ty(c)}, - false); - } - return retType; - } -}; - -} // end of anonymous namespace - -// This part is the new way of registering your pass -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { - return { - LLVM_PLUGIN_API_VERSION, "ClamBCConvertMemsetsTo32Bit", "v0.1", - [](PassBuilder &PB) { - PB.registerPipelineParsingCallback( - [](StringRef Name, ModulePassManager &FPM, - ArrayRef) { - if(Name == "clambc-convert-memsets-to-32Bit"){ - FPM.addPass(ClamBCConvertMemsetsTo32Bit::ClamBCConvertMemsetsTo32Bit()); - return true; - } - return false; - } - ); - } - }; -} - -