123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- #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);
- }
- std::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 std::nullopt;
- }
- std::optional<InstantiatedRelation>
- 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<InstantiatedAttr>
- instantiateExternalAttribute(ExternalAttribute EAttr, CallBase &Call) {
- auto Value = instantiateInterfaceValue(EAttr.IValue, Call);
- if (!Value)
- return std::nullopt;
- return InstantiatedAttr{*Value, EAttr.Attr};
- }
- }
- }
|