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 maximum value for abbreviation indices in block. |
| 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; |
| 57 // The minimum number of bits allowed to be specified in a block. |
| 58 const unsigned BlockMinBits; |
38 | 59 |
39 WriteState(const NaClMungedBitcode::WriteFlags &Flags) : Flags(Flags) {} | 60 WriteState(const NaClMungedBitcode::WriteFlags &Flags) |
| 61 : Flags(Flags), |
| 62 BlockMinBits(NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV)) { |
| 63 BlockScope Scope(UnknownWriteBlockID, naclbitc::DEFAULT_MAX_ABBREV); |
| 64 ScopeStack.push_back(Scope); |
| 65 } |
40 | 66 |
41 // Returns stream to print error message to. | 67 // Returns stream to print error message to. |
42 raw_ostream &Error() { | 68 raw_ostream &Error(); |
43 ++Results.NumErrors; | |
44 return Flags.getErrStream() << "Error (Block " << WriteBlockID << "): "; | |
45 } | |
46 | 69 |
47 // Returns stream to print error message to, assuming that | 70 // Returns stream to print error message to, assuming that |
48 // the error message can be repaired if Flags.TryToRecover is true. | 71 // the error message can be repaired if Flags.TryToRecover is true. |
49 raw_ostream &RecoverableError() { | 72 raw_ostream &RecoverableError() { |
50 if (Flags.getTryToRecover()) | 73 if (Flags.getTryToRecover()) |
51 ++Results.NumRepairs; | 74 ++Results.NumRepairs; |
52 return Error(); | 75 return Error(); |
53 } | 76 } |
54 | 77 |
| 78 bool atOutermostScope() { |
| 79 assert(!ScopeStack.empty()); |
| 80 return ScopeStack.size() == 1; |
| 81 } |
| 82 |
| 83 unsigned getCurWriteBlockID() const { |
| 84 assert(!ScopeStack.empty()); |
| 85 return ScopeStack.back().CurBlockID; |
| 86 } |
| 87 |
| 88 unsigned getCurAbbrevIndexLimit() const { |
| 89 assert(!ScopeStack.empty()); |
| 90 return ScopeStack.back().AbbrevIndexLimit; |
| 91 } |
| 92 |
55 // Converts the abbreviation record to the corresponding abbreviation. | 93 // Converts the abbreviation record to the corresponding abbreviation. |
56 // Returns nullptr if unable to build abbreviation. | 94 // Returns nullptr if unable to build abbreviation. |
57 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); | 95 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); |
58 | 96 |
59 // Emits the given record to the bitcode file. Returns true if | 97 // Emits the given record to the bitcode file. Returns true if |
60 // successful. | 98 // successful. |
61 bool emitRecord(NaClBitstreamWriter &Writer, | 99 bool LLVM_ATTRIBUTE_UNUSED_RESULT |
62 const NaClBitcodeAbbrevRecord &Record); | 100 emitRecord(NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record)
; |
63 | 101 |
64 // Adds any missing end blocks to written bitcode. | 102 // Enter the given block |
65 void writeMissingEndBlocks(NaClBitstreamWriter &Writer) { | 103 bool LLVM_ATTRIBUTE_UNUSED_RESULT |
66 while (!AbbrevIndexLimitStack.empty()) { | 104 enterBlock(NaClBitstreamWriter &Writer, uint64_t WriteBlockID, |
67 Writer.ExitBlock(); | 105 uint64_t NumBits, const NaClBitcodeAbbrevRecord &Record); |
68 AbbrevIndexLimitStack.pop_back(); | 106 |
| 107 // Exit current block and return to previous block. Silently recovers |
| 108 // if at outermost scope. |
| 109 bool LLVM_ATTRIBUTE_UNUSED_RESULT |
| 110 exitBlock(NaClBitstreamWriter &Writer, |
| 111 const NaClBitcodeAbbrevRecord *Record = nullptr) { |
| 112 if (atOutermostScope()) |
| 113 return false; |
| 114 Writer.ExitBlock(); |
| 115 ScopeStack.pop_back(); |
| 116 if (DebugEmit) |
| 117 printScopeStack(errs()); |
| 118 return true; |
| 119 } |
| 120 |
| 121 // Completes the write. |
| 122 NaClMungedBitcode::WriteResults &finish(NaClBitstreamWriter &Writer, |
| 123 bool RecoverSilently); |
| 124 |
| 125 void printScopeStack(raw_ostream &Out) { |
| 126 Out << "Scope Stack:\n"; |
| 127 for (auto &Scope : ScopeStack) |
| 128 Out << " " << Scope << "\n"; |
| 129 } |
| 130 }; |
| 131 |
| 132 raw_ostream &WriteState::Error() { |
| 133 ++Results.NumErrors; |
| 134 raw_ostream &ErrStrm = Flags.getErrStream(); |
| 135 unsigned WriteBlockID = getCurWriteBlockID(); |
| 136 ErrStrm << "Error (Block "; |
| 137 if (WriteBlockID == UnknownWriteBlockID) |
| 138 ErrStrm << "unknown"; |
| 139 else |
| 140 ErrStrm << WriteBlockID; |
| 141 return ErrStrm << "): "; |
| 142 } |
| 143 |
| 144 bool WriteState::enterBlock(NaClBitstreamWriter &Writer, uint64_t WriteBlockID, |
| 145 uint64_t NumBits, |
| 146 const NaClBitcodeAbbrevRecord &Record) { |
| 147 if (NumBits < BlockMinBits || NumBits > naclbitc::MaxAbbrevWidth) { |
| 148 RecoverableError() |
| 149 << "Block index bit limit " << NumBits << " invalid. Must be in [" |
| 150 << BlockMinBits << ".." << naclbitc::MaxAbbrevWidth << "]: " |
| 151 << Record << "\n"; |
| 152 if (!Flags.getTryToRecover()) |
| 153 return false; |
| 154 NumBits = naclbitc::MaxAbbrevWidth; |
| 155 } |
| 156 if (WriteBlockID > UINT_MAX) { |
| 157 RecoverableError() << "Block id must be <= " << UINT_MAX |
| 158 << ": " << Record << "\n"; |
| 159 if (!Flags.getTryToRecover()) |
| 160 return false; |
| 161 WriteBlockID = UnknownWriteBlockID; |
| 162 } |
| 163 |
| 164 uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1; |
| 165 BlockScope Scope(WriteBlockID, MaxAbbrev); |
| 166 ScopeStack.push_back(Scope); |
| 167 if (DebugEmit) |
| 168 printScopeStack(errs()); |
| 169 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { |
| 170 unsigned DefaultMaxBits = |
| 171 NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); |
| 172 if (NumBits != DefaultMaxBits) { |
| 173 RecoverableError() |
| 174 << "Numbits entry for abbreviations record not " |
| 175 << DefaultMaxBits << " but found " << NumBits << |
| 176 ": " << Record << "\n"; |
| 177 if (!Flags.getTryToRecover()) |
| 178 return false; |
| 179 } |
| 180 Writer.EnterBlockInfoBlock(); |
| 181 } else { |
| 182 NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); |
| 183 Writer.EnterSubblock(WriteBlockID, CurCodeLen); |
| 184 } |
| 185 return true; |
| 186 } |
| 187 |
| 188 NaClMungedBitcode::WriteResults &WriteState::finish( |
| 189 NaClBitstreamWriter &Writer, bool RecoverSilently) { |
| 190 // Be sure blocks are balanced. |
| 191 while (!atOutermostScope()) { |
| 192 if (!RecoverSilently) |
| 193 RecoverableError() << "Missing close block.\n"; |
| 194 if (!exitBlock(Writer)) { |
| 195 Error() << "Failed to add missing close block at end of file.\n"; |
| 196 break; |
69 } | 197 } |
70 } | 198 } |
71 }; | 199 |
| 200 // Be sure that generated bitcode buffer is word aligned. |
| 201 if (Writer.GetCurrentBitNo() % 4 * CHAR_BIT) { |
| 202 if (!RecoverSilently) |
| 203 RecoverableError() << "Written bitstream not word aligned\n"; |
| 204 // Force a repair so that the bitstream writer doesn't crash. |
| 205 Writer.FlushToWord(); |
| 206 } |
| 207 return Results; |
| 208 } |
72 | 209 |
73 bool WriteState::emitRecord(NaClBitstreamWriter &Writer, | 210 bool WriteState::emitRecord(NaClBitstreamWriter &Writer, |
74 const NaClBitcodeAbbrevRecord &Record) { | 211 const NaClBitcodeAbbrevRecord &Record) { |
75 size_t NumValues = Record.Values.size(); | 212 size_t NumValues = Record.Values.size(); |
76 if (DebugEmitRecord) { | 213 if (DebugEmit) { |
77 errs() << "Emit " << Record.Abbrev << ": <" << Record.Code; | 214 errs() << "Emit " << Record.Abbrev << ": <" << Record.Code; |
78 for (size_t i = 0; i < NumValues; ++i) { | 215 for (size_t i = 0; i < NumValues; ++i) { |
79 errs() << ", " << Record.Values[i]; | 216 errs() << ", " << Record.Values[i]; |
80 } | 217 } |
81 errs() << ">\n"; | 218 errs() << ">\n"; |
82 } | 219 } |
83 | 220 |
84 switch (Record.Code) { | 221 switch (Record.Code) { |
85 case naclbitc::BLK_CODE_ENTER: { | 222 case naclbitc::BLK_CODE_ENTER: { |
86 unsigned NumBits = NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); | 223 uint64_t WriteBlockID = UnknownWriteBlockID; |
87 WriteBlockID = -1; | 224 uint64_t NumBits = naclbitc::MaxAbbrevWidth; // Default to safest value. |
88 if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) { | 225 if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) { |
89 RecoverableError() | 226 RecoverableError() |
90 << "Uses illegal abbreviation index in enter block record: " | 227 << "Uses illegal abbreviation index in enter block record: " |
91 << Record << "\n"; | 228 << Record << "\n"; |
92 if (!Flags.getTryToRecover()) | 229 if (!Flags.getTryToRecover()) |
93 return false; | 230 return false; |
94 } | 231 } |
95 if (NumValues == 2) { | 232 if (NumValues != 2) { |
| 233 RecoverableError() |
| 234 << "Values for enter record should be of size 2, but found " |
| 235 << NumValues << ": " << Record << "\n"; |
| 236 if (!Flags.getTryToRecover()) |
| 237 return false; |
| 238 } |
| 239 if (NumValues > 0) |
96 WriteBlockID = Record.Values[0]; | 240 WriteBlockID = Record.Values[0]; |
| 241 if (NumValues > 1) |
97 NumBits = Record.Values[1]; | 242 NumBits = Record.Values[1]; |
98 if (NumBits > 32 || NumBits < 2) { | 243 return enterBlock(Writer, WriteBlockID, NumBits, Record); |
99 RecoverableError() | 244 } |
100 << "Bit size " << NumBits << " for record should be " | 245 case naclbitc::BLK_CODE_EXIT: { |
101 << (NumBits > 32 ? "<= 32" : ">= 2") << ": " << Record << "\n"; | 246 if (atOutermostScope()) { |
102 if (!Flags.getTryToRecover()) | 247 RecoverableError() |
103 return false; | 248 << "Extraneous exit block: " << Record << "\n"; |
104 NumBits = 32; | 249 if (!Flags.getTryToRecover()) |
105 } | 250 return false; |
106 } else { | 251 break; |
107 Error() << "Values for enter record should be of size 2, but found " | |
108 << NumValues << ": " << Record << "\n"; | |
109 return false; | |
110 } | 252 } |
111 uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1; | |
112 AbbrevIndexLimitStack.push_back(MaxAbbrev); | |
113 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { | |
114 unsigned DefaultMaxBits = | |
115 NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV); | |
116 if (NumBits != DefaultMaxBits) { | |
117 RecoverableError() | |
118 << "Numbits entry for abbreviations record not " | |
119 << DefaultMaxBits << " but found " << NumBits << | |
120 ": " << Record << "\n"; | |
121 if (!Flags.getTryToRecover()) | |
122 return false; | |
123 } | |
124 Writer.EnterBlockInfoBlock(); | |
125 } else { | |
126 NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); | |
127 Writer.EnterSubblock(WriteBlockID, CurCodeLen); | |
128 } | |
129 break; | |
130 } | |
131 case naclbitc::BLK_CODE_EXIT: | |
132 if (Record.Abbrev != naclbitc::END_BLOCK) { | 253 if (Record.Abbrev != naclbitc::END_BLOCK) { |
133 RecoverableError() | 254 RecoverableError() |
134 << "Uses illegal abbreviation index in exit block record: " | 255 << "Uses illegal abbreviation index in exit block record: " |
135 << Record << "\n"; | 256 << Record << "\n"; |
136 if (!Flags.getTryToRecover()) | 257 if (!Flags.getTryToRecover()) |
137 return false; | 258 return false; |
138 } | 259 } |
139 if (NumValues != 0) { | 260 if (NumValues != 0) { |
140 RecoverableError() << "Exit block should not have values: " | 261 RecoverableError() << "Exit block should not have values: " |
141 << Record << "\n"; | 262 << Record << "\n"; |
142 if (!Flags.getTryToRecover()) | 263 if (!Flags.getTryToRecover()) |
143 return false; | 264 return false; |
144 } | 265 } |
145 if (!AbbrevIndexLimitStack.empty()) | 266 if (!exitBlock(Writer)) { |
146 AbbrevIndexLimitStack.pop_back(); | 267 Error() << "Failed to write exit block, can't continue: " |
147 Writer.ExitBlock(); | 268 << Record << "\n"; |
| 269 return false; |
| 270 } |
148 break; | 271 break; |
| 272 } |
149 case naclbitc::BLK_CODE_DEFINE_ABBREV: { | 273 case naclbitc::BLK_CODE_DEFINE_ABBREV: { |
150 if (Record.Abbrev != naclbitc::DEFINE_ABBREV) { | 274 if (Record.Abbrev != naclbitc::DEFINE_ABBREV) { |
151 RecoverableError() | 275 RecoverableError() |
152 << "Uses illegal abbreviation index in define abbreviation record: " | 276 << "Uses illegal abbreviation index in define abbreviation record: " |
153 << Record << "\n"; | 277 << Record << "\n"; |
154 if (!Flags.getTryToRecover()) | 278 if (!Flags.getTryToRecover()) |
155 return false; | 279 return false; |
156 } | 280 } |
| 281 if (getCurWriteBlockID() != naclbitc::BLOCKINFO_BLOCK_ID |
| 282 && Writer.getMaxCurAbbrevIndex() >= getCurAbbrevIndexLimit()) { |
| 283 RecoverableError() << "Exceeds abbreviation index limit of " |
| 284 << getCurAbbrevIndexLimit() << ": " << Record << "\n"; |
| 285 // Recover by not writing. |
| 286 return Flags.getTryToRecover(); |
| 287 } |
157 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record); | 288 NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record); |
158 if (Abbrev == NULL) | 289 if (Abbrev == NULL) |
159 return Flags.getTryToRecover(); | 290 return Flags.getTryToRecover(); |
160 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { | 291 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) { |
161 Writer.EmitBlockInfoAbbrev(SetBID, Abbrev); | 292 Writer.EmitBlockInfoAbbrev(SetBID, Abbrev); |
162 } else { | 293 } else { |
163 Writer.EmitAbbrev(Abbrev); | 294 Writer.EmitAbbrev(Abbrev); |
164 } | 295 } |
165 break; | 296 break; |
166 } | 297 } |
167 case naclbitc::BLK_CODE_HEADER: | 298 case naclbitc::BLK_CODE_HEADER: |
168 // Note: There is no abbreviation index here. Ignore. | 299 // Note: There is no abbreviation index here. Ignore. |
169 for (uint64_t Value : Record.Values) | 300 for (uint64_t Value : Record.Values) |
170 Writer.Emit(Value, 8); | 301 Writer.Emit(Value, 8); |
171 break; | 302 break; |
172 default: | 303 default: |
173 if (AbbrevIndexLimitStack.empty()) { | 304 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD; |
174 Error() << "Can't write record outside record block: " << Record << "\n"; | 305 if (atOutermostScope()) { |
175 return false; | 306 RecoverableError() << "Record outside block: " << Record << "\n"; |
| 307 if (!Flags.getTryToRecover()) |
| 308 return false; |
| 309 // Create a dummy block to hold record. |
| 310 if (!enterBlock(Writer, UnknownWriteBlockID, |
| 311 naclbitc::DEFAULT_MAX_ABBREV, Record)) { |
| 312 Error() << "Failed to recover from record outside block\n"; |
| 313 return false; |
| 314 } |
| 315 UsesDefaultAbbrev = true; |
176 } | 316 } |
177 bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD; | |
178 if (!UsesDefaultAbbrev | 317 if (!UsesDefaultAbbrev |
179 && !Writer.isUserRecordAbbreviation(Record.Abbrev)) { | 318 && !Writer.isUserRecordAbbreviation(Record.Abbrev)) { |
180 // Illegal abbreviation index found. | 319 // Illegal abbreviation index found. |
181 if (Flags.getWriteBadAbbrevIndex()) { | 320 if (Flags.getWriteBadAbbrevIndex()) { |
182 Error() << "Uses illegal abbreviation index: " << Record << "\n"; | 321 Error() << "Uses illegal abbreviation index: " << Record << "\n"; |
183 // Generate bad abbreviation index so that the bitcode reader | 322 // Generate bad abbreviation index so that the bitcode reader |
184 // can be tested. | 323 // can be tested, and then quit. |
185 Results.WroteBadAbbrevIndex = true; | 324 Results.WroteBadAbbrevIndex = true; |
186 Writer.EmitCode(Record.Abbrev); | 325 Writer.EmitCode(Record.Abbrev); |
187 // Note: We need to close blocks or the bitcode Writer will terminate | 326 bool RecoverSilently = true; |
188 // due to assertions. | 327 finish(Writer, RecoverSilently); |
189 writeMissingEndBlocks(Writer); | |
190 return false; | 328 return false; |
191 } | 329 } |
192 RecoverableError() << "Uses illegal abbreviation index: " | 330 RecoverableError() << "Uses illegal abbreviation index: " |
193 << Record << "\n"; | 331 << Record << "\n"; |
194 if (!Flags.getTryToRecover()) | 332 if (!Flags.getTryToRecover()) |
195 return false; | 333 return false; |
196 UsesDefaultAbbrev = true; | 334 UsesDefaultAbbrev = true; |
197 } | 335 } |
198 if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID | 336 if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID |
199 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) { | 337 && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) { |
200 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev, | 338 // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev, |
201 // based on the SetBID value. Don't bother to generate SetBID record here. | 339 // based on the SetBID value. Don't bother to generate SetBID record here. |
202 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev | 340 // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev |
203 // generate the SetBID record. | 341 // generate the SetBID record. |
204 if (NumValues != 1) { | 342 if (NumValues != 1) { |
205 Error() << "SetBID record expects 1 value but found " | 343 Error() << "SetBID record expects 1 value but found " |
206 << NumValues << ": " << Record << "\n"; | 344 << NumValues << ": " << Record << "\n"; |
207 return false; | 345 return false; |
208 } | 346 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 const WriteFlags &Flags) const { | 453 const WriteFlags &Flags) const { |
316 NaClBitstreamWriter Writer(Buffer); | 454 NaClBitstreamWriter Writer(Buffer); |
317 WriteState State(Flags); | 455 WriteState State(Flags); |
318 if (AddHeader) { | 456 if (AddHeader) { |
319 NaClWriteHeader(Writer, true); | 457 NaClWriteHeader(Writer, true); |
320 } | 458 } |
321 for (const NaClBitcodeAbbrevRecord &Record : *this) { | 459 for (const NaClBitcodeAbbrevRecord &Record : *this) { |
322 if (!State.emitRecord(Writer, Record)) | 460 if (!State.emitRecord(Writer, Record)) |
323 break; | 461 break; |
324 } | 462 } |
325 if (!State.AbbrevIndexLimitStack.empty()) { | 463 bool RecoverSilently = |
326 State.RecoverableError() | 464 State.Results.NumErrors > 0 && !Flags.getTryToRecover(); |
327 << "Bitcode missing " << State.AbbrevIndexLimitStack.size() | 465 return State.finish(Writer, RecoverSilently); |
328 << " close blocks.\n"; | |
329 if (Flags.getTryToRecover()) | |
330 State.writeMissingEndBlocks(Writer); | |
331 } | |
332 return State.Results; | |
333 } | 466 } |
OLD | NEW |