Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- NaClBitcodeMungeWriter.cpp - Write munged bitcode --------*- C++ -*-===// | 1 //===- NaClBitcodeMungeWriter.cpp - Write munged bitcode --------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // Implements method NaClMungedBitcode.write(), which writes out a munged | 10 // Implements method NaClMungedBitcode.write(), which writes out a munged |
| 11 // list of bitcode records using a bitstream writer. | 11 // list of bitcode records using a bitstream writer. |
| 12 | 12 |
| 13 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" | 13 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" |
| 14 | 14 |
| 15 #include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h" | 15 #include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h" |
| 16 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" | 16 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| 17 #include "llvm/Support/raw_ostream.h" | 17 #include "llvm/Support/raw_ostream.h" |
| 18 | 18 |
| 19 #include <set> | |
| 20 | |
| 19 using namespace llvm; | 21 using namespace llvm; |
| 20 | 22 |
| 21 namespace { | 23 namespace { |
| 22 | 24 |
| 23 // For debugging. When true, shows trace information of emitting | 25 // For debugging. When true, shows trace information of emitting |
| 24 // bitcode. | 26 // bitcode. |
| 25 static bool DebugEmit = false; | 27 static bool DebugEmit = false; |
| 26 | 28 |
| 29 // Maximum bits that can be printed out using method | |
| 30 // NaClBitstreamWriter::Emit(). | |
|
jvoung (off chromium)
2015/05/20 22:40:09
Seems like this should be part of NaClBitstreamWri
Karl
2015/05/21 18:22:07
I agree. I originally put it there, but I didn't l
| |
| 31 static const unsigned MaxEmitFixedBits = 32; | |
| 32 | |
| 27 // Description of current block scope | 33 // Description of current block scope |
| 28 struct BlockScope { | 34 struct BlockScope { |
| 29 BlockScope(unsigned CurBlockID, size_t AbbrevIndexLimit) | 35 BlockScope(unsigned CurBlockID, size_t AbbrevIndexLimit) |
| 30 : CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit) {} | 36 : CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit), |
| 37 OmittedAbbreviations(false) {} | |
| 31 unsigned CurBlockID; | 38 unsigned CurBlockID; |
| 32 // Defines the maximum value for abbreviation indices in block. | 39 // Defines the maximum value for abbreviation indices in block. |
| 33 size_t AbbrevIndexLimit; | 40 size_t AbbrevIndexLimit; |
| 41 // Defines if an abbreviation definition was omitted (i.e. not | |
| 42 // written) from this block. Used to turn off writing further | |
| 43 // abbreviation definitions for this block. | |
| 44 bool OmittedAbbreviations; | |
| 34 void print(raw_ostream &Out) const { | 45 void print(raw_ostream &Out) const { |
| 35 Out << "BlockScope(ID=" << CurBlockID << ", AbbrevIndexLimit=" | 46 Out << "BlockScope(ID=" << CurBlockID << ", AbbrevIndexLimit=" |
| 36 << AbbrevIndexLimit << ")"; | 47 << AbbrevIndexLimit << "OmittedAbbreviations = " |
|
jvoung (off chromium)
2015/05/20 22:40:10
= spacing consistency
previous ones just did X=Y
Karl
2015/05/21 18:22:08
Done.
| |
| 48 << OmittedAbbreviations << ")"; | |
| 37 } | 49 } |
| 38 }; | 50 }; |
| 39 | 51 |
| 40 inline raw_ostream &operator<<(raw_ostream &Out, const BlockScope &Scope) { | 52 inline raw_ostream &operator<<(raw_ostream &Out, const BlockScope &Scope) { |
| 41 Scope.print(Out); | 53 Scope.print(Out); |
| 42 return Out; | 54 return Out; |
| 43 } | 55 } |
| 44 | 56 |
| 45 // State of bitcode writing. | 57 // State of bitcode writing. |
| 46 struct WriteState { | 58 struct WriteState { |
| 47 // The block ID associated with records not in any block. | 59 // The block ID associated with records not in any block. |
| 48 static const unsigned UnknownWriteBlockID = UINT_MAX; | 60 static const unsigned UnknownWriteBlockID = UINT_MAX; |
| 49 // The SetBID for the blockinfo block. | 61 // The SetBID for the blockinfo block. |
| 50 unsigned SetBID = UnknownWriteBlockID; | 62 unsigned SetBID = UnknownWriteBlockID; |
| 51 // The stack of scopes the writer is in. | 63 // The stack of scopes the writer is in. |
| 52 SmallVector<BlockScope, 3> ScopeStack; | 64 SmallVector<BlockScope, 3> ScopeStack; |
|
jvoung (off chromium)
2015/05/20 22:40:10
btw, I don't remember if this 3 was "optimized" fo
Karl
2015/05/21 18:22:07
Good point. It was optimized as you suggested. Inc
| |
| 53 // The set of write flags to use. | 65 // The set of write flags to use. |
| 54 const NaClMungedBitcode::WriteFlags &Flags; | 66 const NaClMungedBitcode::WriteFlags &Flags; |
| 55 // The results of the attempted write. | 67 // The results of the attempted write. |
| 56 NaClMungedBitcode::WriteResults Results; | 68 NaClMungedBitcode::WriteResults Results; |
| 57 // The minimum number of bits allowed to be specified in a block. | 69 // The minimum number of bits allowed to be specified in a block. |
| 58 const unsigned BlockMinBits; | 70 const unsigned BlockMinBits; |
| 71 // The set of block IDs for which abbreviation definitions have been | |
| 72 // omitted in the blockinfo block. | |
| 73 std::set<unsigned> BlocksWithOmittedAbbrevs; | |
|
jvoung (off chromium)
2015/05/20 22:40:10
Would DenseSet be better?
I suppose there are onl
Karl
2015/05/21 18:22:07
I did not expect the set to get much larger than 8
| |
| 59 | 74 |
| 60 WriteState(const NaClMungedBitcode::WriteFlags &Flags) | 75 WriteState(const NaClMungedBitcode::WriteFlags &Flags) |
| 61 : Flags(Flags), | 76 : Flags(Flags), |
| 62 BlockMinBits(NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV)) { | 77 BlockMinBits(NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV)) { |
| 63 BlockScope Scope(UnknownWriteBlockID, naclbitc::DEFAULT_MAX_ABBREV); | 78 BlockScope Scope(UnknownWriteBlockID, naclbitc::DEFAULT_MAX_ABBREV); |
| 64 ScopeStack.push_back(Scope); | 79 ScopeStack.push_back(Scope); |
| 65 } | 80 } |
| 66 | 81 |
| 67 // Returns stream to print error message to. | 82 // Returns stream to print error message to. |
| 68 raw_ostream &Error(); | 83 raw_ostream &Error(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 83 unsigned getCurWriteBlockID() const { | 98 unsigned getCurWriteBlockID() const { |
| 84 assert(!ScopeStack.empty()); | 99 assert(!ScopeStack.empty()); |
| 85 return ScopeStack.back().CurBlockID; | 100 return ScopeStack.back().CurBlockID; |
| 86 } | 101 } |
| 87 | 102 |
| 88 unsigned getCurAbbrevIndexLimit() const { | 103 unsigned getCurAbbrevIndexLimit() const { |
| 89 assert(!ScopeStack.empty()); | 104 assert(!ScopeStack.empty()); |
| 90 return ScopeStack.back().AbbrevIndexLimit; | 105 return ScopeStack.back().AbbrevIndexLimit; |
| 91 } | 106 } |
| 92 | 107 |
| 108 // Returns whether any abbreviation definitions were not written to | |
| 109 // the bitcode buffer. | |
| 110 bool curBlockHasOmittedAbbreviations() const { | |
| 111 assert(!ScopeStack.empty()); | |
| 112 return ScopeStack.back().OmittedAbbreviations | |
| 113 || BlocksWithOmittedAbbrevs.count(getCurWriteBlockID()); | |
| 114 } | |
| 115 | |
| 116 // Marks that an abbreviation definition is being omitted (i.e. not | |
| 117 // written) for the current block. | |
| 118 void markCurrentBlockWithOmittedAbbreviations() { | |
| 119 assert(!ScopeStack.empty()); | |
| 120 ScopeStack.back().OmittedAbbreviations = true; | |
| 121 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) | |
| 122 BlocksWithOmittedAbbrevs.insert(SetBID); | |
| 123 return; | |
|
jvoung (off chromium)
2015/05/20 22:40:10
The return doesn't seem to do much so may be bette
Karl
2015/05/21 18:22:08
Hmm. I guess this is a leftover of an earlier vers
| |
| 124 } | |
| 125 | |
| 93 // Converts the abbreviation record to the corresponding abbreviation. | 126 // Converts the abbreviation record to the corresponding abbreviation. |
| 94 // Returns nullptr if unable to build abbreviation. | 127 // Returns nullptr if unable to build abbreviation. |
| 95 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); | 128 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); |
| 96 | 129 |
| 97 // Emits the given record to the bitcode file. Returns true if | 130 // Emits the given record to the bitcode file. Returns true if |
| 98 // successful. | 131 // successful. |
| 99 bool LLVM_ATTRIBUTE_UNUSED_RESULT | 132 bool LLVM_ATTRIBUTE_UNUSED_RESULT |
| 100 emitRecord(NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record) ; | 133 emitRecord(NaClBitstreamWriter &Writer, |
| 134 const NaClBitcodeAbbrevRecord &Record); | |
| 101 | 135 |
| 102 // Enter the given block | 136 // Enter the given block |
| 103 bool LLVM_ATTRIBUTE_UNUSED_RESULT | 137 bool LLVM_ATTRIBUTE_UNUSED_RESULT |
| 104 enterBlock(NaClBitstreamWriter &Writer, uint64_t WriteBlockID, | 138 enterBlock(NaClBitstreamWriter &Writer, uint64_t WriteBlockID, |
| 105 uint64_t NumBits, const NaClBitcodeAbbrevRecord &Record); | 139 uint64_t NumBits, const NaClBitcodeAbbrevRecord &Record); |
| 106 | 140 |
| 107 // Exit current block and return to previous block. Silently recovers | 141 // Exit current block and return to previous block. Silently recovers |
| 108 // if at outermost scope. | 142 // if at outermost scope. |
| 109 bool LLVM_ATTRIBUTE_UNUSED_RESULT | 143 bool LLVM_ATTRIBUTE_UNUSED_RESULT |
| 110 exitBlock(NaClBitstreamWriter &Writer, | 144 exitBlock(NaClBitstreamWriter &Writer, |
| 111 const NaClBitcodeAbbrevRecord *Record = nullptr) { | 145 const NaClBitcodeAbbrevRecord *Record = nullptr) { |
| 112 if (atOutermostScope()) | 146 if (atOutermostScope()) |
| 113 return false; | 147 return false; |
| 114 Writer.ExitBlock(); | 148 Writer.ExitBlock(); |
| 115 ScopeStack.pop_back(); | 149 ScopeStack.pop_back(); |
| 116 if (DebugEmit) | 150 if (DebugEmit) |
| 117 printScopeStack(errs()); | 151 printScopeStack(errs()); |
| 118 return true; | 152 return true; |
| 119 } | 153 } |
| 120 | 154 |
| 155 void WriteRecord(NaClBitstreamWriter &Writer, | |
| 156 const NaClBitcodeAbbrevRecord &Record, | |
| 157 bool UsesDefaultAbbrev) { | |
| 158 if (UsesDefaultAbbrev) | |
| 159 Writer.EmitRecord(Record.Code, Record.Values); | |
| 160 else | |
| 161 Writer.EmitRecord(Record.Code, Record.Values, Record.Abbrev); | |
| 162 | |
| 163 } | |
| 164 | |
| 165 // Returns true if the abbreviation index defines an anbbreviation | |
|
jvoung (off chromium)
2015/05/20 22:40:09
anbbreviation -> ?
Karl
2015/05/21 18:22:07
Fixed.
| |
| 166 // that can be applied to the record. | |
| 167 bool LLVM_ATTRIBUTE_UNUSED_RESULT | |
| 168 canApplyAbbreviation(NaClBitstreamWriter &Writer, | |
| 169 const NaClBitcodeAbbrevRecord &Record); | |
| 170 | |
| 121 // Completes the write. | 171 // Completes the write. |
| 122 NaClMungedBitcode::WriteResults &finish(NaClBitstreamWriter &Writer, | 172 NaClMungedBitcode::WriteResults &finish(NaClBitstreamWriter &Writer, |
| 123 bool RecoverSilently); | 173 bool RecoverSilently); |
| 124 | 174 |
| 125 void printScopeStack(raw_ostream &Out) { | 175 void printScopeStack(raw_ostream &Out) { |
| 126 Out << "Scope Stack:\n"; | 176 Out << "Scope Stack:\n"; |
| 127 for (auto &Scope : ScopeStack) | 177 for (auto &Scope : ScopeStack) |
| 128 Out << " " << Scope << "\n"; | 178 Out << " " << Scope << "\n"; |
| 129 } | 179 } |
| 130 }; | 180 }; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 return false; | 228 return false; |
| 179 } | 229 } |
| 180 Writer.EnterBlockInfoBlock(); | 230 Writer.EnterBlockInfoBlock(); |
| 181 } else { | 231 } else { |
| 182 NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); | 232 NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); |
| 183 Writer.EnterSubblock(WriteBlockID, CurCodeLen); | 233 Writer.EnterSubblock(WriteBlockID, CurCodeLen); |
| 184 } | 234 } |
| 185 return true; | 235 return true; |
| 186 } | 236 } |
| 187 | 237 |
| 238 bool WriteState::canApplyAbbreviation( | |
| 239 NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record) { | |
|
Karl
2015/05/20 20:32:04
Added following two lines to make sure that the bl
jvoung (off chromium)
2015/05/20 22:40:09
Does the Writer.getAbbreviation(...); if (Abbrev =
Karl
2015/05/21 18:22:07
This check helps. I didn't see the case until the
| |
| 240 if (Record.Abbrev > getCurAbbrevIndexLimit()) | |
| 241 return false; | |
| 242 | |
| 243 const NaClBitCodeAbbrev *Abbrev = Writer.getAbbreviation(Record.Abbrev); | |
| 244 if (Abbrev == nullptr) | |
| 245 return false; | |
| 246 | |
| 247 // Merge record code into values and then match abbreviation. | |
| 248 NaClBitcodeValues Values(Record); | |
| 249 size_t ValueIndex = 0; | |
| 250 size_t ValuesSize = Values.size(); | |
| 251 size_t AbbrevIndex = 0; | |
| 252 size_t AbbrevSize = Abbrev->getNumOperandInfos(); | |
| 253 bool FoundArray = false; | |
| 254 while (ValueIndex < ValuesSize && AbbrevIndex < AbbrevSize) { | |
| 255 const NaClBitCodeAbbrevOp *Op = &Abbrev->getOperandInfo(AbbrevIndex++); | |
| 256 uint64_t Value = Values[ValueIndex++]; | |
| 257 if (Op->getEncoding() == NaClBitCodeAbbrevOp::Array) { | |
| 258 if (AbbrevIndex + 1 != AbbrevSize) | |
| 259 return false; | |
| 260 Op = &Abbrev->getOperandInfo(AbbrevIndex); | |
| 261 --AbbrevIndex; // i.e. don't advance to next abbreviation op. | |
| 262 FoundArray = true; | |
| 263 } | |
| 264 switch (Op->getEncoding()) { | |
| 265 case NaClBitCodeAbbrevOp::Literal: | |
| 266 if (Value != Op->getValue()) | |
| 267 return false; | |
| 268 continue; | |
| 269 case NaClBitCodeAbbrevOp::Fixed: | |
| 270 if (Value >= (static_cast<uint64_t>(1) < MaxEmitFixedBits) | |
|
jvoung (off chromium)
2015/05/20 22:40:10
I assume this should actually be a shift and not (
Karl
2015/05/21 18:22:07
Yes. Fixing.
| |
| 271 || NaClBitsNeededForValue(Value) > Op->getValue()) | |
| 272 return false; | |
| 273 continue; | |
| 274 case NaClBitCodeAbbrevOp::VBR: | |
| 275 if (Op->getValue() < 2) | |
| 276 return false; | |
| 277 continue; | |
| 278 case NaClBitCodeAbbrevOp::Array: | |
| 279 // This should not happen | |
|
jvoung (off chromium)
2015/05/20 22:40:10
llvm_unreachable(...);
Karl
2015/05/21 18:22:08
Done.
| |
| 280 return false; | |
| 281 case NaClBitCodeAbbrevOp::Char6: | |
| 282 if (!Op->isChar6(Value)) | |
| 283 return false; | |
| 284 continue; | |
| 285 } | |
| 286 } | |
| 287 return ValueIndex == ValuesSize && (FoundArray || AbbrevIndex == AbbrevSize); | |
| 288 } | |
| 289 | |
| 188 NaClMungedBitcode::WriteResults &WriteState::finish( | 290 NaClMungedBitcode::WriteResults &WriteState::finish( |
| 189 NaClBitstreamWriter &Writer, bool RecoverSilently) { | 291 NaClBitstreamWriter &Writer, bool RecoverSilently) { |
| 190 // Be sure blocks are balanced. | 292 // Be sure blocks are balanced. |
| 191 while (!atOutermostScope()) { | 293 while (!atOutermostScope()) { |
| 192 if (!RecoverSilently) | 294 if (!RecoverSilently) |
| 193 RecoverableError() << "Missing close block.\n"; | 295 RecoverableError() << "Missing close block.\n"; |
| 194 if (!exitBlock(Writer)) { | 296 if (!exitBlock(Writer)) { |
| 195 Error() << "Failed to add missing close block at end of file.\n"; | 297 Error() << "Failed to add missing close block at end of file.\n"; |
| 196 break; | 298 break; |
| 197 } | 299 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 << Record << "\n"; | 370 << Record << "\n"; |
| 269 return false; | 371 return false; |
| 270 } | 372 } |
| 271 break; | 373 break; |
| 272 } | 374 } |
| 273 case naclbitc::BLK_CODE_DEFINE_ABBREV: { | 375 case naclbitc::BLK_CODE_DEFINE_ABBREV: { |
| 274 if (Record.Abbrev != naclbitc::DEFINE_ABBREV) { | 376 if (Record.Abbrev != naclbitc::DEFINE_ABBREV) { |
| 275 RecoverableError() | 377 RecoverableError() |
| 276 << "Uses illegal abbreviation index in define abbreviation record: " | 378 << "Uses illegal abbreviation index in define abbreviation record: " |
| 277 << Record << "\n"; | 379 << Record << "\n"; |
| 380 markCurrentBlockWithOmittedAbbreviations(); | |
| 278 if (!Flags.getTryToRecover()) | 381 if (!Flags.getTryToRecover()) |
|
jvoung (off chromium)
2015/05/20 22:40:10
Might be simpler to just return now like the other
Karl
2015/05/21 18:22:07
I agree that the check for omitted abbreviations s
| |
| 279 return false; | 382 return false; |
| 280 } | 383 } |
| 384 if (curBlockHasOmittedAbbreviations()) { | |
| 385 // If reached, a previous abbreviation for the block was omitted. Can't | |
| 386 // generate more abbreviations without having to fix abbreviation indices. | |
| 387 RecoverableError() << "Ignoring abbreviation: " << Record << "\n"; | |
| 388 return Flags.getTryToRecover(); | |
| 389 } | |
| 281 if (getCurWriteBlockID() != naclbitc::BLOCKINFO_BLOCK_ID | 390 if (getCurWriteBlockID() != naclbitc::BLOCKINFO_BLOCK_ID |
| 282 && Writer.getMaxCurAbbrevIndex() >= getCurAbbrevIndexLimit()) { | 391 && Writer.getMaxCurAbbrevIndex() >= getCurAbbrevIndexLimit()) { |
| 283 RecoverableError() << "Exceeds abbreviation index limit of " | 392 RecoverableError() << "Exceeds abbreviation index limit of " |
| 284 << getCurAbbrevIndexLimit() << ": " << Record << "\n"; | 393 << getCurAbbrevIndexLimit() << ": " << Record << "\n"; |
| 285 // Recover by not writing. | 394 // Recover by not writing. |
| 395 markCurrentBlockWithOmittedAbbreviations(); | |
| 286 return Flags.getTryToRecover(); | 396 return Flags.getTryToRecover(); |
| 287 } | 397 } |
| 288 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record); | 398 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record); |
| 289 if (Abbrev == NULL) | 399 if (Abbrev == nullptr) { |
| 400 markCurrentBlockWithOmittedAbbreviations(); | |
| 290 return Flags.getTryToRecover(); | 401 return Flags.getTryToRecover(); |
| 402 } | |
| 291 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) { | 403 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) { |
| 292 Writer.EmitBlockInfoAbbrev(SetBID, Abbrev); | 404 Writer.EmitBlockInfoAbbrev(SetBID, Abbrev); |
| 293 } else { | 405 } else { |
| 294 Writer.EmitAbbrev(Abbrev); | 406 Writer.EmitAbbrev(Abbrev); |
| 295 } | 407 } |
| 296 break; | 408 break; |
| 297 } | 409 } |
| 298 case naclbitc::BLK_CODE_HEADER: | 410 case naclbitc::BLK_CODE_HEADER: |
| 299 // Note: There is no abbreviation index here. Ignore. | 411 // Note: There is no abbreviation index here. Ignore. |
| 300 for (uint64_t Value : Record.Values) | 412 for (uint64_t Value : Record.Values) |
| 301 Writer.Emit(Value, 8); | 413 Writer.Emit(Value, 8); |
| 302 break; | 414 break; |
| 303 default: | 415 default: |
| 304 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD; | 416 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD; |
| 305 if (atOutermostScope()) { | 417 if (atOutermostScope()) { |
| 306 RecoverableError() << "Record outside block: " << Record << "\n"; | 418 RecoverableError() << "Record outside block: " << Record << "\n"; |
| 307 if (!Flags.getTryToRecover()) | 419 if (!Flags.getTryToRecover()) |
| 308 return false; | 420 return false; |
| 309 // Create a dummy block to hold record. | 421 // Create a dummy block to hold record. |
| 310 if (!enterBlock(Writer, UnknownWriteBlockID, | 422 if (!enterBlock(Writer, UnknownWriteBlockID, |
| 311 naclbitc::DEFAULT_MAX_ABBREV, Record)) { | 423 naclbitc::DEFAULT_MAX_ABBREV, Record)) { |
| 312 Error() << "Failed to recover from record outside block\n"; | 424 Error() << "Failed to recover from record outside block\n"; |
| 313 return false; | 425 return false; |
| 314 } | 426 } |
| 315 UsesDefaultAbbrev = true; | 427 UsesDefaultAbbrev = true; |
| 316 } | 428 } |
| 317 if (!UsesDefaultAbbrev | 429 if (!UsesDefaultAbbrev && !canApplyAbbreviation(Writer, Record)) { |
| 318 && !Writer.isUserRecordAbbreviation(Record.Abbrev)) { | 430 // Can't apply abbreviation, figure out why. |
| 319 // Illegal abbreviation index found. | 431 if (Writer.getAbbreviation(Record.Abbrev) != nullptr) { |
| 432 RecoverableError() << "Abbreviation doesn't apply to record: " | |
|
jvoung (off chromium)
2015/05/20 22:40:09
So here the abbreviation exists, but doesn't apply
Karl
2015/05/21 18:22:07
Yes.
| |
| 433 << Record << "\n"; | |
| 434 UsesDefaultAbbrev = true; | |
| 435 WriteRecord(Writer, Record, UsesDefaultAbbrev); | |
|
jvoung (off chromium)
2015/05/20 22:40:09
This and the one below might be the first case whe
Karl
2015/05/21 18:22:08
Done.
| |
| 436 return Flags.getTryToRecover(); | |
| 437 } | |
| 320 if (Flags.getWriteBadAbbrevIndex()) { | 438 if (Flags.getWriteBadAbbrevIndex()) { |
|
jvoung (off chromium)
2015/05/20 22:40:10
Maybe add a comment here. This CL adds the "figure
Karl
2015/05/21 18:22:08
Removed the first comment, and added a comment to
| |
| 321 Error() << "Uses illegal abbreviation index: " << Record << "\n"; | 439 Error() << "Uses illegal abbreviation index: " << Record << "\n"; |
| 322 // Generate bad abbreviation index so that the bitcode reader | 440 // Generate bad abbreviation index so that the bitcode reader |
| 323 // can be tested, and then quit. | 441 // can be tested, and then quit. |
| 324 Results.WroteBadAbbrevIndex = true; | 442 Results.WroteBadAbbrevIndex = true; |
| 325 Writer.EmitCode(Record.Abbrev); | 443 Writer.EmitCode(Record.Abbrev); |
| 326 bool RecoverSilently = true; | 444 bool RecoverSilently = true; |
| 327 finish(Writer, RecoverSilently); | 445 finish(Writer, RecoverSilently); |
| 328 return false; | 446 return false; |
| 329 } | 447 } |
| 330 RecoverableError() << "Uses illegal abbreviation index: " | 448 RecoverableError() << "Uses illegal abbreviation index: " |
| 331 << Record << "\n"; | 449 << Record << "\n"; |
| 332 if (!Flags.getTryToRecover()) | |
| 333 return false; | |
| 334 UsesDefaultAbbrev = true; | 450 UsesDefaultAbbrev = true; |
| 451 WriteRecord(Writer, Record, UsesDefaultAbbrev); | |
| 452 return Flags.getTryToRecover(); | |
| 335 } | 453 } |
| 336 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID | 454 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID |
| 337 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) { | 455 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) { |
| 338 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev, | 456 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev, |
| 339 // based on the SetBID value. Don't bother to generate SetBID record here. | 457 // based on the SetBID value. Don't bother to generate SetBID record here. |
| 340 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev | 458 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev |
| 341 // generate the SetBID record. | 459 // generate the SetBID record. |
| 342 if (NumValues != 1) { | 460 if (NumValues != 1) { |
| 343 Error() << "SetBID record expects 1 value but found " | 461 Error() << "SetBID record expects 1 value but found " |
| 344 << NumValues << ": " << Record << "\n"; | 462 << NumValues << ": " << Record << "\n"; |
| 345 return false; | 463 return false; |
| 346 } | 464 } |
| 347 SetBID = Record.Values[0]; | 465 SetBID = Record.Values[0]; |
| 348 return true; | 466 return true; |
| 349 } | 467 } |
| 350 if (UsesDefaultAbbrev) | 468 WriteRecord(Writer, Record, UsesDefaultAbbrev); |
| 351 Writer.EmitRecord(Record.Code, Record.Values); | 469 break; |
| 352 else | |
| 353 Writer.EmitRecord(Record.Code, Record.Values, Record.Abbrev); | |
| 354 } | 470 } |
| 355 return true; | 471 return true; |
| 356 } | 472 } |
| 357 | 473 |
| 358 static NaClBitCodeAbbrev *deleteAbbrev(NaClBitCodeAbbrev *Abbrev) { | 474 static NaClBitCodeAbbrev *deleteAbbrev(NaClBitCodeAbbrev *Abbrev) { |
| 359 Abbrev->dropRef(); | 475 Abbrev->dropRef(); |
| 360 return nullptr; | 476 return nullptr; |
| 361 } | 477 } |
| 362 | 478 |
| 363 NaClBitCodeAbbrev *WriteState::buildAbbrev( | 479 NaClBitCodeAbbrev *WriteState::buildAbbrev( |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 374 size_t NumAbbreviations = Record.Values[Index++]; | 490 size_t NumAbbreviations = Record.Values[Index++]; |
| 375 if (NumAbbreviations == 0) { | 491 if (NumAbbreviations == 0) { |
| 376 RecoverableError() << "Abbreviation must contain at least one operator: " | 492 RecoverableError() << "Abbreviation must contain at least one operator: " |
| 377 << Record << "\n"; | 493 << Record << "\n"; |
| 378 return deleteAbbrev(Abbrev); | 494 return deleteAbbrev(Abbrev); |
| 379 } | 495 } |
| 380 for (size_t Count = 0; Count < NumAbbreviations; ++Count) { | 496 for (size_t Count = 0; Count < NumAbbreviations; ++Count) { |
| 381 if (Index >= NumValues) { | 497 if (Index >= NumValues) { |
| 382 RecoverableError() | 498 RecoverableError() |
| 383 << "Malformed abbreviation found. Expects " << NumAbbreviations | 499 << "Malformed abbreviation found. Expects " << NumAbbreviations |
| 384 << " operands but ound " << Count << ": " << Record << "\n"; | 500 << " operands but found " << Count << ": " << Record << "\n"; |
| 385 return deleteAbbrev(Abbrev); | 501 return deleteAbbrev(Abbrev); |
| 386 } | 502 } |
| 387 switch (Record.Values[Index++]) { | 503 switch (Record.Values[Index++]) { |
| 388 case 1: | 504 case 1: |
| 389 if (Index >= NumValues) { | 505 if (Index >= NumValues) { |
| 390 RecoverableError() << "Malformed literal abbreviation: " | 506 RecoverableError() << "Malformed literal abbreviation: " |
| 391 << Record << "\n"; | 507 << Record << "\n"; |
| 392 return deleteAbbrev(Abbrev); | 508 return deleteAbbrev(Abbrev); |
| 393 } | 509 } |
| 394 Abbrev->Add(NaClBitCodeAbbrevOp(Record.Values[Index++])); | 510 Abbrev->Add(NaClBitCodeAbbrevOp(Record.Values[Index++])); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6)); | 547 Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6)); |
| 432 break; | 548 break; |
| 433 default: | 549 default: |
| 434 RecoverableError() << "Unknown abbreviation kind " << Kind | 550 RecoverableError() << "Unknown abbreviation kind " << Kind |
| 435 << ": " << Record << "\n"; | 551 << ": " << Record << "\n"; |
| 436 return deleteAbbrev(Abbrev); | 552 return deleteAbbrev(Abbrev); |
| 437 } | 553 } |
| 438 break; | 554 break; |
| 439 } | 555 } |
| 440 default: | 556 default: |
| 441 RecoverableError() << "Error: Bad literal flag " << Record.Values[Index] | 557 RecoverableError() << "Error: Bad abbreviation operand encoding " |
| 442 << ": " << Record << "\n"; | 558 << Record.Values[Index-1] << ": " << Record << "\n"; |
| 443 return deleteAbbrev(Abbrev); | 559 return deleteAbbrev(Abbrev); |
| 444 } | 560 } |
| 445 } | 561 } |
| 446 return Abbrev; | 562 return Abbrev; |
| 447 } | 563 } |
| 448 | 564 |
| 449 } // end of anonymous namespace. | 565 } // end of anonymous namespace. |
| 450 | 566 |
| 451 NaClMungedBitcode::WriteResults NaClMungedBitcode::writeMaybeRepair( | 567 NaClMungedBitcode::WriteResults NaClMungedBitcode::writeMaybeRepair( |
| 452 SmallVectorImpl<char> &Buffer, bool AddHeader, | 568 SmallVectorImpl<char> &Buffer, bool AddHeader, |
| 453 const WriteFlags &Flags) const { | 569 const WriteFlags &Flags) const { |
| 454 NaClBitstreamWriter Writer(Buffer); | 570 NaClBitstreamWriter Writer(Buffer); |
| 455 WriteState State(Flags); | 571 WriteState State(Flags); |
| 456 if (AddHeader) { | 572 if (AddHeader) { |
| 457 NaClWriteHeader(Writer, true); | 573 NaClWriteHeader(Writer, true); |
| 458 } | 574 } |
| 459 for (const NaClBitcodeAbbrevRecord &Record : *this) { | 575 for (const NaClBitcodeAbbrevRecord &Record : *this) { |
| 460 if (!State.emitRecord(Writer, Record)) | 576 if (!State.emitRecord(Writer, Record)) |
| 461 break; | 577 break; |
| 462 } | 578 } |
| 463 bool RecoverSilently = | 579 bool RecoverSilently = |
| 464 State.Results.NumErrors > 0 && !Flags.getTryToRecover(); | 580 State.Results.NumErrors > 0 && !Flags.getTryToRecover(); |
| 465 return State.finish(Writer, RecoverSilently); | 581 return State.finish(Writer, RecoverSilently); |
| 466 } | 582 } |
| OLD | NEW |