diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 7588c25fd2..f17f92e0e4 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -28,8 +28,8 @@ jobs: - name: Build Doxygen Docs shell: bash env: - CXX: clang++-15 - CC: clang-15 + CXX: clang++-16 + CC: clang-16 run: | cmake -S . -B build -DPHASAR_BUILD_DOC=ON cmake --build ./build --target doc_doxygen diff --git a/CMakeLists.txt b/CMakeLists.txt index e6f2cbcba0..86c4fece2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -335,7 +335,7 @@ option(USE_LLVM_FAT_LIB "Link against libLLVM.so instead of the individual LLVM # LLVM if (NOT PHASAR_LLVM_VERSION) - set(PHASAR_LLVM_VERSION 15) + set(PHASAR_LLVM_VERSION 16) endif() include(add_llvm) add_llvm() diff --git a/bootstrap.sh b/bootstrap.sh index 6ae97de5da..b61241a2be 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -6,10 +6,10 @@ source ./utils/safeCommandsSet.sh readonly PHASAR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" PHASAR_INSTALL_DIR="/usr/local/phasar" -LLVM_INSTALL_DIR="/usr/local/llvm-15" +LLVM_INSTALL_DIR="/usr/local/llvm-16" NUM_THREADS=$(nproc) -LLVM_RELEASE=llvmorg-15.0.7 +LLVM_RELEASE=llvmorg-16.0.6 DO_UNIT_TEST=true DO_INSTALL=false BUILD_TYPE=Release diff --git a/cmake/phasar_macros.cmake b/cmake/phasar_macros.cmake index f6edfef0ee..961d57697d 100644 --- a/cmake/phasar_macros.cmake +++ b/cmake/phasar_macros.cmake @@ -86,7 +86,7 @@ function(generate_ll_file) NAMES clang++-${PHASAR_LLVM_VERSION} clang++ HINTS ${binary_hint_paths}) find_program(opt REQUIRED - NAMES opt-${PHASAR_LLVM_VERSION}4 opt + NAMES opt-${PHASAR_LLVM_VERSION} opt HINTS ${binary_hint_paths}) set(IS_VALID_VERSION "") @@ -212,7 +212,7 @@ function(generate_ll_file) add_custom_command( OUTPUT ${test_code_ll_file} COMMAND ${GEN_CMD} ${test_code_file_path} -o ${test_code_ll_file} - COMMAND ${CMAKE_CXX_COMPILER_LAUNCHER} ${opt} -mem2reg -S ${test_code_ll_file} -o ${test_code_ll_file} + COMMAND ${CMAKE_CXX_COMPILER_LAUNCHER} ${opt} -p mem2reg -S ${test_code_ll_file} -o ${test_code_ll_file} COMMENT ${GEN_CMD_COMMENT} DEPENDS ${GEN_LL_FILE} VERBATIM diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h index 58393936a9..0e200ebb54 100644 --- a/include/phasar/ControlFlow/CallGraphData.h +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -11,6 +11,7 @@ #define PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h index bbd82fad88..dc1b2d816a 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h @@ -351,7 +351,7 @@ template struct JoinEdgeFunction { if (const auto *Join = llvm::dyn_cast(EF)) { return {Join->OtherEF, Join->Seed}; } - return {llvm::makeArrayRef(EF), JLattice::top()}; + return {llvm::ArrayRef(EF), JLattice::top()}; }; auto [LVec, LSeed] = GetEFArrayAndSeed(LHS); diff --git a/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h b/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h index 622c1341a9..9f64625f1f 100644 --- a/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h +++ b/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h @@ -45,8 +45,17 @@ class LLVMProjectIRDB : public ProjectIRDBBase { /// Reads and parses the given LLVM IR file and owns the resulting IR Module. /// If an error occurs, an error message is written to stderr and subsequent /// calls to isValid() return false. + explicit LLVMProjectIRDB(const llvm::Twine &IRFileName); + + /// Reads and parses the given LLVM IR file and owns the resulting IR Module. + /// If an error occurs, an error message is written to stderr and subsequent + /// calls to isValid() return false. + [[deprecated("When moving to the next LLVM version, opaque pointers support " + "is removed completely. Please use one of the other " + "constructors of LLVMProjectIRDB.")]] explicit LLVMProjectIRDB(const llvm::Twine &IRFileName, - bool EnableOpaquePointers = LLVM_VERSION_MAJOR > 14); + bool EnableOpaquePointers); + /// Initializes the new ProjectIRDB with the given IR Module _without_ taking /// ownership. The module is optionally being preprocessed. /// @@ -68,8 +77,16 @@ class LLVMProjectIRDB : public ProjectIRDBBase { /// Parses the given LLVM IR file and owns the resulting IR Module. /// If an error occurs, an error message is written to stderr and subsequent /// calls to isValid() return false. + explicit LLVMProjectIRDB(llvm::MemoryBufferRef Buf); + + /// Parses the given LLVM IR file and owns the resulting IR Module. + /// If an error occurs, an error message is written to stderr and subsequent + /// calls to isValid() return false. + [[deprecated("When moving to the next LLVM version, opaque pointers support " + "is removed completely. Please use one of the other " + "constructors of LLVMProjectIRDB.")]] explicit LLVMProjectIRDB(llvm::MemoryBufferRef Buf, - bool EnableOpaquePointers = LLVM_VERSION_MAJOR > 14); + bool EnableOpaquePointers); LLVMProjectIRDB(const LLVMProjectIRDB &) = delete; LLVMProjectIRDB &operator=(const LLVMProjectIRDB &) = delete; @@ -87,12 +104,12 @@ class LLVMProjectIRDB : public ProjectIRDBBase { llvm::LLVMContext &Ctx) noexcept; [[nodiscard]] static llvm::ErrorOr - load(const llvm::Twine &IRFileName, - bool EnableOpaquePointers = LLVM_VERSION_MAJOR > 14); + load(const llvm::Twine &IRFileName); + + [[nodiscard]] static LLVMProjectIRDB loadOrExit(const llvm::Twine &IRFileName, + int ErrorExitCode = 1); [[nodiscard]] static LLVMProjectIRDB - loadOrExit(const llvm::Twine &IRFileName, - bool EnableOpaquePointers = LLVM_VERSION_MAJOR > 14, - int ErrorExitCode = 1); + loadOrExit(const llvm::Twine &IRFileName, bool EnableOpaquePointers) = delete; /// Also use the const overload using ProjectIRDBBase::getFunction; @@ -165,7 +182,7 @@ class LLVMProjectIRDB : public ProjectIRDBBase { [[nodiscard]] auto getAllInstructionsImpl() const noexcept { return llvm::map_range( - llvm::makeArrayRef(IdToInst).drop_front(IdOffset), + llvm::ArrayRef(IdToInst).drop_front(IdOffset), [](const llvm::Value *V) { return llvm::cast(V); }); } diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysis.h index 7f3e1ef8dc..9c4498190f 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysis.h @@ -22,8 +22,8 @@ #include "phasar/Utils/TypeTraits.h" #include "llvm/ADT/FunctionExtras.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/bit.h" #include #include @@ -48,7 +48,7 @@ struct IDEFeatureTaintEdgeFact { } #endif - llvm::SmallBitVector Ret(llvm::findLastSet(Bits) + 1); + llvm::SmallBitVector Ret(llvm::bit_width(Bits)); Ret.setBitsInMask((const uint32_t *)&Bits, sizeof(Bits)); return Ret; } @@ -62,7 +62,7 @@ struct IDEFeatureTaintEdgeFact { explicit IDEFeatureTaintEdgeFact() noexcept { Taints.invalid(); } void unionWith(uintptr_t Facts) { - auto RequiredSize = llvm::findLastSet(Facts) + 1; + size_t RequiredSize = llvm::bit_width(Facts); if (RequiredSize > Taints.size()) { Taints.resize(RequiredSize); } @@ -247,7 +247,7 @@ class FeatureTaintGenerator { FeatureTaintGenerator(EdgeFactGenerator &&EFGen) : FeatureTaintGenerator( [EFGen](InstOrGlobal IG) { - return !llvm::empty(std::invoke(EFGen, IG)); + return !std::empty(std::invoke(EFGen, IG)); }, std::forward(EFGen)) {} diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.h index 783698c91c..56a7e86f9b 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.h @@ -18,6 +18,7 @@ #include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/raw_ostream.h" +#include #include namespace psr::glca { diff --git a/include/phasar/PhasarLLVM/HelperAnalyses.h b/include/phasar/PhasarLLVM/HelperAnalyses.h index c3287ffe94..63b9044444 100644 --- a/include/phasar/PhasarLLVM/HelperAnalyses.h +++ b/include/phasar/PhasarLLVM/HelperAnalyses.h @@ -15,6 +15,8 @@ #include "phasar/PhasarLLVM/HelperAnalysisConfig.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h" +#include "llvm/ADT/Twine.h" + #include #include #include diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h index d895741ad2..282530f2dc 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMALIASSETDATA_H #define PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMALIASSETDATA_H +#include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h index e3997d9f53..c6ed7bdaa1 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMVFTABLEDATA_H_ #define PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMVFTABLEDATA_H_ +#include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/lib/ControlFlow/CallGraphAnalysisType.cpp b/lib/ControlFlow/CallGraphAnalysisType.cpp index e244e28a86..52c1c1014f 100644 --- a/lib/ControlFlow/CallGraphAnalysisType.cpp +++ b/lib/ControlFlow/CallGraphAnalysisType.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" std::string psr::toString(CallGraphAnalysisType CGA) { switch (CGA) { diff --git a/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp b/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp index 09e3b86c56..954d47ee36 100644 --- a/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp +++ b/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp @@ -24,6 +24,7 @@ namespace psr { +[[deprecated]] static void setOpaquePointersForCtx(llvm::LLVMContext &Ctx, bool Enable) { #if LLVM_VERSION_MAJOR >= 15 && LLVM_VERSION_MAJOR < 17 if (!Enable) { @@ -115,28 +116,19 @@ LLVMProjectIRDB::getParsedIRModuleOrErr(const llvm::Twine &IRFileName, } llvm::ErrorOr -LLVMProjectIRDB::load(const llvm::Twine &IRFileName, - bool EnableOpaquePointers) { - auto FileOrErr = - llvm::MemoryBuffer::getFileOrSTDIN(IRFileName, /*IsText=*/true); - if (!FileOrErr) { - return FileOrErr.getError(); - } - +LLVMProjectIRDB::load(const llvm::Twine &IRFileName) { auto Ctx = std::make_unique(); - - auto M = getParsedIRModuleOrErr(**FileOrErr, *Ctx); + auto M = getParsedIRModuleOrErr(IRFileName, *Ctx); if (!M) { return M.getError(); } - return LLVMProjectIRDB(std::move(*M), std::move(Ctx), EnableOpaquePointers); + return LLVMProjectIRDB(std::move(*M), std::move(Ctx)); } LLVMProjectIRDB LLVMProjectIRDB::loadOrExit(const llvm::Twine &IRFileName, - bool EnableOpaquePointers, int ErrorExitCode) { - auto Ret = load(IRFileName, EnableOpaquePointers); + auto Ret = load(IRFileName); if (!Ret) { llvm::WithColor::error() << "Could not load LLVM-" << LLVM_VERSION_MAJOR << " IR file " @@ -147,6 +139,20 @@ LLVMProjectIRDB LLVMProjectIRDB::loadOrExit(const llvm::Twine &IRFileName, return std::move(*Ret); } +LLVMProjectIRDB::LLVMProjectIRDB(const llvm::Twine &IRFileName) + : Ctx(new llvm::LLVMContext()) { + auto M = getParsedIRModuleOrErr(IRFileName, *Ctx); + + if (!M) { + return; + } + + auto *NonConst = M->get(); + Mod = std::move(M.get()); + ModulesToSlotTracker::setMSTForModule(Mod.get()); + preprocessModule(NonConst); +} + LLVMProjectIRDB::LLVMProjectIRDB(const llvm::Twine &IRFileName, bool EnableOpaquePointers) : Ctx(new llvm::LLVMContext()) { @@ -253,6 +259,18 @@ LLVMProjectIRDB::LLVMProjectIRDB(std::unique_ptr Mod, this->Ctx = std::move(Ctx); } +LLVMProjectIRDB::LLVMProjectIRDB(llvm::MemoryBufferRef Buf) + : Ctx(new llvm::LLVMContext()) { + auto M = getParsedIRModuleOrErr(Buf, *Ctx); + if (!M) { + return; + } + + auto *NonConst = M->get(); + Mod = std::move(M.get()); + ModulesToSlotTracker::setMSTForModule(Mod.get()); + preprocessModule(NonConst); +} LLVMProjectIRDB::LLVMProjectIRDB(llvm::MemoryBufferRef Buf, bool EnableOpaquePointers) : Ctx(new llvm::LLVMContext()) { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/ExtendedTaintAnalysis/AbstractMemoryLocation.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/ExtendedTaintAnalysis/AbstractMemoryLocation.cpp index da9898ee05..b01b8483fa 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/ExtendedTaintAnalysis/AbstractMemoryLocation.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/ExtendedTaintAnalysis/AbstractMemoryLocation.cpp @@ -37,8 +37,7 @@ AbstractMemoryLocationImpl::AbstractMemoryLocationImpl( AbstractMemoryLocationImpl::AbstractMemoryLocationImpl( const llvm::Value *Baseptr, llvm::SmallVectorImpl &&Offsets, unsigned Lifetime) noexcept - : AbstractMemoryLocationImpl(Baseptr, llvm::makeArrayRef(Offsets), - Lifetime) {} + : AbstractMemoryLocationImpl(Baseptr, llvm::ArrayRef(Offsets), Lifetime) {} AbstractMemoryLocationImpl::AbstractMemoryLocationImpl( const llvm::Value *Baseptr, llvm::ArrayRef Offsets, unsigned Lifetime) noexcept @@ -52,7 +51,7 @@ bool AbstractMemoryLocationImpl::isZero() const { } llvm::ArrayRef AbstractMemoryLocationImpl::offsets() const { - return llvm::makeArrayRef(this->getTrailingObjects(), NumOffsets); + return llvm::ArrayRef(this->getTrailingObjects(), NumOffsets); } auto AbstractMemoryLocationImpl::computeOffset( diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index dc1b619e22..8d1c1d9a73 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -349,7 +349,7 @@ IDEExtendedTaintAnalysis::getCallFlowFunction(n_t CallStmt, f_t DestFun) { /// padding for now. } Offs += - ptrdiff_t(DL.getTypeAllocSize(It->get()->getType()).getFixedSize()); + ptrdiff_t(DL.getTypeAllocSize(It->get()->getType()).getFixedValue()); } #ifdef XTAINT_DIAGNOSTICS allTaintedValues.insert(ret.begin(), ret.end()); diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.cpp index 93e4089eb3..c1f05d4b93 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.cpp @@ -191,20 +191,6 @@ bool EdgeValue::isString() const { return VariantType == String; } EdgeValue::Type EdgeValue::getKind() const { return VariantType; } -EdgeValue::operator bool() { - switch (VariantType) { - case Integer: - return !std::get(ValVariant).isNullValue(); - case FloatingPoint: - return std::get(ValVariant).isNonZero(); - case String: - return !std::get(ValVariant).empty(); - default: - break; - } - return false; -} - bool operator==(const EdgeValue &Lhs, const EdgeValue &Rhs) { if (Lhs.VariantType != Rhs.VariantType) { return false; diff --git a/lib/PhasarLLVM/DataFlow/PathSensitivity/Z3BasedPathSensitivityManager.cpp b/lib/PhasarLLVM/DataFlow/PathSensitivity/Z3BasedPathSensitivityManager.cpp index 65c121163c..a1d3f47b0b 100644 --- a/lib/PhasarLLVM/DataFlow/PathSensitivity/Z3BasedPathSensitivityManager.cpp +++ b/lib/PhasarLLVM/DataFlow/PathSensitivity/Z3BasedPathSensitivityManager.cpp @@ -95,7 +95,7 @@ z3::expr Z3BasedPathSensitivityManagerBase::filterOutUnreachableNodes( llvm_unreachable("Adj nonempty and Ys empty is unexpected"); } auto Y = Ys[0]; - for (const auto &Constr : llvm::makeArrayRef(Ys).drop_front()) { + for (const auto &Constr : llvm::ArrayRef(Ys).drop_front()) { Y = Y || Constr; } return Ctx.NodeConstraints[Vtx] = (X && Y).simplify(); diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp index 5b246c3d8f..3974f59d1b 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp @@ -359,7 +359,7 @@ void LLVMAliasSet::addPointer(FunctionAliasView AA, const llvm::DataLayout &DL, Reps[ToMerge[0]]->getType()}; llvm::SmallVector ToRemove; - for (auto Idx : llvm::makeArrayRef(ToMerge).slice(1)) { + for (auto Idx : llvm::ArrayRef(ToMerge).slice(1)) { mergeAliasSets(PTS, AliasSets[Reps[Idx]]); if (auto [Unused, Inserted] = OccurringTypes.insert(Reps[Idx]->getType()); !Inserted) { diff --git a/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp b/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp index 38a79105b0..0406dbfbc9 100644 --- a/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp @@ -45,7 +45,7 @@ bool LLVMBasedAliasAnalysis::hasAliasInfo(const llvm::Function &Fun) const { } void LLVMBasedAliasAnalysis::computeAliasInfo(llvm::Function &Fun) { - llvm::PreservedAnalyses PA = FPM.run(Fun, FAM); + // llvm::PreservedAnalyses PA = FPM.run(Fun, FAM); llvm::AAResults &AAR = FAM.getResult(Fun); AAInfos.insert(std::make_pair(&Fun, &AAR)); } @@ -81,6 +81,7 @@ LLVMBasedAliasAnalysis::LLVMBasedAliasAnalysis(LLVMProjectIRDB &IRDB, default: break; } + // Note: The order of the alias analyses is important. See LLVM's source // code for reference (e.g. registerAAAnalyses() in // llvm/CodeGen/CodeGenPassBuilder.h) @@ -90,7 +91,13 @@ LLVMBasedAliasAnalysis::LLVMBasedAliasAnalysis(LLVMProjectIRDB &IRDB, AA.registerFunctionAnalysis(); return AA; }); + PB.registerFunctionAnalyses(FAM); + if (PATy == AliasAnalysisType::CFLAnders) { + FAM.registerPass([] { return llvm::CFLAndersAA(); }); + } else if (PATy == AliasAnalysisType::CFLSteens) { + FAM.registerPass([] { return llvm::CFLSteensAA(); }); + } if (!UseLazyEvaluation) { for (auto &F : *IRDB.getModule()) { diff --git a/lib/PhasarLLVM/Pointer/external/README.md b/lib/PhasarLLVM/Pointer/external/README.md index b35f89681c..072dd8ea8c 100644 --- a/lib/PhasarLLVM/Pointer/external/README.md +++ b/lib/PhasarLLVM/Pointer/external/README.md @@ -3,8 +3,8 @@ All files in the `llvm` subfolder are 1:1 copied from LLVM 14.0.6 and are subject to the LLVM license. You can find a copy of the LLVM license [here](./LLVM-LICENSE.txt). -Note that we needed to copy these files, as LLVM removed them in the transition from version 14 to 15. +Note that we needed to copy these files, as LLVM removed them in the transition from version 14 to more recent LLVM versions. To avoid LLVM from blocking PhASAR releases, we provide these files ourselves as a *temporary solution*. -We, as the PhASAR development core team, do not aim for maintaining the here provided LLVM code and will not add any modifications to it (bugfixes, enhancements, etc.). +We, as the PhASAR development core team, do not aim for maintaining the here provided LLVM code and will not add any modifications to it, except for compilation fixes when changing the LLVM version (bugfixes, enhancements, etc.). Rather, we will add a custom replacement eventually. diff --git a/lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.cpp b/lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.cpp new file mode 100644 index 0000000000..66b25a6567 --- /dev/null +++ b/lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.cpp @@ -0,0 +1,105 @@ +#include "AliasAnalysisSummary.h" + +#include "llvm/IR/Argument.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +namespace cflaa { + +namespace { +const unsigned AttrEscapedIndex = 0; +const unsigned AttrUnknownIndex = 1; +const unsigned AttrGlobalIndex = 2; +const unsigned AttrCallerIndex = 3; +const unsigned AttrFirstArgIndex = 4; +const unsigned AttrLastArgIndex = NumAliasAttrs; +const unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex; + +// It would be *slightly* prettier if we changed these to AliasAttrs, but it +// seems that both GCC and MSVC emit dynamic initializers for const bitsets. +using AliasAttr = unsigned; +const AliasAttr AttrNone = 0; +const AliasAttr AttrEscaped = 1 << AttrEscapedIndex; +const AliasAttr AttrUnknown = 1 << AttrUnknownIndex; +const AliasAttr AttrGlobal = 1 << AttrGlobalIndex; +const AliasAttr AttrCaller = 1 << AttrCallerIndex; +const AliasAttr ExternalAttrMask = AttrEscaped | AttrUnknown | AttrGlobal; +} // namespace + +AliasAttrs getAttrNone() { return AttrNone; } + +AliasAttrs getAttrUnknown() { return AttrUnknown; } +bool hasUnknownAttr(AliasAttrs Attr) { return Attr.test(AttrUnknownIndex); } + +AliasAttrs getAttrCaller() { return AttrCaller; } +bool hasCallerAttr(AliasAttrs Attr) { return Attr.test(AttrCaller); } +bool hasUnknownOrCallerAttr(AliasAttrs Attr) { + return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex); +} + +AliasAttrs getAttrEscaped() { return AttrEscaped; } +bool hasEscapedAttr(AliasAttrs Attr) { return Attr.test(AttrEscapedIndex); } + +static AliasAttr argNumberToAttr(unsigned ArgNum) { + if (ArgNum >= AttrMaxNumArgs) + return AttrUnknown; + // N.B. MSVC complains if we use `1U` here, since AliasAttr' ctor takes + // an unsigned long long. + return AliasAttr(1ULL << (ArgNum + AttrFirstArgIndex)); +} + +AliasAttrs getGlobalOrArgAttrFromValue(const Value &Val) { + if (isa(Val)) + return AttrGlobal; + + if (auto *Arg = dyn_cast(&Val)) + // Only pointer arguments should have the argument attribute, + // because things can't escape through scalars without us seeing a + // cast, and thus, interaction with them doesn't matter. + if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy()) + return argNumberToAttr(Arg->getArgNo()); + return AttrNone; +} + +bool isGlobalOrArgAttr(AliasAttrs Attr) { + return Attr.reset(AttrEscapedIndex) + .reset(AttrUnknownIndex) + .reset(AttrCallerIndex) + .any(); +} + +AliasAttrs getExternallyVisibleAttrs(AliasAttrs Attr) { + return Attr & AliasAttrs(ExternalAttrMask); +} + +std::optional +instantiateInterfaceValue(InterfaceValue IValue, CallBase &Call) { + auto Index = IValue.Index; + auto *V = (Index == 0) ? &Call : Call.getArgOperand(Index - 1); + if (V->getType()->isPointerTy()) + return InstantiatedValue{V, IValue.DerefLevel}; + return std::nullopt; +} + +std::optional +instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call) { + auto From = instantiateInterfaceValue(ERelation.From, Call); + if (!From) + return std::nullopt; + auto To = instantiateInterfaceValue(ERelation.To, Call); + if (!To) + return std::nullopt; + return InstantiatedRelation{*From, *To, ERelation.Offset}; +} + +std::optional +instantiateExternalAttribute(ExternalAttribute EAttr, CallBase &Call) { + auto Value = instantiateInterfaceValue(EAttr.IValue, Call); + if (!Value) + return std::nullopt; + return InstantiatedAttr{*Value, EAttr.Attr}; +} +} // namespace cflaa +} // namespace llvm diff --git a/lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.h b/lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.h index 6fcb6cc4b4..5f5ea0516e 100644 --- a/lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.h +++ b/lib/PhasarLLVM/Pointer/external/llvm/AliasAnalysisSummary.h @@ -35,10 +35,10 @@ #define LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H #include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include +#include namespace llvm { @@ -204,8 +204,8 @@ struct InstantiatedValue { Value *Val; unsigned DerefLevel; }; -Optional instantiateInterfaceValue(InterfaceValue IValue, - CallBase &Call); +std::optional +instantiateInterfaceValue(InterfaceValue IValue, CallBase &Call); inline bool operator==(InstantiatedValue LHS, InstantiatedValue RHS) { return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel; @@ -233,7 +233,7 @@ struct InstantiatedRelation { InstantiatedValue From, To; int64_t Offset; }; -Optional +std::optional instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call); /// This is the result of instantiating ExternalAttribute at a particular @@ -242,8 +242,8 @@ struct InstantiatedAttr { InstantiatedValue IValue; AliasAttrs Attr; }; -Optional instantiateExternalAttribute(ExternalAttribute EAttr, - CallBase &Call); +std::optional +instantiateExternalAttribute(ExternalAttribute EAttr, CallBase &Call); } // namespace cflaa template <> struct DenseMapInfo { diff --git a/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.cpp b/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.cpp index 404e0df3aa..36796b40e6 100644 --- a/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.cpp +++ b/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.cpp @@ -52,13 +52,11 @@ // run on. Realistically, this likely isn't a problem until we allow // FunctionPasses to run concurrently. -#include "llvm/Analysis/CFLAndersAliasAnalysis.h" +#include "CFLAndersAliasAnalysis.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" @@ -336,7 +334,7 @@ class CFLAndersAAResult::FunctionInfo { /// Summary of externally visible effects. AliasSummary Summary; - Optional getAttrs(const Value *) const; + std::optional getAttrs(const Value *) const; public: FunctionInfo(const Function &, const SmallVectorImpl &, @@ -354,12 +352,12 @@ static bool hasWriteOnlyState(StateSet Set) { return (Set & StateSet(WriteOnlyStateMask)).any(); } -static Optional +static std::optional getInterfaceValue(InstantiatedValue IValue, const SmallVectorImpl &RetVals) { auto Val = IValue.Val; - Optional Index; + std::optional Index; if (auto Arg = dyn_cast(Val)) Index = Arg->getArgNo() + 1; else if (is_contained(RetVals, Val)) @@ -367,7 +365,7 @@ getInterfaceValue(InstantiatedValue IValue, if (Index) return InterfaceValue{*Index, IValue.DerefLevel}; - return None; + return {}; } static void populateAttrMap(DenseMap &AttrMap, @@ -510,14 +508,14 @@ CFLAndersAAResult::FunctionInfo::FunctionInfo( populateExternalRelations(Summary.RetParamRelations, Fn, RetVals, ReachSet); } -Optional +std::optional CFLAndersAAResult::FunctionInfo::getAttrs(const Value *V) const { assert(V != nullptr); auto Itr = AttrMap.find(V); if (Itr != AttrMap.end()) return Itr->second; - return None; + return {}; } bool CFLAndersAAResult::FunctionInfo::mayAlias( @@ -628,12 +626,12 @@ static void initializeWorkList(std::vector &WorkList, } } -static Optional getNodeBelow(const CFLGraph &Graph, - InstantiatedValue V) { +static std::optional getNodeBelow(const CFLGraph &Graph, + InstantiatedValue V) { auto NodeBelow = InstantiatedValue{V.Val, V.DerefLevel + 1}; if (Graph.getNode(NodeBelow)) return NodeBelow; - return None; + return {}; } static void processWorkListItem(const WorkListItem &Item, const CFLGraph &Graph, @@ -812,7 +810,8 @@ CFLAndersAAResult::buildInfoFrom(const Function &Fn) { } void CFLAndersAAResult::scan(const Function &Fn) { - auto InsertPair = Cache.insert(std::make_pair(&Fn, Optional())); + auto InsertPair = + Cache.insert(std::make_pair(&Fn, std::optional())); (void)InsertPair; assert(InsertPair.second && "Trying to scan a function that has already been cached"); @@ -827,21 +826,21 @@ void CFLAndersAAResult::scan(const Function &Fn) { void CFLAndersAAResult::evict(const Function *Fn) { Cache.erase(Fn); } -const Optional & +const std::optional & CFLAndersAAResult::ensureCached(const Function &Fn) { auto Iter = Cache.find(&Fn); if (Iter == Cache.end()) { scan(Fn); Iter = Cache.find(&Fn); assert(Iter != Cache.end()); - assert(Iter->second.hasValue()); + assert(Iter->second.has_value()); } return Iter->second; } const AliasSummary *CFLAndersAAResult::getAliasSummary(const Function &Fn) { auto &FunInfo = ensureCached(Fn); - if (FunInfo.hasValue()) + if (FunInfo.has_value()) return &FunInfo->getAliasSummary(); else return nullptr; @@ -881,7 +880,8 @@ AliasResult CFLAndersAAResult::query(const MemoryLocation &LocA, AliasResult CFLAndersAAResult::alias(const MemoryLocation &LocA, const MemoryLocation &LocB, - AAQueryInfo &AAQI) { + AAQueryInfo &AAQI, + const Instruction *CtxI) { if (LocA.Ptr == LocB.Ptr) return AliasResult::MustAlias; @@ -891,11 +891,11 @@ AliasResult CFLAndersAAResult::alias(const MemoryLocation &LocA, // ConstantExpr, but every query needs to have at least one Value tied to a // Function, and neither GlobalValues nor ConstantExprs are. if (isa(LocA.Ptr) && isa(LocB.Ptr)) - return AAResultBase::alias(LocA, LocB, AAQI); + return AAResultBase::alias(LocA, LocB, AAQI, CtxI); AliasResult QueryResult = query(LocA, LocB); if (QueryResult == AliasResult::MayAlias) - return AAResultBase::alias(LocA, LocB, AAQI); + return AAResultBase::alias(LocA, LocB, AAQI, CtxI); return QueryResult; } @@ -908,27 +908,3 @@ CFLAndersAAResult CFLAndersAA::run(Function &F, FunctionAnalysisManager &AM) { }; return CFLAndersAAResult(GetTLI); } - -char CFLAndersAAWrapperPass::ID = 0; -INITIALIZE_PASS(CFLAndersAAWrapperPass, "cfl-anders-aa", - "Inclusion-Based CFL Alias Analysis", false, true) - -ImmutablePass *llvm::createCFLAndersAAWrapperPass() { - return new CFLAndersAAWrapperPass(); -} - -CFLAndersAAWrapperPass::CFLAndersAAWrapperPass() : ImmutablePass(ID) { - initializeCFLAndersAAWrapperPassPass(*PassRegistry::getPassRegistry()); -} - -void CFLAndersAAWrapperPass::initializePass() { - auto GetTLI = [this](Function &F) -> TargetLibraryInfo & { - return this->getAnalysis().getTLI(F); - }; - Result.reset(new CFLAndersAAResult(GetTLI)); -} - -void CFLAndersAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired(); -} diff --git a/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.h b/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.h index ddc2908855..fca6cb7711 100644 --- a/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.h +++ b/lib/PhasarLLVM/Pointer/external/llvm/CFLAndersAliasAnalysis.h @@ -15,12 +15,12 @@ #define LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/CFLAliasAnalysisUtils.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" +#include "CFLAliasAnalysisUtils.h" + #include #include @@ -36,9 +36,7 @@ struct AliasSummary; } // end namespace cflaa -class CFLAndersAAResult : public AAResultBase { - friend AAResultBase; - +class CFLAndersAAResult : public AAResultBase { class FunctionInfo; public: @@ -63,12 +61,12 @@ class CFLAndersAAResult : public AAResultBase { AliasResult query(const MemoryLocation &, const MemoryLocation &); AliasResult alias(const MemoryLocation &, const MemoryLocation &, - AAQueryInfo &); + AAQueryInfo &, const Instruction *CtxI); private: /// Ensures that the given function is available in the cache. /// Returns the appropriate entry from the cache. - const Optional &ensureCached(const Function &); + const std::optional &ensureCached(const Function &); /// Inserts the given Function into the cache. void scan(const Function &); @@ -83,7 +81,7 @@ class CFLAndersAAResult : public AAResultBase { /// in the cache as an Optional without a value. This way, if we /// have any kind of recursion, it is discernable from a function /// that simply has empty sets. - DenseMap> Cache; + DenseMap> Cache; std::forward_list> Handles; }; @@ -103,26 +101,6 @@ class CFLAndersAA : public AnalysisInfoMixin { CFLAndersAAResult run(Function &F, FunctionAnalysisManager &AM); }; -/// Legacy wrapper pass to provide the CFLAndersAAResult object. -class CFLAndersAAWrapperPass : public ImmutablePass { - std::unique_ptr Result; - -public: - static char ID; - - CFLAndersAAWrapperPass(); - - CFLAndersAAResult &getResult() { return *Result; } - const CFLAndersAAResult &getResult() const { return *Result; } - - void initializePass() override; - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; - -// createCFLAndersAAWrapperPass - This pass implements a set-based approach to -// alias analysis. -ImmutablePass *createCFLAndersAAWrapperPass(); - } // end namespace llvm #endif // LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H diff --git a/lib/PhasarLLVM/Pointer/external/llvm/CFLGraph.h b/lib/PhasarLLVM/Pointer/external/llvm/CFLGraph.h index c3e53c1146..999a420a89 100644 --- a/lib/PhasarLLVM/Pointer/external/llvm/CFLGraph.h +++ b/lib/PhasarLLVM/Pointer/external/llvm/CFLGraph.h @@ -405,7 +405,7 @@ template class CFLGraphBuilder { auto &RetParamRelations = Summary->RetParamRelations; for (auto &Relation : RetParamRelations) { auto IRelation = instantiateExternalRelation(Relation, Call); - if (IRelation.hasValue()) { + if (IRelation.has_value()) { Graph.addNode(IRelation->From); Graph.addNode(IRelation->To); Graph.addEdge(IRelation->From, IRelation->To); @@ -415,7 +415,7 @@ template class CFLGraphBuilder { auto &RetParamAttributes = Summary->RetParamAttributes; for (auto &Attribute : RetParamAttributes) { auto IAttr = instantiateExternalAttribute(Attribute, Call); - if (IAttr.hasValue()) + if (IAttr.has_value()) Graph.addNode(IAttr->IValue, IAttr->Attr); } } @@ -649,8 +649,8 @@ template class CFLGraphBuilder { void buildGraphFrom(Function &Fn) { GetEdgesVisitor Visitor(*this, Fn.getParent()->getDataLayout()); - for (auto &Bb : Fn.getBasicBlockList()) - for (auto &Inst : Bb.getInstList()) + for (auto &Bb : Fn) + for (auto &Inst : Bb) addInstructionToGraph(Visitor, Inst); for (auto &Arg : Fn.args()) diff --git a/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.cpp b/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.cpp index 1a17153b3c..33fd1e6b11 100644 --- a/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.cpp +++ b/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.cpp @@ -34,10 +34,9 @@ // run on. Realistically, this likely isn't a problem until we allow // FunctionPasses to run concurrently. -#include "llvm/Analysis/CFLSteensAliasAnalysis.h" +#include "CFLSteensAliasAnalysis.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/Constants.h" @@ -168,7 +167,7 @@ CFLSteensAAResult::FunctionInfo::FunctionInfo( assert(RetVal != nullptr); assert(RetVal->getType()->isPointerTy()); auto RetInfo = Sets.find(InstantiatedValue{RetVal, 0}); - if (RetInfo.hasValue()) + if (RetInfo.has_value()) AddToRetParamRelations(0, RetInfo->Index); } @@ -177,7 +176,7 @@ CFLSteensAAResult::FunctionInfo::FunctionInfo( for (auto &Param : Fn.args()) { if (Param.getType()->isPointerTy()) { auto ParamInfo = Sets.find(InstantiatedValue{&Param, 0}); - if (ParamInfo.hasValue()) + if (ParamInfo.has_value()) AddToRetParamRelations(I + 1, ParamInfo->Index); } ++I; @@ -228,7 +227,8 @@ CFLSteensAAResult::FunctionInfo CFLSteensAAResult::buildSetsFrom(Function *Fn) { } void CFLSteensAAResult::scan(Function *Fn) { - auto InsertPair = Cache.insert(std::make_pair(Fn, Optional())); + auto InsertPair = + Cache.insert(std::make_pair(Fn, std::optional())); (void)InsertPair; assert(InsertPair.second && "Trying to scan a function that has already been cached"); @@ -246,21 +246,21 @@ void CFLSteensAAResult::evict(Function *Fn) { Cache.erase(Fn); } /// Ensures that the given function is available in the cache, and returns the /// entry. -const Optional & +const std::optional & CFLSteensAAResult::ensureCached(Function *Fn) { auto Iter = Cache.find(Fn); if (Iter == Cache.end()) { scan(Fn); Iter = Cache.find(Fn); assert(Iter != Cache.end()); - assert(Iter->second.hasValue()); + assert(Iter->second.has_value()); } return Iter->second; } const AliasSummary *CFLSteensAAResult::getAliasSummary(Function &Fn) { auto &FunInfo = ensureCached(&Fn); - if (FunInfo.hasValue()) + if (FunInfo.has_value()) return &FunInfo->getAliasSummary(); else return nullptr; @@ -296,15 +296,15 @@ AliasResult CFLSteensAAResult::query(const MemoryLocation &LocA, assert(Fn != nullptr); auto &MaybeInfo = ensureCached(Fn); - assert(MaybeInfo.hasValue()); + assert(MaybeInfo.has_value()); auto &Sets = MaybeInfo->getStratifiedSets(); auto MaybeA = Sets.find(InstantiatedValue{ValA, 0}); - if (!MaybeA.hasValue()) + if (!MaybeA.has_value()) return AliasResult::MayAlias; auto MaybeB = Sets.find(InstantiatedValue{ValB, 0}); - if (!MaybeB.hasValue()) + if (!MaybeB.has_value()) return AliasResult::MayAlias; auto SetA = *MaybeA; @@ -341,27 +341,3 @@ CFLSteensAAResult CFLSteensAA::run(Function &F, FunctionAnalysisManager &AM) { }; return CFLSteensAAResult(GetTLI); } - -char CFLSteensAAWrapperPass::ID = 0; -INITIALIZE_PASS(CFLSteensAAWrapperPass, "cfl-steens-aa", - "Unification-Based CFL Alias Analysis", false, true) - -ImmutablePass *llvm::createCFLSteensAAWrapperPass() { - return new CFLSteensAAWrapperPass(); -} - -CFLSteensAAWrapperPass::CFLSteensAAWrapperPass() : ImmutablePass(ID) { - initializeCFLSteensAAWrapperPassPass(*PassRegistry::getPassRegistry()); -} - -void CFLSteensAAWrapperPass::initializePass() { - auto GetTLI = [this](Function &F) -> const TargetLibraryInfo & { - return this->getAnalysis().getTLI(F); - }; - Result.reset(new CFLSteensAAResult(GetTLI)); -} - -void CFLSteensAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired(); -} diff --git a/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.h b/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.h index b0ab37baa4..c405209e1c 100644 --- a/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.h +++ b/lib/PhasarLLVM/Pointer/external/llvm/CFLSteensAliasAnalysis.h @@ -15,14 +15,14 @@ #define LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/CFLAliasAnalysisUtils.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" +#include "CFLAliasAnalysisUtils.h" + #include #include @@ -37,9 +37,7 @@ struct AliasSummary; } // end namespace cflaa -class CFLSteensAAResult : public AAResultBase { - friend AAResultBase; - +class CFLSteensAAResult : public AAResultBase { class FunctionInfo; public: @@ -63,7 +61,7 @@ class CFLSteensAAResult : public AAResultBase { /// Ensures that the given function is available in the cache. /// Returns the appropriate entry from the cache. - const Optional &ensureCached(Function *Fn); + const std::optional &ensureCached(Function *Fn); /// Get the alias summary for the given function /// Return nullptr if the summary is not found or not available @@ -72,7 +70,7 @@ class CFLSteensAAResult : public AAResultBase { AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB); AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, - AAQueryInfo &AAQI) { + AAQueryInfo &AAQI, const Instruction *CtxI) { if (LocA.Ptr == LocB.Ptr) return AliasResult::MustAlias; @@ -82,11 +80,11 @@ class CFLSteensAAResult : public AAResultBase { // ConstantExpr, but every query needs to have at least one Value tied to a // Function, and neither GlobalValues nor ConstantExprs are. if (isa(LocA.Ptr) && isa(LocB.Ptr)) - return AAResultBase::alias(LocA, LocB, AAQI); + return AAResultBase::alias(LocA, LocB, AAQI, CtxI); AliasResult QueryResult = query(LocA, LocB); if (QueryResult == AliasResult::MayAlias) - return AAResultBase::alias(LocA, LocB, AAQI); + return AAResultBase::alias(LocA, LocB, AAQI, CtxI); return QueryResult; } @@ -99,7 +97,7 @@ class CFLSteensAAResult : public AAResultBase { /// in the cache as an Optional without a value. This way, if we /// have any kind of recursion, it is discernable from a function /// that simply has empty sets. - DenseMap> Cache; + DenseMap> Cache; std::forward_list> Handles; FunctionInfo buildSetsFrom(Function *F); @@ -120,26 +118,6 @@ class CFLSteensAA : public AnalysisInfoMixin { CFLSteensAAResult run(Function &F, FunctionAnalysisManager &AM); }; -/// Legacy wrapper pass to provide the CFLSteensAAResult object. -class CFLSteensAAWrapperPass : public ImmutablePass { - std::unique_ptr Result; - -public: - static char ID; - - CFLSteensAAWrapperPass(); - - CFLSteensAAResult &getResult() { return *Result; } - const CFLSteensAAResult &getResult() const { return *Result; } - - void initializePass() override; - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; - -// createCFLSteensAAWrapperPass - This pass implements a set-based approach to -// alias analysis. -ImmutablePass *createCFLSteensAAWrapperPass(); - } // end namespace llvm #endif // LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H diff --git a/lib/PhasarLLVM/Pointer/external/llvm/StratifiedSets.h b/lib/PhasarLLVM/Pointer/external/llvm/StratifiedSets.h index 71f07af543..78ac53f88a 100644 --- a/lib/PhasarLLVM/Pointer/external/llvm/StratifiedSets.h +++ b/lib/PhasarLLVM/Pointer/external/llvm/StratifiedSets.h @@ -10,7 +10,6 @@ #define LLVM_ADT_STRATIFIEDSETS_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" @@ -19,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -93,10 +93,10 @@ template class StratifiedSets { std::vector Links) : Values(std::move(Map)), Links(std::move(Links)) {} - Optional find(const T &Elem) const { + std::optional find(const T &Elem) const { auto Iter = Values.find(Elem); if (Iter == Values.end()) - return None; + return std::nullopt; return Iter->second; } @@ -342,10 +342,10 @@ template class StratifiedSetsBuilder { return StratifiedSets(std::move(Values), std::move(StratLinks)); } - bool has(const T &Elem) const { return get(Elem).hasValue(); } + bool has(const T &Elem) const { return get(Elem).has_value(); } bool add(const T &Main) { - if (get(Main).hasValue()) + if (get(Main).has_value()) return false; auto NewIndex = getNewUnlinkedIndex(); @@ -546,24 +546,24 @@ template class StratifiedSetsBuilder { return true; } - Optional get(const T &Val) const { + std::optional get(const T &Val) const { auto Result = Values.find(Val); if (Result == Values.end()) - return None; + return std::nullopt; return &Result->second; } - Optional get(const T &Val) { + std::optional get(const T &Val) { auto Result = Values.find(Val); if (Result == Values.end()) - return None; + return std::nullopt; return &Result->second; } - Optional indexOf(const T &Val) { + std::optional indexOf(const T &Val) { auto MaybeVal = get(Val); - if (!MaybeVal.hasValue()) - return None; + if (!MaybeVal.has_value()) + return std::nullopt; auto *Info = *MaybeVal; auto &Link = linksAt(Info->Index); return Link.Number; diff --git a/lib/PhasarLLVM/TaintConfig/LLVMTaintConfig.cpp b/lib/PhasarLLVM/TaintConfig/LLVMTaintConfig.cpp index 7528eb9c5d..f8a392c4db 100644 --- a/lib/PhasarLLVM/TaintConfig/LLVMTaintConfig.cpp +++ b/lib/PhasarLLVM/TaintConfig/LLVMTaintConfig.cpp @@ -16,6 +16,7 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" @@ -182,9 +183,20 @@ LLVMTaintConfig::LLVMTaintConfig(const psr::LLVMProjectIRDB &Code, } LLVMTaintConfig::LLVMTaintConfig(const psr::LLVMProjectIRDB &AnnotatedCode) { + + llvm::SmallVector VarAnnotations{}; + llvm::SmallVector PtrAnnotations{}; + for (const auto *F : AnnotatedCode.getAllFunctions()) { + if (F->getName().startswith("llvm.var.annotation")) { + VarAnnotations.push_back(F); + } + if (F->getName().startswith("llvm.ptr.annotation")) { + PtrAnnotations.push_back(F); + } + } + // handle "local" annotation declarations - const auto *Annotation = AnnotatedCode.getFunction("llvm.var.annotation"); - if (Annotation) { + for (const auto *Annotation : VarAnnotations) { for (const auto *VarAnnotationUser : Annotation->users()) { if (const auto *AnnotationCall = llvm::dyn_cast(VarAnnotationUser)) { @@ -221,14 +233,6 @@ LLVMTaintConfig::LLVMTaintConfig(const psr::LLVMProjectIRDB &AnnotatedCode) { } } - std::vector PtrAnnotations{}; - PtrAnnotations.reserve(AnnotatedCode.getNumFunctions()); - for (const auto *F : AnnotatedCode.getAllFunctions()) { - if (F->getName().startswith("llvm.ptr.annotation")) { - PtrAnnotations.push_back(F); - } - } - for (const auto *Annotation : PtrAnnotations) { for (const auto *VarAnnotationUser : Annotation->users()) { if (const auto *AnnotationCall = diff --git a/lib/PhasarLLVM/Utils/Annotation.cpp b/lib/PhasarLLVM/Utils/Annotation.cpp index 0883217d98..219e0e5b71 100644 --- a/lib/PhasarLLVM/Utils/Annotation.cpp +++ b/lib/PhasarLLVM/Utils/Annotation.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" @@ -31,7 +32,7 @@ VarAnnotation::VarAnnotation(const llvm::CallBase *AnnotationCall) noexcept : AnnotationCall(AnnotationCall) { [[maybe_unused]] auto *Callee = AnnotationCall->getCalledFunction(); assert(Callee && Callee->hasName() && - (Callee->getName() == "llvm.var.annotation" || + (Callee->getName().starts_with("llvm.var.annotation") || Callee->getName().startswith("llvm.ptr.annotation"))); } diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp index 5e0c1f890c..bacb4008b8 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp @@ -366,7 +366,11 @@ TEST(DBTHTest, BasicTHReconstruction_12_b) { // check for all subtypes const auto &SubTypes = DBTH.getSubTypes(BaseType); +#if LLVM_VERSION_MAJOR < 16 + // In LLVM 16, the metadata is pruned to the relations that are actually + // *used* in the code EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +#endif const auto &SubTypesChild = DBTH.getSubTypes(ChildType); EXPECT_TRUE(SubTypesChild.find(ChildsChildType) != SubTypesChild.end()); } @@ -1097,12 +1101,16 @@ TEST(DBTHTest, TransitivelyReachableTypes_12_b) { auto ReachableTypesChild = DBTH.getSubTypes(ChildType); auto ReachableTypesChildsChild = DBTH.getSubTypes(ChildsChildType); - EXPECT_EQ(ReachableTypesBase.size(), 3U); + EXPECT_EQ(ReachableTypesBase.size(), LLVM_VERSION_MAJOR < 16 ? 3U : 1U); EXPECT_EQ(ReachableTypesChild.size(), 2U); EXPECT_EQ(ReachableTypesChildsChild.size(), 1U); EXPECT_TRUE(ReachableTypesBase.count(BaseType)); +#if LLVM_VERSION_MAJOR < 16 + // In LLVM 16, the metadata is pruned to the relations that are actually + // *used* in the code EXPECT_TRUE(ReachableTypesBase.count(ChildType)); EXPECT_TRUE(ReachableTypesBase.count(ChildsChildType)); +#endif EXPECT_FALSE(ReachableTypesChild.count(BaseType)); EXPECT_TRUE(ReachableTypesChild.count(ChildType)); EXPECT_TRUE(ReachableTypesChild.count(ChildsChildType)); diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index c13ca7f8d4..9cfafd1cb8 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -363,7 +363,7 @@ testingLocInIR(TestingSrcLocation Loc, }, [&](RetVal R) -> llvm::Value const * { const auto *InFun = GetFunction(R.InFunction); - for (const auto &BB : llvm::reverse(InFun->getBasicBlockList())) { + for (const auto &BB : llvm::reverse(*InFun)) { if (const auto *Ret = llvm::dyn_cast(BB.getTerminator())) { return Ret->getReturnValue(); @@ -374,7 +374,7 @@ testingLocInIR(TestingSrcLocation Loc, }, [&](RetStmt R) -> llvm::Value const * { const auto *InFun = GetFunction(R.InFunction); - for (const auto &BB : llvm::reverse(InFun->getBasicBlockList())) { + for (const auto &BB : llvm::reverse(*InFun)) { if (const auto *Ret = llvm::dyn_cast(BB.getTerminator())) { return Ret; diff --git a/utils/InstallAptDependencies.sh b/utils/InstallAptDependencies.sh index 3376cfcd1a..1b5c7bf371 100755 --- a/utils/InstallAptDependencies.sh +++ b/utils/InstallAptDependencies.sh @@ -7,7 +7,7 @@ if printf "%s\n" "$@" | grep -Eqe '^--noninteractive|-ni$'; then else readonly noninteractive="false" fi -readonly LLVM_IR_VERSION=15 +readonly LLVM_IR_VERSION=16 additional_dependencies=("$@") (