| #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; |
| } |
| |
| 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, |
| 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 None; |
| } |
| |
| Optional<InstantiatedRelation> |
| instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call) { |
| auto From = instantiateInterfaceValue(ERelation.From, Call); |
| if (!From) |
| return None; |
| auto To = instantiateInterfaceValue(ERelation.To, Call); |
| if (!To) |
| return None; |
| return InstantiatedRelation{*From, *To, ERelation.Offset}; |
| } |
| |
| Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr, |
| CallBase &Call) { |
| auto Value = instantiateInterfaceValue(EAttr.IValue, Call); |
| if (!Value) |
| return None; |
| return InstantiatedAttr{*Value, EAttr.Attr}; |
| } |
| } |
| } |