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 | 18 |
| 18 using namespace llvm; | 19 using namespace llvm; |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 // For debugging. When true, shows each PNaCl record that is | 23 // For debugging. When true, shows trace information of emitting |
| 23 // emitted to the bitcode file. | 24 // bitcode. |
| 24 static bool DebugEmitRecord = false; | 25 static bool DebugEmit = false; |
| 26 | |
| 27 // Description of current block scope | |
| 28 struct BlockScope { | |
| 29 BlockScope(unsigned CurBlockID, size_t AbbrevIndexLimit) | |
| 30 : CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit) {} | |
| 31 unsigned CurBlockID; | |
| 32 // Defines the maximun value for abbreviation indices in block. | |
|
jvoung (off chromium)
2015/05/13 00:58:16
maximun -> maximum
Karl
2015/05/13 21:39:24
Done.
| |
| 33 size_t AbbrevIndexLimit; | |
| 34 void print(raw_ostream &Out) const { | |
| 35 Out << "BlockScope(ID=" << CurBlockID << ", AbbrevIndexLimit=" | |
| 36 << AbbrevIndexLimit << ")"; | |
| 37 } | |
| 38 }; | |
| 39 | |
| 40 inline raw_ostream &operator<<(raw_ostream &Out, const BlockScope &Scope) { | |
| 41 Scope.print(Out); | |
| 42 return Out; | |
| 43 } | |
| 25 | 44 |
| 26 // State of bitcode writing. | 45 // State of bitcode writing. |
| 27 struct WriteState { | 46 struct WriteState { |
| 28 // The block ID associated with the block being written. | 47 // The block ID associated with records not in any block. |
| 29 int WriteBlockID = -1; | 48 static const unsigned UnknownWriteBlockID = UINT_MAX; |
| 30 // The SetBID for the blockinfo block. | 49 // The SetBID for the blockinfo block. |
| 31 int SetBID = -1; | 50 unsigned SetBID = UnknownWriteBlockID; |
| 32 // The stack of maximum abbreviation indices allowed by block enter record. | 51 // The stack of scopes the writer is in. |
| 33 SmallVector<uint64_t, 3> AbbrevIndexLimitStack; | 52 SmallVector<BlockScope, 3> ScopeStack; |
| 34 // The set of write flags to use. | 53 // The set of write flags to use. |
| 35 const NaClMungedBitcode::WriteFlags &Flags; | 54 const NaClMungedBitcode::WriteFlags &Flags; |
| 36 // The results of the attempted write. | 55 // The results of the attempted write. |
| 37 NaClMungedBitcode::WriteResults Results; | 56 NaClMungedBitcode::WriteResults Results; |
| 38 | 57 |
| 39 WriteState(const NaClMungedBitcode::WriteFlags &Flags) : Flags(Flags) {} | 58 WriteState(const NaClMungedBitcode::WriteFlags &Flags) : Flags(Flags) { |
| 59 BlockScope Scope(UnknownWriteBlockID, naclbitc::DEFAULT_MAX_ABBREV); | |
| 60 ScopeStack.push_back(Scope); | |
| 61 } | |
| 40 | 62 |
| 41 // Returns stream to print error message to. | 63 // Returns stream to print error message to. |
| 42 raw_ostream &Error() { | 64 raw_ostream &Error(); |
| 43 ++Results.NumErrors; | |
| 44 return Flags.getErrStream() << "Error (Block " << WriteBlockID << "): "; | |
| 45 } | |
| 46 | 65 |
| 47 // Returns stream to print error message to, assuming that | 66 // Returns stream to print error message to, assuming that |
| 48 // the error message can be repaired if Flags.TryToRecover is true. | 67 // the error message can be repaired if Flags.TryToRecover is true. |
| 49 raw_ostream &RecoverableError() { | 68 raw_ostream &RecoverableError() { |
| 50 if (Flags.getTryToRecover()) | 69 if (Flags.getTryToRecover()) |
| 51 ++Results.NumRepairs; | 70 ++Results.NumRepairs; |
| 52 return Error(); | 71 return Error(); |
| 53 } | 72 } |
| 54 | 73 |
| 74 bool atOutermostScope() { | |
| 75 assert(!ScopeStack.empty()); | |
| 76 return ScopeStack.size() == 1; | |
| 77 } | |
| 78 | |
| 79 unsigned getCurWriteBlockID() const { | |
| 80 assert(!ScopeStack.empty()); | |
| 81 return ScopeStack.back().CurBlockID; | |
| 82 } | |
| 83 | |
| 84 unsigned getCurAbbrevIndexLimit() const { | |
| 85 assert(!ScopeStack.empty()); | |
| 86 return ScopeStack.back().AbbrevIndexLimit; | |
| 87 } | |
| 88 | |
| 55 // Converts the abbreviation record to the corresponding abbreviation. | 89 // Converts the abbreviation record to the corresponding abbreviation. |
| 56 // Returns nullptr if unable to build abbreviation. | 90 // Returns nullptr if unable to build abbreviation. |
| 57 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); | 91 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); |
| 58 | 92 |
| 59 // Emits the given record to the bitcode file. Returns true if | 93 // Emits the given record to the bitcode file. Returns true if |
| 60 // successful. | 94 // successful. |
| 61 bool emitRecord(NaClBitstreamWriter &Writer, | 95 bool emitRecord(NaClBitstreamWriter &Writer, |
| 62 const NaClBitcodeAbbrevRecord &Record); | 96 const NaClBitcodeAbbrevRecord &Record); |
| 63 | 97 |
| 64 // Adds any missing end blocks to written bitcode. | 98 // Enter the given block |
| 65 void writeMissingEndBlocks(NaClBitstreamWriter &Writer) { | 99 bool enterBlock(NaClBitstreamWriter &Writer, unsigned WriteBlockID, |
| 66 while (!AbbrevIndexLimitStack.empty()) { | 100 unsigned NumBits, const NaClBitcodeAbbrevRecord &Record); |
| 67 Writer.ExitBlock(); | 101 |
| 68 AbbrevIndexLimitStack.pop_back(); | 102 // Exit current block and return to previous block. Silently recovers |
| 69 } | 103 // if at outermost scope. |
| 104 void exitBlock(NaClBitstreamWriter &Writer) { | |
| 105 Writer.ExitBlock(); | |
| 106 ScopeStack.pop_back(); | |
|
jvoung (off chromium)
2015/05/13 00:58:17
Hmm, I don't see how this prevents popping too muc
Karl
2015/05/13 21:39:24
Hmm, I'm confused too. Earlier versions had the ch
| |
| 107 if (DebugEmit) | |
| 108 printScopeStack(errs()); | |
| 109 } | |
| 110 | |
| 111 // Completes the write. | |
| 112 NaClMungedBitcode::WriteResults &finish(NaClBitstreamWriter &Writer, | |
| 113 bool RecoverSilently = false); | |
| 114 | |
| 115 void printScopeStack(raw_ostream &Out) { | |
| 116 Out << "Scope Stack:\n"; | |
| 117 for (auto Scope : ScopeStack) | |
|
jvoung (off chromium)
2015/05/13 00:58:17
auto &Scope ? Not sure if this is one of those cas
Karl
2015/05/13 21:39:23
Done.
| |
| 118 Out << " " << Scope << "\n"; | |
| 70 } | 119 } |
| 71 }; | 120 }; |
| 72 | 121 |
| 122 raw_ostream &WriteState::Error() { | |
| 123 ++Results.NumErrors; | |
| 124 raw_ostream &ErrStrm = Flags.getErrStream(); | |
| 125 unsigned WriteBlockID = getCurWriteBlockID(); | |
| 126 ErrStrm << "Error (Block "; | |
| 127 if (WriteBlockID == UnknownWriteBlockID) | |
| 128 ErrStrm << "unknown"; | |
| 129 else | |
| 130 ErrStrm << WriteBlockID; | |
| 131 return ErrStrm << "): "; | |
| 132 } | |
| 133 | |
| 134 bool WriteState::enterBlock(NaClBitstreamWriter &Writer, unsigned WriteBlockID, | |
| 135 unsigned NumBits, | |
| 136 const NaClBitcodeAbbrevRecord &Record) { | |
| 137 uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1; | |
|
jvoung (off chromium)
2015/05/13 00:58:17
maybe assert NumBits < 64 or some smaller limit --
Karl
2015/05/13 21:39:23
Good point. The code reader/writer assumes 32. Add
| |
| 138 BlockScope Scope(WriteBlockID, MaxAbbrev); | |
| 139 ScopeStack.push_back(Scope); | |
| 140 if (DebugEmit) | |
| 141 printScopeStack(errs()); | |
| 142 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { | |
| 143 unsigned DefaultMaxBits = | |
| 144 NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); | |
| 145 if (NumBits != DefaultMaxBits) { | |
| 146 RecoverableError() | |
| 147 << "Numbits entry for abbreviations record not " | |
| 148 << DefaultMaxBits << " but found " << NumBits << | |
| 149 ": " << Record << "\n"; | |
| 150 if (!Flags.getTryToRecover()) | |
| 151 return false; | |
| 152 } | |
| 153 Writer.EnterBlockInfoBlock(); | |
| 154 } else { | |
| 155 NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); | |
| 156 Writer.EnterSubblock(WriteBlockID, CurCodeLen); | |
| 157 } | |
| 158 return true; | |
| 159 } | |
| 160 | |
| 161 NaClMungedBitcode::WriteResults & WriteState::finish( | |
|
jvoung (off chromium)
2015/05/13 00:58:17
flush the & in the return type to the right
Karl
2015/05/13 21:39:24
Done.
| |
| 162 NaClBitstreamWriter &Writer, bool RecoverSilently) { | |
| 163 // Be sure blocks are balanced. | |
| 164 while (!atOutermostScope()) { | |
| 165 if (!RecoverSilently) | |
| 166 RecoverableError() << "Missing close block.\n"; | |
| 167 exitBlock(Writer); | |
| 168 } | |
| 169 | |
| 170 // Be sure that generated bitcode buffer is word aligned. | |
| 171 if (Writer.GetCurrentBitNo() % 4 * CHAR_BIT) { | |
| 172 if (!RecoverSilently) | |
| 173 RecoverableError() << "Written bitstream not word aligned\n"; | |
| 174 // Force a repair so that the bitstream writer doesn't crash. | |
| 175 Writer.FlushToWord(); | |
| 176 } | |
| 177 return Results; | |
| 178 } | |
| 179 | |
| 73 bool WriteState::emitRecord(NaClBitstreamWriter &Writer, | 180 bool WriteState::emitRecord(NaClBitstreamWriter &Writer, |
| 74 const NaClBitcodeAbbrevRecord &Record) { | 181 const NaClBitcodeAbbrevRecord &Record) { |
| 75 size_t NumValues = Record.Values.size(); | 182 size_t NumValues = Record.Values.size(); |
| 76 if (DebugEmitRecord) { | 183 if (DebugEmit) { |
| 77 errs() << "Emit " << Record.Abbrev << ": <" << Record.Code; | 184 errs() << "Emit " << Record.Abbrev << ": <" << Record.Code; |
| 78 for (size_t i = 0; i < NumValues; ++i) { | 185 for (size_t i = 0; i < NumValues; ++i) { |
| 79 errs() << ", " << Record.Values[i]; | 186 errs() << ", " << Record.Values[i]; |
| 80 } | 187 } |
| 81 errs() << ">\n"; | 188 errs() << ">\n"; |
| 82 } | 189 } |
| 83 | 190 |
| 84 switch (Record.Code) { | 191 switch (Record.Code) { |
| 85 case naclbitc::BLK_CODE_ENTER: { | 192 case naclbitc::BLK_CODE_ENTER: { |
| 86 unsigned NumBits = NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); | 193 unsigned MinNumBits = NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); |
| 87 WriteBlockID = -1; | 194 unsigned WriteBlockID = UnknownWriteBlockID; |
| 195 unsigned NumBits = MinNumBits; | |
| 88 if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) { | 196 if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) { |
| 89 RecoverableError() | 197 RecoverableError() |
| 90 << "Uses illegal abbreviation index in enter block record: " | 198 << "Uses illegal abbreviation index in enter block record: " |
| 91 << Record << "\n"; | 199 << Record << "\n"; |
| 92 if (!Flags.getTryToRecover()) | 200 if (!Flags.getTryToRecover()) |
| 93 return false; | 201 return false; |
| 94 } | 202 } |
| 95 if (NumValues == 2) { | 203 if (NumValues != 2) { |
| 96 WriteBlockID = Record.Values[0]; | 204 RecoverableError() |
| 97 NumBits = Record.Values[1]; | 205 << "Values for enter record should be of size 2, but found " |
| 98 if (NumBits > 32 || NumBits < 2) { | 206 << NumValues << ": " << Record << "\n"; |
| 99 RecoverableError() | 207 if (!Flags.getTryToRecover()) |
| 100 << "Bit size " << NumBits << " for record should be " | 208 return false; |
| 101 << (NumBits > 32 ? "<= 32" : ">= 2") << ": " << Record << "\n"; | |
| 102 if (!Flags.getTryToRecover()) | |
| 103 return false; | |
| 104 NumBits = 32; | |
| 105 } | |
| 106 } else { | |
| 107 Error() << "Values for enter record should be of size 2, but found " | |
| 108 << NumValues << ": " << Record << "\n"; | |
| 109 return false; | |
| 110 } | 209 } |
| 111 uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1; | 210 if (NumValues == 0) |
| 112 AbbrevIndexLimitStack.push_back(MaxAbbrev); | 211 return enterBlock(Writer, WriteBlockID, NumBits, Record); |
| 113 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { | 212 WriteBlockID = Record.Values[0]; |
| 114 unsigned DefaultMaxBits = | 213 if (Record.Values[0] > UINT_MAX) { |
| 115 NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); | 214 RecoverableError() << "Block id must be less than << " << UINT_MAX |
| 116 if (NumBits != DefaultMaxBits) { | 215 << ": " << Record << "\n"; |
| 117 RecoverableError() | 216 if (!Flags.getTryToRecover()) |
| 118 << "Numbits entry for abbreviations record not " | 217 return false; |
| 119 << DefaultMaxBits << " but found " << NumBits << | 218 WriteBlockID = UnknownWriteBlockID; |
| 120 ": " << Record << "\n"; | 219 enterBlock(Writer, WriteBlockID, NumBits, Record); |
|
jvoung (off chromium)
2015/05/13 00:58:17
return enterBlock(...);
To avoid falling through
jvoung (off chromium)
2015/05/13 00:58:17
At this point, it's still possible for NumValues =
Karl
2015/05/13 21:39:24
Removing call to writeBlock(). Rather, let the cod
| |
| 121 if (!Flags.getTryToRecover()) | |
| 122 return false; | |
| 123 } | |
| 124 Writer.EnterBlockInfoBlock(); | |
| 125 } else { | |
| 126 NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); | |
| 127 Writer.EnterSubblock(WriteBlockID, CurCodeLen); | |
| 128 } | 220 } |
| 129 break; | 221 if (NumValues < 2) |
| 222 return enterBlock(Writer, WriteBlockID, NumBits, Record); | |
| 223 NumBits = Record.Values[1]; | |
| 224 if (NumBits > 32 || MinNumBits < 2) { | |
|
jvoung (off chromium)
2015/05/13 00:58:17
"MinNumBits < 2" MinNumBits is pretty much a const
Karl
2015/05/13 21:39:24
Good catch. Using MinNumBits.
| |
| 225 raw_ostream &ErrStrm = RecoverableError(); | |
| 226 ErrStrm << "Bit size " << NumBits << " for record should be "; | |
| 227 if (NumBits > 32) | |
| 228 ErrStrm << "<= 32"; | |
| 229 else | |
| 230 ErrStrm << ">= " << MinNumBits; | |
| 231 ErrStrm << ": " << Record << "\n"; | |
| 232 if (!Flags.getTryToRecover()) | |
| 233 return false; | |
| 234 NumBits = 32; | |
| 235 } | |
| 236 return enterBlock(Writer, WriteBlockID, NumBits, Record); | |
| 130 } | 237 } |
| 131 case naclbitc::BLK_CODE_EXIT: | 238 case naclbitc::BLK_CODE_EXIT: |
| 239 if (atOutermostScope()) { | |
| 240 RecoverableError() | |
| 241 << "Extraneous exit block: " << Record << "\n"; | |
| 242 if (!Flags.getTryToRecover()) | |
| 243 return false; | |
| 244 break; | |
| 245 } | |
| 132 if (Record.Abbrev != naclbitc::END_BLOCK) { | 246 if (Record.Abbrev != naclbitc::END_BLOCK) { |
| 133 RecoverableError() | 247 RecoverableError() |
| 134 << "Uses illegal abbreviation index in exit block record: " | 248 << "Uses illegal abbreviation index in exit block record: " |
| 135 << Record << "\n"; | 249 << Record << "\n"; |
| 136 if (!Flags.getTryToRecover()) | 250 if (!Flags.getTryToRecover()) |
| 137 return false; | 251 return false; |
| 138 } | 252 } |
| 139 if (NumValues != 0) { | 253 if (NumValues != 0) { |
| 140 RecoverableError() << "Exit block should not have values: " | 254 RecoverableError() << "Exit block should not have values: " |
| 141 << Record << "\n"; | 255 << Record << "\n"; |
| 142 if (!Flags.getTryToRecover()) | 256 if (!Flags.getTryToRecover()) |
| 143 return false; | 257 return false; |
| 144 } | 258 } |
| 145 if (!AbbrevIndexLimitStack.empty()) | 259 exitBlock(Writer); |
|
jvoung (off chromium)
2015/05/13 22:24:05
btw: I was about to suggest adding LLVM_ATTRIBUTE_
Karl
2015/05/14 17:08:11
Added and fixed code (3 cases). In all three, they
| |
| 146 AbbrevIndexLimitStack.pop_back(); | |
| 147 Writer.ExitBlock(); | |
| 148 break; | 260 break; |
| 149 case naclbitc::BLK_CODE_DEFINE_ABBREV: { | 261 case naclbitc::BLK_CODE_DEFINE_ABBREV: { |
| 150 if (Record.Abbrev != naclbitc::DEFINE_ABBREV) { | 262 if (Record.Abbrev != naclbitc::DEFINE_ABBREV) { |
| 151 RecoverableError() | 263 RecoverableError() |
| 152 << "Uses illegal abbreviation index in define abbreviation record: " | 264 << "Uses illegal abbreviation index in define abbreviation record: " |
| 153 << Record << "\n"; | 265 << Record << "\n"; |
| 154 if (!Flags.getTryToRecover()) | 266 if (!Flags.getTryToRecover()) |
| 155 return false; | 267 return false; |
| 156 } | 268 } |
| 269 if (getCurWriteBlockID() != naclbitc::BLOCKINFO_BLOCK_ID | |
| 270 && Writer.getMaxCurAbbrevIndex() >= getCurAbbrevIndexLimit()) { | |
|
jvoung (off chromium)
2015/05/13 00:58:17
">= "
">= "
Karl
2015/05/13 21:39:23
Done.
jvoung (off chromium)
2015/05/13 22:24:06
Ping =) >=
Karl
2015/05/14 17:08:11
Done.
| |
| 271 RecoverableError() << "Exceeds abbreviation index limit of " | |
| 272 << getCurAbbrevIndexLimit() << ": " << Record << "\n"; | |
| 273 // Recover by not writing. | |
| 274 return Flags.getTryToRecover(); | |
| 275 } | |
| 157 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record); | 276 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record); |
| 158 if (Abbrev == NULL) | 277 if (Abbrev == NULL) |
| 159 return Flags.getTryToRecover(); | 278 return Flags.getTryToRecover(); |
| 160 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { | 279 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) { |
| 161 Writer.EmitBlockInfoAbbrev(SetBID, Abbrev); | 280 Writer.EmitBlockInfoAbbrev(SetBID, Abbrev); |
| 162 } else { | 281 } else { |
| 163 Writer.EmitAbbrev(Abbrev); | 282 Writer.EmitAbbrev(Abbrev); |
| 164 } | 283 } |
| 165 break; | 284 break; |
| 166 } | 285 } |
| 167 case naclbitc::BLK_CODE_HEADER: | 286 case naclbitc::BLK_CODE_HEADER: |
| 168 // Note: There is no abbreviation index here. Ignore. | 287 // Note: There is no abbreviation index here. Ignore. |
| 169 for (uint64_t Value : Record.Values) | 288 for (uint64_t Value : Record.Values) |
| 170 Writer.Emit(Value, 8); | 289 Writer.Emit(Value, 8); |
| 171 break; | 290 break; |
| 172 default: | 291 default: |
| 173 if (AbbrevIndexLimitStack.empty()) { | 292 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD; |
| 174 Error() << "Can't write record outside record block: " << Record << "\n"; | 293 if (atOutermostScope()) { |
| 175 return false; | 294 RecoverableError() << "Record outside block: " << Record << "\n"; |
| 295 if (!Flags.getTryToRecover()) | |
| 296 return false; | |
| 297 // Create a dummy block to hold record. | |
| 298 enterBlock(Writer, UnknownWriteBlockID, naclbitc::DEFAULT_MAX_ABBREV, | |
| 299 Record); | |
| 300 UsesDefaultAbbrev = true; | |
| 176 } | 301 } |
| 177 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD; | |
| 178 if (!UsesDefaultAbbrev | 302 if (!UsesDefaultAbbrev |
| 179 && !Writer.isUserRecordAbbreviation(Record.Abbrev)) { | 303 && !Writer.isUserRecordAbbreviation(Record.Abbrev)) { |
| 180 // Illegal abbreviation index found. | 304 // Illegal abbreviation index found. |
| 181 if (Flags.getWriteBadAbbrevIndex()) { | 305 if (Flags.getWriteBadAbbrevIndex()) { |
| 182 Error() << "Uses illegal abbreviation index: " << Record << "\n"; | 306 Error() << "Uses illegal abbreviation index: " << Record << "\n"; |
| 183 // Generate bad abbreviation index so that the bitcode reader | 307 // Generate bad abbreviation index so that the bitcode reader |
| 184 // can be tested. | 308 // can be tested, and then quit. |
| 185 Results.WroteBadAbbrevIndex = true; | 309 Results.WroteBadAbbrevIndex = true; |
| 186 Writer.EmitCode(Record.Abbrev); | 310 Writer.EmitCode(Record.Abbrev); |
| 187 // Note: We need to close blocks or the bitcode Writer will terminate | 311 finish(Writer, /* RecoverSilently = */ true); |
| 188 // due to assertions. | 312 return true; |
| 189 writeMissingEndBlocks(Writer); | |
| 190 return false; | |
| 191 } | 313 } |
| 192 RecoverableError() << "Uses illegal abbreviation index: " | 314 RecoverableError() << "Uses illegal abbreviation index: " |
| 193 << Record << "\n"; | 315 << Record << "\n"; |
| 194 if (!Flags.getTryToRecover()) | 316 if (!Flags.getTryToRecover()) |
| 195 return false; | 317 return false; |
| 196 UsesDefaultAbbrev = true; | 318 UsesDefaultAbbrev = true; |
| 197 } | 319 } |
| 198 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID | 320 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID |
| 199 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) { | 321 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) { |
| 200 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev, | 322 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev, |
| 201 // based on the SetBID value. Don't bother to generate SetBID record here. | 323 // based on the SetBID value. Don't bother to generate SetBID record here. |
| 202 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev | 324 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev |
| 203 // generate the SetBID record. | 325 // generate the SetBID record. |
| 204 if (NumValues != 1) { | 326 if (NumValues != 1) { |
| 205 Error() << "SetBID record expects 1 value but found " | 327 Error() << "SetBID record expects 1 value but found " |
| 206 << NumValues << ": " << Record << "\n"; | 328 << NumValues << ": " << Record << "\n"; |
| 207 return false; | 329 return false; |
| 208 } | 330 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 const WriteFlags &Flags) const { | 437 const WriteFlags &Flags) const { |
| 316 NaClBitstreamWriter Writer(Buffer); | 438 NaClBitstreamWriter Writer(Buffer); |
| 317 WriteState State(Flags); | 439 WriteState State(Flags); |
| 318 if (AddHeader) { | 440 if (AddHeader) { |
| 319 NaClWriteHeader(Writer, true); | 441 NaClWriteHeader(Writer, true); |
| 320 } | 442 } |
| 321 for (const NaClBitcodeAbbrevRecord &Record : *this) { | 443 for (const NaClBitcodeAbbrevRecord &Record : *this) { |
| 322 if (!State.emitRecord(Writer, Record)) | 444 if (!State.emitRecord(Writer, Record)) |
| 323 break; | 445 break; |
| 324 } | 446 } |
| 325 if (!State.AbbrevIndexLimitStack.empty()) { | 447 return State.finish(Writer); |
| 326 State.RecoverableError() | |
| 327 << "Bitcode missing " << State.AbbrevIndexLimitStack.size() | |
| 328 << " close blocks.\n"; | |
| 329 if (Flags.getTryToRecover()) | |
| 330 State.writeMissingEndBlocks(Writer); | |
| 331 } | |
| 332 return State.Results; | |
| 333 } | 448 } |
| OLD | NEW |