#include "AliasAnalysisSummary.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Type.h" #include "llvm/Support/Compiler.h" namespace llvm { namespace cflaa { namespace { LLVM_CONSTEXPR unsigned AttrEscapedIndex = 0; LLVM_CONSTEXPR unsigned AttrUnknownIndex = 1; LLVM_CONSTEXPR unsigned AttrGlobalIndex = 2; LLVM_CONSTEXPR unsigned AttrCallerIndex = 3; LLVM_CONSTEXPR unsigned AttrFirstArgIndex = 4; LLVM_CONSTEXPR unsigned AttrLastArgIndex = NumAliasAttrs; LLVM_CONSTEXPR unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex; // NOTE: These aren't AliasAttrs because bitsets don't have a constexpr // ctor for some versions of MSVC that we support. We could maybe refactor, // but... using AliasAttr = unsigned; LLVM_CONSTEXPR AliasAttr AttrNone = 0; LLVM_CONSTEXPR AliasAttr AttrEscaped = 1 << AttrEscapedIndex; LLVM_CONSTEXPR AliasAttr AttrUnknown = 1 << AttrUnknownIndex; LLVM_CONSTEXPR AliasAttr AttrGlobal = 1 << AttrGlobalIndex; LLVM_CONSTEXPR AliasAttr AttrCaller = 1 << AttrCallerIndex; LLVM_CONSTEXPR AliasAttr ExternalAttrMask = AttrEscaped | AttrUnknown | AttrGlobal; } 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<GlobalValue>(Val)) return AttrGlobal; if (auto *Arg = dyn_cast<Argument>(&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); } Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue IValue, CallSite CS) { auto Index = IValue.Index; auto Value = (Index == 0) ? CS.getInstruction() : CS.getArgument(Index - 1); if (Value->getType()->isPointerTy()) return InstantiatedValue{Value, IValue.DerefLevel}; return None; } Optional<InstantiatedRelation> instantiateExternalRelation(ExternalRelation ERelation, CallSite CS) { auto From = instantiateInterfaceValue(ERelation.From, CS); if (!From) return None; auto To = instantiateInterfaceValue(ERelation.To, CS); if (!To) return None; return InstantiatedRelation{*From, *To}; } Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr, CallSite CS) { auto Value = instantiateInterfaceValue(EAttr.IValue, CS); if (!Value) return None; return InstantiatedAttr{*Value, EAttr.Attr}; } } }