1 //=====- CFLSummary.h - Abstract stratified sets implementation. --------=====// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// This file defines various utility types and functions useful to 11 /// summary-based alias analysis. 12 /// 13 /// Summary-based analysis, also known as bottom-up analysis, is a style of 14 /// interprocedrual static analysis that tries to analyze the callees before the 15 /// callers get analyzed. The key idea of summary-based analysis is to first 16 /// process each function independently, outline its behavior in a condensed 17 /// summary, and then instantiate the summary at the callsite when the said 18 /// function is called elsewhere. This is often in contrast to another style 19 /// called top-down analysis, in which callers are always analyzed first before 20 /// the callees. 21 /// 22 /// In a summary-based analysis, functions must be examined independently and 23 /// out-of-context. We have no information on the state of the memory, the 24 /// arguments, the global values, and anything else external to the function. To 25 /// carry out the analysis conservative assumptions have to be made about those 26 /// external states. In exchange for the potential loss of precision, the 27 /// summary we obtain this way is highly reusable, which makes the analysis 28 /// easier to scale to large programs even if carried out context-sensitively. 29 /// 30 /// Currently, all CFL-based alias analyses adopt the summary-based approach 31 /// and therefore heavily rely on this header. 32 /// 33 //===----------------------------------------------------------------------===// 34 35 #ifndef LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H 36 #define LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H 37 38 #include "llvm/ADT/DenseMapInfo.h" 39 #include "llvm/ADT/Optional.h" 40 #include "llvm/ADT/SmallVector.h" 41 #include "llvm/IR/CallSite.h" 42 #include <bitset> 43 44 namespace llvm { 45 namespace cflaa { 46 47 //===----------------------------------------------------------------------===// 48 // AliasAttr related stuffs 49 //===----------------------------------------------------------------------===// 50 51 /// The number of attributes that AliasAttr should contain. Attributes are 52 /// described below, and 32 was an arbitrary choice because it fits nicely in 32 53 /// bits (because we use a bitset for AliasAttr). 54 static const unsigned NumAliasAttrs = 32; 55 56 /// These are attributes that an alias analysis can use to mark certain special 57 /// properties of a given pointer. Refer to the related functions below to see 58 /// what kinds of attributes are currently defined. 59 typedef std::bitset<NumAliasAttrs> AliasAttrs; 60 61 /// Attr represent whether the said pointer comes from an unknown source 62 /// (such as opaque memory or an integer cast). 63 AliasAttrs getAttrNone(); 64 65 /// AttrUnknown represent whether the said pointer comes from a source not known 66 /// to alias analyses (such as opaque memory or an integer cast). 67 AliasAttrs getAttrUnknown(); 68 bool hasUnknownAttr(AliasAttrs); 69 70 /// AttrCaller represent whether the said pointer comes from a source not known 71 /// to the current function but known to the caller. Values pointed to by the 72 /// arguments of the current function have this attribute set 73 AliasAttrs getAttrCaller(); 74 bool hasCallerAttr(AliasAttrs); 75 bool hasUnknownOrCallerAttr(AliasAttrs); 76 77 /// AttrEscaped represent whether the said pointer comes from a known source but 78 /// escapes to the unknown world (e.g. casted to an integer, or passed as an 79 /// argument to opaque function). Unlike non-escaped pointers, escaped ones may 80 /// alias pointers coming from unknown sources. 81 AliasAttrs getAttrEscaped(); 82 bool hasEscapedAttr(AliasAttrs); 83 84 /// AttrGlobal represent whether the said pointer is a global value. 85 /// AttrArg represent whether the said pointer is an argument, and if so, what 86 /// index the argument has. 87 AliasAttrs getGlobalOrArgAttrFromValue(const Value &); 88 bool isGlobalOrArgAttr(AliasAttrs); 89 90 /// Given an AliasAttrs, return a new AliasAttrs that only contains attributes 91 /// meaningful to the caller. This function is primarily used for 92 /// interprocedural analysis 93 /// Currently, externally visible AliasAttrs include AttrUnknown, AttrGlobal, 94 /// and AttrEscaped 95 AliasAttrs getExternallyVisibleAttrs(AliasAttrs); 96 97 //===----------------------------------------------------------------------===// 98 // Function summary related stuffs 99 //===----------------------------------------------------------------------===// 100 101 /// The maximum number of arguments we can put into a summary. 102 static const unsigned MaxSupportedArgsInSummary = 50; 103 104 /// We use InterfaceValue to describe parameters/return value, as well as 105 /// potential memory locations that are pointed to by parameters/return value, 106 /// of a function. 107 /// Index is an integer which represents a single parameter or a return value. 108 /// When the index is 0, it refers to the return value. Non-zero index i refers 109 /// to the i-th parameter. 110 /// DerefLevel indicates the number of dereferences one must perform on the 111 /// parameter/return value to get this InterfaceValue. 112 struct InterfaceValue { 113 unsigned Index; 114 unsigned DerefLevel; 115 }; 116 117 inline bool operator==(InterfaceValue LHS, InterfaceValue RHS) { 118 return LHS.Index == RHS.Index && LHS.DerefLevel == RHS.DerefLevel; 119 } 120 inline bool operator!=(InterfaceValue LHS, InterfaceValue RHS) { 121 return !(LHS == RHS); 122 } 123 inline bool operator<(InterfaceValue LHS, InterfaceValue RHS) { 124 return LHS.Index < RHS.Index || 125 (LHS.Index == RHS.Index && LHS.DerefLevel < RHS.DerefLevel); 126 } 127 inline bool operator>(InterfaceValue LHS, InterfaceValue RHS) { 128 return RHS < LHS; 129 } 130 inline bool operator<=(InterfaceValue LHS, InterfaceValue RHS) { 131 return !(RHS < LHS); 132 } 133 inline bool operator>=(InterfaceValue LHS, InterfaceValue RHS) { 134 return !(LHS < RHS); 135 } 136 137 // We use UnknownOffset to represent pointer offsets that cannot be determined 138 // at compile time. Note that MemoryLocation::UnknownSize cannot be used here 139 // because we require a signed value. 140 static const int64_t UnknownOffset = INT64_MAX; 141 142 inline int64_t addOffset(int64_t LHS, int64_t RHS) { 143 if (LHS == UnknownOffset || RHS == UnknownOffset) 144 return UnknownOffset; 145 // FIXME: Do we need to guard against integer overflow here? 146 return LHS + RHS; 147 } 148 149 /// We use ExternalRelation to describe an externally visible aliasing relations 150 /// between parameters/return value of a function. 151 struct ExternalRelation { 152 InterfaceValue From, To; 153 int64_t Offset; 154 }; 155 156 inline bool operator==(ExternalRelation LHS, ExternalRelation RHS) { 157 return LHS.From == RHS.From && LHS.To == RHS.To && LHS.Offset == RHS.Offset; 158 } 159 inline bool operator!=(ExternalRelation LHS, ExternalRelation RHS) { 160 return !(LHS == RHS); 161 } 162 inline bool operator<(ExternalRelation LHS, ExternalRelation RHS) { 163 if (LHS.From < RHS.From) 164 return true; 165 if (LHS.From > RHS.From) 166 return false; 167 if (LHS.To < RHS.To) 168 return true; 169 if (LHS.To > RHS.To) 170 return false; 171 return LHS.Offset < RHS.Offset; 172 } 173 inline bool operator>(ExternalRelation LHS, ExternalRelation RHS) { 174 return RHS < LHS; 175 } 176 inline bool operator<=(ExternalRelation LHS, ExternalRelation RHS) { 177 return !(RHS < LHS); 178 } 179 inline bool operator>=(ExternalRelation LHS, ExternalRelation RHS) { 180 return !(LHS < RHS); 181 } 182 183 /// We use ExternalAttribute to describe an externally visible AliasAttrs 184 /// for parameters/return value. 185 struct ExternalAttribute { 186 InterfaceValue IValue; 187 AliasAttrs Attr; 188 }; 189 190 /// AliasSummary is just a collection of ExternalRelation and ExternalAttribute 191 struct AliasSummary { 192 // RetParamRelations is a collection of ExternalRelations. 193 SmallVector<ExternalRelation, 8> RetParamRelations; 194 195 // RetParamAttributes is a collection of ExternalAttributes. 196 SmallVector<ExternalAttribute, 8> RetParamAttributes; 197 }; 198 199 /// This is the result of instantiating InterfaceValue at a particular callsite 200 struct InstantiatedValue { 201 Value *Val; 202 unsigned DerefLevel; 203 }; 204 Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue, CallSite); 205 206 inline bool operator==(InstantiatedValue LHS, InstantiatedValue RHS) { 207 return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel; 208 } 209 inline bool operator!=(InstantiatedValue LHS, InstantiatedValue RHS) { 210 return !(LHS == RHS); 211 } 212 inline bool operator<(InstantiatedValue LHS, InstantiatedValue RHS) { 213 return std::less<Value *>()(LHS.Val, RHS.Val) || 214 (LHS.Val == RHS.Val && LHS.DerefLevel < RHS.DerefLevel); 215 } 216 inline bool operator>(InstantiatedValue LHS, InstantiatedValue RHS) { 217 return RHS < LHS; 218 } 219 inline bool operator<=(InstantiatedValue LHS, InstantiatedValue RHS) { 220 return !(RHS < LHS); 221 } 222 inline bool operator>=(InstantiatedValue LHS, InstantiatedValue RHS) { 223 return !(LHS < RHS); 224 } 225 226 /// This is the result of instantiating ExternalRelation at a particular 227 /// callsite 228 struct InstantiatedRelation { 229 InstantiatedValue From, To; 230 int64_t Offset; 231 }; 232 Optional<InstantiatedRelation> instantiateExternalRelation(ExternalRelation, 233 CallSite); 234 235 /// This is the result of instantiating ExternalAttribute at a particular 236 /// callsite 237 struct InstantiatedAttr { 238 InstantiatedValue IValue; 239 AliasAttrs Attr; 240 }; 241 Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute, 242 CallSite); 243 } 244 245 template <> struct DenseMapInfo<cflaa::InstantiatedValue> { 246 static inline cflaa::InstantiatedValue getEmptyKey() { 247 return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getEmptyKey(), 248 DenseMapInfo<unsigned>::getEmptyKey()}; 249 } 250 static inline cflaa::InstantiatedValue getTombstoneKey() { 251 return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getTombstoneKey(), 252 DenseMapInfo<unsigned>::getTombstoneKey()}; 253 } 254 static unsigned getHashValue(const cflaa::InstantiatedValue &IV) { 255 return DenseMapInfo<std::pair<Value *, unsigned>>::getHashValue( 256 std::make_pair(IV.Val, IV.DerefLevel)); 257 } 258 static bool isEqual(const cflaa::InstantiatedValue &LHS, 259 const cflaa::InstantiatedValue &RHS) { 260 return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel; 261 } 262 }; 263 } 264 265 #endif 266