forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			266 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
//=====- CFLSummary.h - Abstract stratified sets implementation. --------=====//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
/// \file
 | 
						|
/// This file defines various utility types and functions useful to
 | 
						|
/// summary-based alias analysis.
 | 
						|
///
 | 
						|
/// Summary-based analysis, also known as bottom-up analysis, is a style of
 | 
						|
/// interprocedrual static analysis that tries to analyze the callees before the
 | 
						|
/// callers get analyzed. The key idea of summary-based analysis is to first
 | 
						|
/// process each function independently, outline its behavior in a condensed
 | 
						|
/// summary, and then instantiate the summary at the callsite when the said
 | 
						|
/// function is called elsewhere. This is often in contrast to another style
 | 
						|
/// called top-down analysis, in which callers are always analyzed first before
 | 
						|
/// the callees.
 | 
						|
///
 | 
						|
/// In a summary-based analysis, functions must be examined independently and
 | 
						|
/// out-of-context. We have no information on the state of the memory, the
 | 
						|
/// arguments, the global values, and anything else external to the function. To
 | 
						|
/// carry out the analysis conservative assumptions have to be made about those
 | 
						|
/// external states. In exchange for the potential loss of precision, the
 | 
						|
/// summary we obtain this way is highly reusable, which makes the analysis
 | 
						|
/// easier to scale to large programs even if carried out context-sensitively.
 | 
						|
///
 | 
						|
/// Currently, all CFL-based alias analyses adopt the summary-based approach
 | 
						|
/// and therefore heavily rely on this header.
 | 
						|
///
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#ifndef LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
 | 
						|
#define LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
 | 
						|
 | 
						|
#include "llvm/ADT/DenseMapInfo.h"
 | 
						|
#include "llvm/ADT/Optional.h"
 | 
						|
#include "llvm/ADT/SmallVector.h"
 | 
						|
#include "llvm/IR/InstrTypes.h"
 | 
						|
#include <bitset>
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
namespace cflaa {
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// AliasAttr related stuffs
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
/// The number of attributes that AliasAttr should contain. Attributes are
 | 
						|
/// described below, and 32 was an arbitrary choice because it fits nicely in 32
 | 
						|
/// bits (because we use a bitset for AliasAttr).
 | 
						|
static const unsigned NumAliasAttrs = 32;
 | 
						|
 | 
						|
/// These are attributes that an alias analysis can use to mark certain special
 | 
						|
/// properties of a given pointer. Refer to the related functions below to see
 | 
						|
/// what kinds of attributes are currently defined.
 | 
						|
typedef std::bitset<NumAliasAttrs> AliasAttrs;
 | 
						|
 | 
						|
/// Attr represent whether the said pointer comes from an unknown source
 | 
						|
/// (such as opaque memory or an integer cast).
 | 
						|
AliasAttrs getAttrNone();
 | 
						|
 | 
						|
/// AttrUnknown represent whether the said pointer comes from a source not known
 | 
						|
/// to alias analyses (such as opaque memory or an integer cast).
 | 
						|
AliasAttrs getAttrUnknown();
 | 
						|
bool hasUnknownAttr(AliasAttrs);
 | 
						|
 | 
						|
/// AttrCaller represent whether the said pointer comes from a source not known
 | 
						|
/// to the current function but known to the caller. Values pointed to by the
 | 
						|
/// arguments of the current function have this attribute set
 | 
						|
AliasAttrs getAttrCaller();
 | 
						|
bool hasCallerAttr(AliasAttrs);
 | 
						|
bool hasUnknownOrCallerAttr(AliasAttrs);
 | 
						|
 | 
						|
/// AttrEscaped represent whether the said pointer comes from a known source but
 | 
						|
/// escapes to the unknown world (e.g. casted to an integer, or passed as an
 | 
						|
/// argument to opaque function). Unlike non-escaped pointers, escaped ones may
 | 
						|
/// alias pointers coming from unknown sources.
 | 
						|
AliasAttrs getAttrEscaped();
 | 
						|
bool hasEscapedAttr(AliasAttrs);
 | 
						|
 | 
						|
/// AttrGlobal represent whether the said pointer is a global value.
 | 
						|
/// AttrArg represent whether the said pointer is an argument, and if so, what
 | 
						|
/// index the argument has.
 | 
						|
AliasAttrs getGlobalOrArgAttrFromValue(const Value &);
 | 
						|
bool isGlobalOrArgAttr(AliasAttrs);
 | 
						|
 | 
						|
/// Given an AliasAttrs, return a new AliasAttrs that only contains attributes
 | 
						|
/// meaningful to the caller. This function is primarily used for
 | 
						|
/// interprocedural analysis
 | 
						|
/// Currently, externally visible AliasAttrs include AttrUnknown, AttrGlobal,
 | 
						|
/// and AttrEscaped
 | 
						|
AliasAttrs getExternallyVisibleAttrs(AliasAttrs);
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// Function summary related stuffs
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
/// The maximum number of arguments we can put into a summary.
 | 
						|
static const unsigned MaxSupportedArgsInSummary = 50;
 | 
						|
 | 
						|
/// We use InterfaceValue to describe parameters/return value, as well as
 | 
						|
/// potential memory locations that are pointed to by parameters/return value,
 | 
						|
/// of a function.
 | 
						|
/// Index is an integer which represents a single parameter or a return value.
 | 
						|
/// When the index is 0, it refers to the return value. Non-zero index i refers
 | 
						|
/// to the i-th parameter.
 | 
						|
/// DerefLevel indicates the number of dereferences one must perform on the
 | 
						|
/// parameter/return value to get this InterfaceValue.
 | 
						|
struct InterfaceValue {
 | 
						|
  unsigned Index;
 | 
						|
  unsigned DerefLevel;
 | 
						|
};
 | 
						|
 | 
						|
inline bool operator==(InterfaceValue LHS, InterfaceValue RHS) {
 | 
						|
  return LHS.Index == RHS.Index && LHS.DerefLevel == RHS.DerefLevel;
 | 
						|
}
 | 
						|
inline bool operator!=(InterfaceValue LHS, InterfaceValue RHS) {
 | 
						|
  return !(LHS == RHS);
 | 
						|
}
 | 
						|
inline bool operator<(InterfaceValue LHS, InterfaceValue RHS) {
 | 
						|
  return LHS.Index < RHS.Index ||
 | 
						|
         (LHS.Index == RHS.Index && LHS.DerefLevel < RHS.DerefLevel);
 | 
						|
}
 | 
						|
inline bool operator>(InterfaceValue LHS, InterfaceValue RHS) {
 | 
						|
  return RHS < LHS;
 | 
						|
}
 | 
						|
inline bool operator<=(InterfaceValue LHS, InterfaceValue RHS) {
 | 
						|
  return !(RHS < LHS);
 | 
						|
}
 | 
						|
inline bool operator>=(InterfaceValue LHS, InterfaceValue RHS) {
 | 
						|
  return !(LHS < RHS);
 | 
						|
}
 | 
						|
 | 
						|
// We use UnknownOffset to represent pointer offsets that cannot be determined
 | 
						|
// at compile time. Note that MemoryLocation::UnknownSize cannot be used here
 | 
						|
// because we require a signed value.
 | 
						|
static const int64_t UnknownOffset = INT64_MAX;
 | 
						|
 | 
						|
inline int64_t addOffset(int64_t LHS, int64_t RHS) {
 | 
						|
  if (LHS == UnknownOffset || RHS == UnknownOffset)
 | 
						|
    return UnknownOffset;
 | 
						|
  // FIXME: Do we need to guard against integer overflow here?
 | 
						|
  return LHS + RHS;
 | 
						|
}
 | 
						|
 | 
						|
/// We use ExternalRelation to describe an externally visible aliasing relations
 | 
						|
/// between parameters/return value of a function.
 | 
						|
struct ExternalRelation {
 | 
						|
  InterfaceValue From, To;
 | 
						|
  int64_t Offset;
 | 
						|
};
 | 
						|
 | 
						|
inline bool operator==(ExternalRelation LHS, ExternalRelation RHS) {
 | 
						|
  return LHS.From == RHS.From && LHS.To == RHS.To && LHS.Offset == RHS.Offset;
 | 
						|
}
 | 
						|
inline bool operator!=(ExternalRelation LHS, ExternalRelation RHS) {
 | 
						|
  return !(LHS == RHS);
 | 
						|
}
 | 
						|
inline bool operator<(ExternalRelation LHS, ExternalRelation RHS) {
 | 
						|
  if (LHS.From < RHS.From)
 | 
						|
    return true;
 | 
						|
  if (LHS.From > RHS.From)
 | 
						|
    return false;
 | 
						|
  if (LHS.To < RHS.To)
 | 
						|
    return true;
 | 
						|
  if (LHS.To > RHS.To)
 | 
						|
    return false;
 | 
						|
  return LHS.Offset < RHS.Offset;
 | 
						|
}
 | 
						|
inline bool operator>(ExternalRelation LHS, ExternalRelation RHS) {
 | 
						|
  return RHS < LHS;
 | 
						|
}
 | 
						|
inline bool operator<=(ExternalRelation LHS, ExternalRelation RHS) {
 | 
						|
  return !(RHS < LHS);
 | 
						|
}
 | 
						|
inline bool operator>=(ExternalRelation LHS, ExternalRelation RHS) {
 | 
						|
  return !(LHS < RHS);
 | 
						|
}
 | 
						|
 | 
						|
/// We use ExternalAttribute to describe an externally visible AliasAttrs
 | 
						|
/// for parameters/return value.
 | 
						|
struct ExternalAttribute {
 | 
						|
  InterfaceValue IValue;
 | 
						|
  AliasAttrs Attr;
 | 
						|
};
 | 
						|
 | 
						|
/// AliasSummary is just a collection of ExternalRelation and ExternalAttribute
 | 
						|
struct AliasSummary {
 | 
						|
  // RetParamRelations is a collection of ExternalRelations.
 | 
						|
  SmallVector<ExternalRelation, 8> RetParamRelations;
 | 
						|
 | 
						|
  // RetParamAttributes is a collection of ExternalAttributes.
 | 
						|
  SmallVector<ExternalAttribute, 8> RetParamAttributes;
 | 
						|
};
 | 
						|
 | 
						|
/// This is the result of instantiating InterfaceValue at a particular call
 | 
						|
struct InstantiatedValue {
 | 
						|
  Value *Val;
 | 
						|
  unsigned DerefLevel;
 | 
						|
};
 | 
						|
Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue IValue,
 | 
						|
                                                      CallBase &Call);
 | 
						|
 | 
						|
inline bool operator==(InstantiatedValue LHS, InstantiatedValue RHS) {
 | 
						|
  return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel;
 | 
						|
}
 | 
						|
inline bool operator!=(InstantiatedValue LHS, InstantiatedValue RHS) {
 | 
						|
  return !(LHS == RHS);
 | 
						|
}
 | 
						|
inline bool operator<(InstantiatedValue LHS, InstantiatedValue RHS) {
 | 
						|
  return std::less<Value *>()(LHS.Val, RHS.Val) ||
 | 
						|
         (LHS.Val == RHS.Val && LHS.DerefLevel < RHS.DerefLevel);
 | 
						|
}
 | 
						|
inline bool operator>(InstantiatedValue LHS, InstantiatedValue RHS) {
 | 
						|
  return RHS < LHS;
 | 
						|
}
 | 
						|
inline bool operator<=(InstantiatedValue LHS, InstantiatedValue RHS) {
 | 
						|
  return !(RHS < LHS);
 | 
						|
}
 | 
						|
inline bool operator>=(InstantiatedValue LHS, InstantiatedValue RHS) {
 | 
						|
  return !(LHS < RHS);
 | 
						|
}
 | 
						|
 | 
						|
/// This is the result of instantiating ExternalRelation at a particular
 | 
						|
/// callsite
 | 
						|
struct InstantiatedRelation {
 | 
						|
  InstantiatedValue From, To;
 | 
						|
  int64_t Offset;
 | 
						|
};
 | 
						|
Optional<InstantiatedRelation>
 | 
						|
instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call);
 | 
						|
 | 
						|
/// This is the result of instantiating ExternalAttribute at a particular
 | 
						|
/// callsite
 | 
						|
struct InstantiatedAttr {
 | 
						|
  InstantiatedValue IValue;
 | 
						|
  AliasAttrs Attr;
 | 
						|
};
 | 
						|
Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr,
 | 
						|
                                                        CallBase &Call);
 | 
						|
}
 | 
						|
 | 
						|
template <> struct DenseMapInfo<cflaa::InstantiatedValue> {
 | 
						|
  static inline cflaa::InstantiatedValue getEmptyKey() {
 | 
						|
    return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getEmptyKey(),
 | 
						|
                                    DenseMapInfo<unsigned>::getEmptyKey()};
 | 
						|
  }
 | 
						|
  static inline cflaa::InstantiatedValue getTombstoneKey() {
 | 
						|
    return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getTombstoneKey(),
 | 
						|
                                    DenseMapInfo<unsigned>::getTombstoneKey()};
 | 
						|
  }
 | 
						|
  static unsigned getHashValue(const cflaa::InstantiatedValue &IV) {
 | 
						|
    return DenseMapInfo<std::pair<Value *, unsigned>>::getHashValue(
 | 
						|
        std::make_pair(IV.Val, IV.DerefLevel));
 | 
						|
  }
 | 
						|
  static bool isEqual(const cflaa::InstantiatedValue &LHS,
 | 
						|
                      const cflaa::InstantiatedValue &RHS) {
 | 
						|
    return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel;
 | 
						|
  }
 | 
						|
};
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |