OLD | NEW |
(Empty) | |
| 1 //===- AbbrevTrieNode.cpp ------------------------------------------------===// |
| 2 // Implements abbreviation lookup tries. |
| 3 // |
| 4 // The LLVM Compiler Infrastructure |
| 5 // |
| 6 // This file is distributed under the University of Illinois Open Source |
| 7 // License. See LICENSE.TXT for details. |
| 8 // |
| 9 //===----------------------------------------------------------------------===// |
| 10 |
| 11 #include "llvm/Bitcode/NaCl/AbbrevTrieNode.h" |
| 12 #include "llvm/Bitcode/NaCl/NaClBitcodeValueDist.h" |
| 13 |
| 14 using namespace llvm; |
| 15 |
| 16 void AbbrevTrieNode::GetSuccessorLabels(SuccessorLabels &Labels) const { |
| 17 for (SuccessorMap::const_iterator |
| 18 IndexIter = Successors.begin(), IndexIterEnd = Successors.end(); |
| 19 IndexIter != IndexIterEnd; ++IndexIter) { |
| 20 if (const SuccessorValueMap *ValueMap = IndexIter->second) { |
| 21 for (SuccessorValueMap::const_iterator |
| 22 ValueIter = ValueMap->begin(), ValueIterEnd = ValueMap->end(); |
| 23 ValueIter != ValueIterEnd; ++ValueIter) { |
| 24 Labels.push_back(std::pair<size_t, uint64_t>(IndexIter->first, |
| 25 ValueIter->first)); |
| 26 } |
| 27 } |
| 28 } |
| 29 } |
| 30 |
| 31 AbbrevTrieNode::~AbbrevTrieNode() { |
| 32 for (SuccessorMap::const_iterator |
| 33 Iter = Successors.begin(), IterEnd = Successors.end(); |
| 34 Iter != IterEnd; ++Iter) { |
| 35 if (const SuccessorValueMap *ValueMap = Iter->second) { |
| 36 for (SuccessorValueMap::const_iterator |
| 37 Iter = ValueMap->begin(), IterEnd = ValueMap->end(); |
| 38 Iter != IterEnd; ++Iter) { |
| 39 delete Iter->second; |
| 40 } |
| 41 delete ValueMap; |
| 42 } |
| 43 } |
| 44 } |
| 45 |
| 46 void AbbrevTrieNode::Print(raw_ostream &Stream, |
| 47 const std::string &Indent, |
| 48 bool LocalOnly) const { |
| 49 std::string IndentPlus(Indent); |
| 50 IndentPlus.append(" "); |
| 51 std::string IndentPlusPlus(IndentPlus); |
| 52 IndentPlusPlus.append(" "); |
| 53 if (! Abbreviations.empty()) { |
| 54 Stream << Indent << "Abbreviations:\n"; |
| 55 for (std::set<AbbrevIndexPair>::const_iterator |
| 56 Iter = Abbreviations.begin(), IterEnd = Abbreviations.end(); |
| 57 Iter != IterEnd; ++Iter) { |
| 58 Stream << IndentPlus; |
| 59 Iter->second->Print(Stream, /* AddNewline= */ false); |
| 60 Stream << " (abbrev #" << Iter->first << ")\n"; |
| 61 } |
| 62 } |
| 63 if (LocalOnly) return; |
| 64 if (!Successors.empty()) { |
| 65 Stream << Indent << "Successor Map:\n"; |
| 66 SuccessorLabels Labels; |
| 67 GetSuccessorLabels(Labels); |
| 68 for (SuccessorLabels::const_iterator |
| 69 Iter = Labels.begin(), IterEnd = Labels.end(); |
| 70 Iter != IterEnd; ++Iter) { |
| 71 size_t Index = Iter->first; |
| 72 if (Index == 0) { |
| 73 Stream << IndentPlus << "Record.Code = " << Iter->second << "\n"; |
| 74 } else { |
| 75 Stream << IndentPlus << "Record.Values[" << (Index-1) |
| 76 << "] = " << Iter->second << "\n"; |
| 77 } |
| 78 GetSuccessor(Iter->first, Iter->second)->Print(Stream, IndentPlusPlus); |
| 79 } |
| 80 } |
| 81 } |
| 82 |
| 83 AbbrevTrieNode *AbbrevTrieNode:: |
| 84 GetSuccessor(size_t Index, uint64_t Value) const { |
| 85 SuccessorMap::const_iterator IndexPos = Successors.find(Index); |
| 86 if (IndexPos != Successors.end()) { |
| 87 if (SuccessorValueMap *ValueMap = IndexPos->second) { |
| 88 SuccessorValueMap::iterator ValuePos = ValueMap->find(Value); |
| 89 if (ValuePos != ValueMap->end()) |
| 90 return ValuePos->second; |
| 91 } |
| 92 } |
| 93 return 0; |
| 94 } |
| 95 |
| 96 bool AbbrevTrieNode::Add(NaClBitCodeAbbrev *Abbrev, |
| 97 size_t Index, size_t SkipIndex) { |
| 98 if (Index >= Abbrev->getNumOperandInfos()) return false; |
| 99 bool AddedNodes = false; |
| 100 |
| 101 // Skip over matches that may match because they don't have constants |
| 102 // in the index. |
| 103 while (SkipIndex < Index) { |
| 104 SuccessorMap::iterator Pos = Successors.find(SkipIndex); |
| 105 if (Pos != Successors.end()) { |
| 106 SuccessorValueMap *ValueMap = Pos->second; |
| 107 for (SuccessorValueMap::const_iterator |
| 108 Iter = ValueMap->begin(), IterEnd = ValueMap->end(); |
| 109 Iter != IterEnd; ++Iter) { |
| 110 if (AbbrevTrieNode *Successor = Iter->second) { |
| 111 if (Successor->Add(Abbrev, Index, SkipIndex+1)) |
| 112 AddedNodes = true; |
| 113 } |
| 114 } |
| 115 } |
| 116 ++SkipIndex; |
| 117 } |
| 118 |
| 119 // Now update successors for next matching constant in abbreviation. |
| 120 for (; Index < Abbrev->GetMinRecordSize(); ++Index) { |
| 121 const NaClBitCodeAbbrevOp &Op = Abbrev->getOperandInfo(Index); |
| 122 if (Op.isLiteral()) { |
| 123 if (Index == SkipIndex) { |
| 124 // No preceeding nodes to match, add here. |
| 125 SuccessorValueMap *ValueMap = Successors[Index]; |
| 126 if (ValueMap == 0) { |
| 127 ValueMap = new SuccessorValueMap(); |
| 128 Successors[Index] = ValueMap; |
| 129 } |
| 130 AbbrevTrieNode *Successor = (*ValueMap)[Op.getValue()]; |
| 131 if (Successor == 0) { |
| 132 Successor = new AbbrevTrieNode(); |
| 133 AddedNodes = true; |
| 134 (*ValueMap)[Op.getValue()] = Successor; |
| 135 } |
| 136 if (Successor->Add(Abbrev, Index+1, Index+1)) |
| 137 AddedNodes = true; |
| 138 } else { |
| 139 // Need to match all possible prefixes before inserting constant. |
| 140 if (Add(Abbrev, Index, SkipIndex)) |
| 141 AddedNodes = true; |
| 142 } |
| 143 return AddedNodes; |
| 144 } |
| 145 } |
| 146 return AddedNodes; |
| 147 } |
| 148 |
| 149 void AbbrevTrieNode::Insert(AbbrevIndexPair &AbbrevPair) { |
| 150 NaClBitCodeAbbrev *Abbrev = AbbrevPair.second; |
| 151 |
| 152 for (std::map<size_t, SuccessorValueMap*>::iterator |
| 153 Iter = Successors.begin(), IterEnd = Successors.end(); |
| 154 Iter != IterEnd; ++Iter) { |
| 155 if (SuccessorValueMap *ValueMap = Iter->second) { |
| 156 if (Iter->first < Abbrev->GetMinRecordSize()) { |
| 157 const NaClBitCodeAbbrevOp &Op = |
| 158 Abbrev->getOperandInfo(Iter->first); |
| 159 if (Op.isLiteral()) { |
| 160 uint64_t Value = Op.getValue(); |
| 161 SuccessorValueMap::iterator Pos = ValueMap->find(Value); |
| 162 if (Pos != ValueMap->end()) { |
| 163 if (AbbrevTrieNode *Next = Pos->second) { |
| 164 // Found constant that will be followed, update subgraph |
| 165 // and quit. |
| 166 Next->Insert(AbbrevPair); |
| 167 return; |
| 168 } |
| 169 } |
| 170 } else { |
| 171 // Not literal, so it may (or may not) be followed, depending |
| 172 // on the value in the record that will be matched against. So |
| 173 // add to subgraph, and here if no succeeding matching literal |
| 174 // constants. |
| 175 for (SuccessorValueMap::iterator |
| 176 Iter = ValueMap->begin(), IterEnd = ValueMap->end(); |
| 177 Iter != IterEnd; ++Iter) { |
| 178 if (AbbrevTrieNode *Next = Iter->second) |
| 179 Next->Insert(AbbrevPair); |
| 180 } |
| 181 } |
| 182 } else if (!Abbrev->IsFixedSize()) { |
| 183 // May match array element. So add to subgraph as well as here. |
| 184 for (SuccessorValueMap::iterator |
| 185 Iter = ValueMap->begin(), IterEnd = ValueMap->end(); |
| 186 Iter != IterEnd; ++Iter) { |
| 187 if (AbbrevTrieNode *Next = Iter->second) |
| 188 Next->Insert(AbbrevPair); |
| 189 } |
| 190 } |
| 191 } |
| 192 } |
| 193 |
| 194 // If reached, no guarantees that any edge was followed, so add |
| 195 // to matches of this node. |
| 196 Abbreviations.insert(AbbrevPair); |
| 197 } |
| 198 |
| 199 const AbbrevTrieNode *AbbrevTrieNode:: |
| 200 MatchRecord(const NaClBitcodeRecordData &Record) const { |
| 201 for (std::map<size_t, SuccessorValueMap*>::const_iterator |
| 202 Iter = Successors.begin(), IterEnd = Successors.end(); |
| 203 Iter != IterEnd; ++Iter) { |
| 204 if (SuccessorValueMap *ValueMap = Iter->second) { |
| 205 if (Iter->first <= Record.Values.size()) { |
| 206 uint64_t Value; |
| 207 if (Iter->first == 0) |
| 208 Value = Record.Code; |
| 209 else |
| 210 Value = Record.Values[Iter->first-1]; |
| 211 SuccessorValueMap::iterator Pos = ValueMap->find(Value); |
| 212 if (Pos != ValueMap->end()) { |
| 213 if (AbbrevTrieNode *Next = Pos->second) { |
| 214 return Next->MatchRecord(Record); |
| 215 } |
| 216 } |
| 217 } else { |
| 218 // Map index too big, quit. |
| 219 break; |
| 220 } |
| 221 } |
| 222 } |
| 223 |
| 224 // If reached, no refinement found, use this node. |
| 225 return this; |
| 226 } |
| 227 |
| 228 static void ComputeAbbrevRange(NaClBitCodeAbbrev *Abbrev, |
| 229 size_t &MinIndex, size_t &MaxIndex) { |
| 230 // Find the range of record lengths for which the abbreviation may |
| 231 // apply. Note: To keep a limit on the number of copies, collapse all |
| 232 // records with length > NaClValueIndexCutoff into the same bucket. |
| 233 MinIndex = Abbrev->GetMinRecordSize(); |
| 234 if (MinIndex > NaClValueIndexCutoff) { |
| 235 MinIndex = NaClValueIndexCutoff + 1; |
| 236 } |
| 237 MaxIndex = MinIndex; |
| 238 if (!Abbrev->IsFixedSize()) { |
| 239 MaxIndex = NaClValueIndexCutoff + 1; |
| 240 } |
| 241 } |
| 242 |
| 243 // Once all nodes have been added (via calls to AddAbbrevToLookupMap), |
| 244 // this function adds the given abbreviation pair to all possible |
| 245 // matchxes in the lookup map. |
| 246 static void AddAbbrevPairToLookupMap(AbbrevLookupSizeMap &LookupMap, |
| 247 AbbrevIndexPair &AbbrevPair) { |
| 248 size_t MinIndex, MaxIndex; |
| 249 ComputeAbbrevRange(AbbrevPair.second, MinIndex, MaxIndex); |
| 250 for (size_t Index = MinIndex; Index <= MaxIndex; ++Index) { |
| 251 AbbrevTrieNode *Node = LookupMap[Index]; |
| 252 assert(Node); |
| 253 Node->Insert(AbbrevPair); |
| 254 } |
| 255 } |
| 256 |
| 257 // Adds the given abbreviation to the corresponding lookup map, constructing |
| 258 // the map of usable lookup tries. |
| 259 static bool AddAbbrevToLookupMap(AbbrevLookupSizeMap &LookupMap, |
| 260 NaClBitCodeAbbrev *Abbrev) { |
| 261 bool Added = false; |
| 262 size_t MinIndex, MaxIndex; |
| 263 ComputeAbbrevRange(Abbrev, MinIndex, MaxIndex); |
| 264 for (size_t Index = MinIndex; Index <= MaxIndex; ++Index) { |
| 265 AbbrevTrieNode *Node = LookupMap[Index]; |
| 266 if (Node == 0) { |
| 267 Node = new AbbrevTrieNode(); |
| 268 LookupMap[Index] = Node; |
| 269 Added = true; |
| 270 } |
| 271 if (Node->Add(Abbrev)) Added = true; |
| 272 } |
| 273 return Added; |
| 274 } |
| 275 |
| 276 void llvm::NaClBuildAbbrevLookupMap( |
| 277 AbbrevLookupSizeMap &LookupMap, |
| 278 const SmallVectorImpl<NaClBitCodeAbbrev*> &Abbrevs, |
| 279 size_t InitialIndex) { |
| 280 // First build nodes of trie. |
| 281 bool FixpointFound = false; |
| 282 while (!FixpointFound) { |
| 283 FixpointFound = true; |
| 284 for (size_t i = InitialIndex; i < Abbrevs.size(); ++i) { |
| 285 if (AddAbbrevToLookupMap(LookupMap, Abbrevs[i])) |
| 286 FixpointFound = false; |
| 287 } |
| 288 } |
| 289 |
| 290 // Now populate with abbreviations that apply. |
| 291 for (size_t i = InitialIndex; i < Abbrevs.size(); ++i) { |
| 292 AbbrevIndexPair Pair(i, Abbrevs[i]); |
| 293 AddAbbrevPairToLookupMap(LookupMap, Pair); |
| 294 } |
| 295 } |
OLD | NEW |