diff --git a/CMakeLists.txt b/CMakeLists.txt index 1692878e08..fe8e3a923b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,6 +272,9 @@ include(add_nlohmann_json) add_nlohmann_json() add_json_schema_validator() +# TBB +find_package(TBB) # needed by GCC + # Coverage if (CODE_COVERAGE) set(CODE_COVERAGE_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/code-coverage.cmake") @@ -426,6 +429,9 @@ target_sources(phasar_interface INTERFACE BASE_DIRS "${PHASAR_SRC_DIR}/include" "${PHASAR_BINARY_DIR}/include" FILES ${PHASAR_PUBLIC_HEADERS} "${PHASAR_BINARY_DIR}/include/phasar/Config/phasar-config.h" ) +if (TARGET TBB::tbb) + target_link_libraries(phasar_interface INTERFACE TBB::tbb) # needed by GCC +endif() # Some preprocessor symbols that need to be available in phasar sources, but should not be installed add_cxx_compile_definitions(PHASAR_SRC_DIR="${CMAKE_SOURCE_DIR}") diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMRawAAResults.h b/include/phasar/PhasarLLVM/Pointer/LLVMRawAAResults.h index 4a436ad382..d4460a880e 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMRawAAResults.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMRawAAResults.h @@ -13,6 +13,7 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Pointer/AliasResult.h" #include "phasar/Pointer/RawAAResult.h" +#include "phasar/Utils/MapUtils.h" #include "phasar/Utils/NonNullPtr.h" #include "llvm/IR/Instructions.h" diff --git a/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h b/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h index 06fa418a0d..6ff02c3871 100644 --- a/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h +++ b/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h @@ -65,9 +65,9 @@ struct DebugLocation { /// \brief A struct that contains information about a source code line, function /// name, file name corresponding to the IR statement. struct SourceCodeInfo { - std::string SourceCodeLine; - std::string SourceCodeFilename; - std::string SourceCodeFunctionName; + std::string SourceCodeLine{}; + std::string SourceCodeFilename{}; + std::string SourceCodeFunctionName{}; unsigned Line = 0; unsigned Column = 0; diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp index 93ae6188ba..daa3806773 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp @@ -111,6 +111,7 @@ auto detail::LLVMBasedCFGImpl::getSuccsOfImpl(n_t I) const [IgnoreDbgInstructions{IgnoreDbgInstructions}]( const llvm::BasicBlock *BB) { const llvm::Instruction *Succ = &BB->front(); + (void)IgnoreDbgInstructions; #if LLVM_VERSION_MAJOR <= 18 if (IgnoreDbgInstructions && llvm::isa(Succ)) { Succ = Succ->getNextNonDebugInstruction( diff --git a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp index b35c6b3aba..a131db273b 100644 --- a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp +++ b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp @@ -46,6 +46,23 @@ using namespace psr; +// If mem2reg is not activated, formal parameters will be stored in +// registers at the beginning of function call. Debug info linked to +// those allocas instead of the arguments itself. +static const llvm::AllocaInst *getArgumentAlloca(const llvm::Argument *Arg) { + for (const auto *User : Arg->users()) { + if (const auto *Store = llvm::dyn_cast(User)) { + if (Store->getValueOperand() == Arg) { + if (const auto *Alloca = + llvm::dyn_cast(Store->getPointerOperand())) { + return Alloca; + } + } + } + } + return nullptr; +} + static llvm::DbgVariableIntrinsic *getDbgVarIntrinsic(const llvm::Value *V) { if (auto *VAM = llvm::ValueAsMetadata::getIfExists( const_cast(V))) { // NOLINT FIXME when LLVM supports it @@ -57,16 +74,8 @@ static llvm::DbgVariableIntrinsic *getDbgVarIntrinsic(const llvm::Value *V) { } } } else if (const auto *Arg = llvm::dyn_cast(V)) { - /* If mem2reg is not activated, formal parameters will be stored in - * registers at the beginning of function call. Debug info will be linked to - * those alloca's instead of the arguments itself. */ - for (const auto *User : Arg->users()) { - if (const auto *Store = llvm::dyn_cast(User)) { - if (Store->getValueOperand() == Arg && - llvm::isa(Store->getPointerOperand())) { - return getDbgVarIntrinsic(Store->getPointerOperand()); - } - } + if (const auto *Alloca = getArgumentAlloca(Arg)) { + return getDbgVarIntrinsic(Alloca); } } return nullptr; @@ -114,6 +123,20 @@ static llvm::DISubprogram *getDISubprogram(const llvm::Value *V) { return nullptr; } +#if LLVM_VERSION_MAJOR > 18 +static llvm::DILocation *findLocInDbgRecords(const llvm::Value *V) { + if (auto *VAM = llvm::ValueAsMetadata::getIfExists( + const_cast(V))) { // NOLINT FIXME when LLVM supports it + for (const auto &DbgRec : VAM->getAllDbgVariableRecordUsers()) { + if (const auto &Loc = DbgRec->getDebugLoc()) { + return Loc; + } + } + } + return nullptr; +} +#endif + llvm::DILocation *psr::getDILocation(const llvm::Value *V) { // Arguments and Instruction such as AllocaInst @@ -123,31 +146,28 @@ llvm::DILocation *psr::getDILocation(const llvm::Value *V) { } #if LLVM_VERSION_MAJOR > 18 - const auto FindLocInDbgRecords = - [](const llvm::Value *Val) -> llvm::DILocation * { - if (auto *VAM = llvm::ValueAsMetadata::getIfExists( - const_cast(Val))) { - for (const auto &DbgRec : VAM->getAllDbgVariableRecordUsers()) { - if (const auto &Loc = DbgRec->getDebugLoc()) { - return Loc; - } - } - } - return nullptr; - }; - if (const auto *Store = llvm::dyn_cast(I); Store && llvm::isa(Store->getValueOperand())) { // For each argument, clang creates an alloca + store; both have no !dbg // metadata attached - return FindLocInDbgRecords(Store->getPointerOperand()); + return findLocInDbgRecords(Store->getPointerOperand()); } if (llvm::isa(I)) { - return FindLocInDbgRecords(I); + return findLocInDbgRecords(I); } #endif } +#if LLVM_VERSION_MAJOR > 18 + if (const auto *Arg = llvm::dyn_cast(V)) { + if (const auto *Alloca = getArgumentAlloca(Arg)) { + if (auto *Loc = findLocInDbgRecords(Alloca)) { + return Loc; + } + } + } +#endif + if (auto *DbgIntr = getDbgVarIntrinsic(V)) { if (auto *MN = DbgIntr->getMetadata(llvm::LLVMContext::MD_dbg)) { return llvm::dyn_cast(MN); @@ -177,7 +197,8 @@ static llvm::DIType *getVarTypeFromIRImpl(const llvm::Value *V) { if (const auto *Call = llvm::dyn_cast(V)) { if (const auto *Callee = llvm::dyn_cast( Call->getCalledOperand()->stripPointerCastsAndAliases())) { - if (auto *DICallee = Callee->getSubprogram()) { + if (auto *DICallee = Callee->getSubprogram(); + DICallee && DICallee->getType()) { auto Types = DICallee->getType()->getTypeArray(); if (Types.size()) { return Types[0]; @@ -304,7 +325,7 @@ std::string psr::getFunctionNameFromIR(const llvm::Value *V) { if (const auto *I = llvm::dyn_cast(V)) { return I->getFunction()->getName().str(); } - return ""; + return {}; } std::string psr::getFilePathFromIR(const llvm::Value *V) { @@ -312,10 +333,10 @@ std::string psr::getFilePathFromIR(const llvm::Value *V) { return getFilePathFromIR(DIF); } /* As a fallback solution, we will return 'source_filename' info from - * module. However, it is not guaranteed to contain the absoult path, and it + * module. However, it is not guaranteed to contain the absoulte path, and it * will return 'llvm-link' for linked modules. */ - if (const auto *F = llvm::dyn_cast(V)) { - return F->getParent()->getSourceFileName(); + if (const auto *GO = llvm::dyn_cast(V)) { + return GO->getParent()->getSourceFileName(); } if (const auto *Arg = llvm::dyn_cast(V)) { return Arg->getParent()->getParent()->getSourceFileName(); @@ -328,6 +349,9 @@ std::string psr::getFilePathFromIR(const llvm::Value *V) { } std::string psr::getFilePathFromIR(const llvm::DIFile *DIF) { + if (!DIF) { + return {}; + } auto FileName = DIF->getFilename(); auto DirName = DIF->getDirectory(); @@ -347,45 +371,37 @@ std::string psr::getFilePathFromIR(const llvm::DIFile *DIF) { return FileName.str(); } -const llvm::DIFile *psr::getDIFileFromIR(const llvm::Value *V) { - if (const auto *GO = llvm::dyn_cast(V)) { - if (auto *MN = GO->getMetadata(llvm::LLVMContext::MD_dbg)) { - if (auto *Subpr = llvm::dyn_cast(MN)) { - return Subpr->getFile(); - } - if (auto *GVExpr = llvm::dyn_cast(MN)) { - return GVExpr->getVariable()->getFile(); - } - } - } else if (const auto *Arg = llvm::dyn_cast(V)) { - if (auto *LocVar = getDILocalVariable(Arg)) { - return LocVar->getFile(); - } - } else if (const auto *I = llvm::dyn_cast(V)) { - if (I->isUsedByMetadata()) { - if (auto *LocVar = getDILocalVariable(I)) { - return LocVar->getFile(); - } - } else if (I->getMetadata(llvm::LLVMContext::MD_dbg)) { - return I->getDebugLoc()->getFile(); - } - if (const auto *DIFun = I->getFunction()->getSubprogram()) { - return DIFun->getFile(); - } +static llvm::DISubprogram *getEnclosingSubprogram(const llvm::Value *V) { + if (const auto *I = llvm::dyn_cast(V)) { + return I->getFunction()->getSubprogram(); + } + if (const auto *Arg = llvm::dyn_cast(V)) { + return Arg->getParent()->getSubprogram(); } return nullptr; } -std::string psr::getDirectoryFromIR(const llvm::Value *V) { +const llvm::DIFile *psr::getDIFileFromIR(const llvm::Value *V) { // Argument and Instruction if (auto *DILoc = getDILocation(V)) { - return DILoc->getDirectory().str(); + return DILoc->getFile(); + } + if (auto *DISubpr = + getEnclosingSubprogram(V)) { // Instruction/Argument fallback + return DISubpr->getFile(); } if (auto *DISubpr = getDISubprogram(V)) { // Function - return DISubpr->getDirectory().str(); + return DISubpr->getFile(); } if (auto *DIGV = getDIGlobalVariable(V)) { // Globals - return DIGV->getDirectory().str(); + return DIGV->getFile(); + } + return nullptr; +} + +std::string psr::getDirectoryFromIR(const llvm::Value *V) { + if (const auto *DIF = getDIFileFromIR(V)) { + return DIF->getDirectory().str(); } return ""; } @@ -395,6 +411,10 @@ unsigned int psr::getLineFromIR(const llvm::Value *V) { if (auto *DILoc = getDILocation(V)) { return DILoc->getLine(); } + if (auto *DISubpr = + getEnclosingSubprogram(V)) { // Instruction/Argument fallback + return DISubpr->getLine(); + } if (auto *DISubpr = getDISubprogram(V)) { // Function return DISubpr->getLine(); } @@ -417,13 +437,10 @@ std::pair psr::getLineAndColFromIR(const llvm::Value *V) { if (auto *DILoc = getDILocation(V)) { return {DILoc->getLine(), DILoc->getColumn()}; } - - if (const auto *I = llvm::dyn_cast(V)) { - if (const auto *DIFun = I->getFunction()->getSubprogram()) { - return {DIFun->getLine(), 0}; - } + if (auto *DISubpr = + getEnclosingSubprogram(V)) { // Instruction/Argument fallback + return {DISubpr->getLine(), 0}; } - if (auto *DISubpr = getDISubprogram(V)) { // Function return {DISubpr->getLine(), 0}; } @@ -524,31 +541,53 @@ void psr::to_json(nlohmann::json &J, const SourceCodeInfo &Info) { } SourceCodeInfo psr::getSrcCodeInfoFromIR(const llvm::Value *V) { - return SourceCodeInfo{ - getSrcCodeFromIR(V), - getFilePathFromIR(V), - llvm::demangle(getFunctionNameFromIR(V)), - getLineFromIR(V), - getColumnFromIR(V), + auto Loc = getDebugLocation(V); + auto FName = llvm::demangle(getFunctionNameFromIR(V)); + if (!Loc) { + return { + .SourceCodeFilename = getFilePathFromIR(V), + .SourceCodeFunctionName = std::move(FName), + }; + } + return { + .SourceCodeLine = getSrcCodeFromIR(*Loc), + .SourceCodeFilename = getFilePathFromIR(Loc->File), + .SourceCodeFunctionName = std::move(FName), + .Line = Loc->Line, + .Column = Loc->Column, }; } std::optional psr::getDebugLocation(const llvm::Value *V) { // Argument and Instruction if (auto *DILoc = getDILocation(V)) { - return DebugLocation{DILoc->getLine(), DILoc->getColumn(), - DILoc->getFile()}; + return DebugLocation{ + .Line = DILoc->getLine(), + .Column = DILoc->getColumn(), + .File = DILoc->getFile(), + }; } - if (const auto *I = llvm::dyn_cast(V)) { - if (const auto *DIFun = I->getFunction()->getSubprogram()) { - return DebugLocation{DIFun->getLine(), 0, DIFun->getFile()}; - } + if (auto *DIFun = + getEnclosingSubprogram(V)) { // Instruction/Argument fallback + return DebugLocation{ + .Line = DIFun->getLine(), + .Column = 0, + .File = DIFun->getFile(), + }; } if (auto *DISubpr = getDISubprogram(V)) { // Function - return DebugLocation{DISubpr->getLine(), 0, DISubpr->getFile()}; + return DebugLocation{ + .Line = DISubpr->getLine(), + .Column = 0, + .File = DISubpr->getFile(), + }; } if (auto *DIGV = getDIGlobalVariable(V)) { // Globals - return DebugLocation{DIGV->getLine(), 0, DIGV->getFile()}; + return DebugLocation{ + .Line = DIGV->getLine(), + .Column = 0, + .File = DIGV->getFile(), + }; } return std::nullopt; diff --git a/tools/ptaben/SupportedAnalysisTypes.h b/tools/ptaben/SupportedAnalysisTypes.h index decdecea25..ea2414d59e 100644 --- a/tools/ptaben/SupportedAnalysisTypes.h +++ b/tools/ptaben/SupportedAnalysisTypes.h @@ -10,6 +10,7 @@ *****************************************************************************/ #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" #include @@ -37,6 +38,7 @@ constexpr llvm::StringRef to_string(SupportedAnalysisTypes AT) noexcept { return #NAME "Result"; #include "SupportedAnalysisTypes.def" } + llvm_unreachable("All analysis types handled in the switch above"); // for gcc } } // namespace psr::ptaben diff --git a/tools/ptaben/ptaben_benchmark_tool.cpp b/tools/ptaben/ptaben_benchmark_tool.cpp index 4ed492a82f..6f7d5b8a0a 100644 --- a/tools/ptaben/ptaben_benchmark_tool.cpp +++ b/tools/ptaben/ptaben_benchmark_tool.cpp @@ -90,6 +90,7 @@ ufaaTypeFromSupported(SupportedAnalysisTypes AT) { case SupportedAnalysisTypes::UFAABotCtxInd: return psr::UnionFindAliasAnalysisType::BotCtxIndSens; } + llvm_unreachable("All analysis types handled in the switch above"); // for gcc } static psr::AliasResult