From d6ef35600e7093e06dfc7a3fb5ce9a69232ca74e Mon Sep 17 00:00:00 2001 From: Marek Chalupa Date: Mon, 20 Jun 2022 13:36:30 +0200 Subject: [PATCH] llvm-slicer-crit: improve the precision of matching without PTA We can handle also constant expressions and global variables. --- tools/llvm-slicer-crit.cpp | 51 +++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/tools/llvm-slicer-crit.cpp b/tools/llvm-slicer-crit.cpp index d9f2294e5..f7eaf7450 100644 --- a/tools/llvm-slicer-crit.cpp +++ b/tools/llvm-slicer-crit.cpp @@ -38,15 +38,49 @@ static inline bool isNumber(const std::string &s) { } static inline bool mayBeTheVar(const llvm::Value *val, const std::string &var) { + // global variables have names, just compare it + if (auto *G = llvm::dyn_cast(val)) { + return G->getName() == var; + } + + // for other cases, we must relay on the information about allocas auto name = valuesToVariables.find(val); if (name != valuesToVariables.end() && name->second != var) { return false; } + // either the var matches or we do not know the var, // which we must take as a match return true; } +static llvm::Value *constExprVar(const llvm::ConstantExpr *CE) { + using namespace llvm; + Value *var = nullptr; + Instruction *Inst = CE->getAsInstruction(); + + switch (Inst->getOpcode()) { + case Instruction::GetElementPtr: + var = cast(Inst)->getPointerOperand(); + break; + case Instruction::BitCast: + var = Inst->getOperand(0); + break; + default: + break; + } + +#if LLVM_VERSION_MAJOR < 5 + delete Inst; +#else + Inst->deleteValue(); +#endif + + if (var && isa(var)) + var = constExprVar(cast(var)); + return var; +} + static bool usesTheVariable(const llvm::Instruction &I, const std::string &var, bool isglobal = false, LLVMPointerAnalysis *pta = nullptr) { @@ -56,17 +90,26 @@ static bool usesTheVariable(const llvm::Instruction &I, const std::string &var, if (!pta) { // try basic cases that we can decide without PTA using namespace llvm; + const Value *operand = nullptr; if (auto *S = dyn_cast(&I)) { auto *A = S->getPointerOperand()->stripPointerCasts(); - if (isa(A) && !mayBeTheVar(A, var)) { - return false; + if (auto *C = dyn_cast(A)) { + operand = constExprVar(C); + } else if ((isa(A) || isa(A))) { + operand = A; } } else if (auto *L = dyn_cast(&I)) { auto *A = L->getPointerOperand()->stripPointerCasts(); - if (isa(A) && !mayBeTheVar(A, var)) { - return false; + if (auto *C = dyn_cast(A)) { + operand = constExprVar(C); + } else if ((isa(A) || isa(A))) { + operand = A; } } + + if (operand && !mayBeTheVar(operand, var)) { + return false; + } return true; }