16
16
#include " llvm/Bitcode/NaCl/NaClReaderWriter.h"
17
17
#include " llvm/Support/raw_ostream.h"
18
18
19
+ #include < set>
20
+
19
21
using namespace llvm ;
20
22
21
23
namespace {
@@ -27,13 +29,19 @@ static bool DebugEmit = false;
27
29
// Description of current block scope
28
30
struct BlockScope {
29
31
BlockScope (unsigned CurBlockID, size_t AbbrevIndexLimit)
30
- : CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit) {}
32
+ : CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit),
33
+ OmittedAbbreviations (false ) {}
31
34
unsigned CurBlockID;
32
35
// Defines the maximum value for abbreviation indices in block.
33
36
size_t AbbrevIndexLimit;
37
+ // Defines if an abbreviation definition was omitted (i.e. not
38
+ // written) from this block. Used to turn off writing further
39
+ // abbreviation definitions for this block.
40
+ bool OmittedAbbreviations;
34
41
void print (raw_ostream &Out) const {
35
42
Out << " BlockScope(ID=" << CurBlockID << " , AbbrevIndexLimit="
36
- << AbbrevIndexLimit << " )" ;
43
+ << AbbrevIndexLimit << " OmittedAbbreviations="
44
+ << OmittedAbbreviations << " )" ;
37
45
}
38
46
};
39
47
@@ -49,13 +57,16 @@ struct WriteState {
49
57
// The SetBID for the blockinfo block.
50
58
unsigned SetBID = UnknownWriteBlockID;
51
59
// The stack of scopes the writer is in.
52
- SmallVector<BlockScope, 3 > ScopeStack;
60
+ SmallVector<BlockScope, 4 > ScopeStack;
53
61
// The set of write flags to use.
54
62
const NaClMungedBitcode::WriteFlags &Flags;
55
63
// The results of the attempted write.
56
64
NaClMungedBitcode::WriteResults Results;
57
65
// The minimum number of bits allowed to be specified in a block.
58
66
const unsigned BlockMinBits;
67
+ // The set of block IDs for which abbreviation definitions have been
68
+ // omitted in the blockinfo block.
69
+ std::set<unsigned > BlocksWithOmittedAbbrevs;
59
70
60
71
WriteState (const NaClMungedBitcode::WriteFlags &Flags)
61
72
: Flags(Flags),
@@ -90,14 +101,32 @@ struct WriteState {
90
101
return ScopeStack.back ().AbbrevIndexLimit ;
91
102
}
92
103
104
+ // Returns whether any abbreviation definitions were not written to
105
+ // the bitcode buffer.
106
+ bool curBlockHasOmittedAbbreviations () const {
107
+ assert (!ScopeStack.empty ());
108
+ return ScopeStack.back ().OmittedAbbreviations
109
+ || BlocksWithOmittedAbbrevs.count (getCurWriteBlockID ());
110
+ }
111
+
112
+ // Marks that an abbreviation definition is being omitted (i.e. not
113
+ // written) for the current block.
114
+ void markCurrentBlockWithOmittedAbbreviations () {
115
+ assert (!ScopeStack.empty ());
116
+ ScopeStack.back ().OmittedAbbreviations = true ;
117
+ if (getCurWriteBlockID () == naclbitc::BLOCKINFO_BLOCK_ID)
118
+ BlocksWithOmittedAbbrevs.insert (SetBID);
119
+ }
120
+
93
121
// Converts the abbreviation record to the corresponding abbreviation.
94
122
// Returns nullptr if unable to build abbreviation.
95
123
NaClBitCodeAbbrev *buildAbbrev (const NaClBitcodeAbbrevRecord &Record);
96
124
97
125
// Emits the given record to the bitcode file. Returns true if
98
126
// successful.
99
127
bool LLVM_ATTRIBUTE_UNUSED_RESULT
100
- emitRecord (NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record);
128
+ emitRecord (NaClBitstreamWriter &Writer,
129
+ const NaClBitcodeAbbrevRecord &Record);
101
130
102
131
// Enter the given block
103
132
bool LLVM_ATTRIBUTE_UNUSED_RESULT
@@ -118,6 +147,21 @@ struct WriteState {
118
147
return true ;
119
148
}
120
149
150
+ void WriteRecord (NaClBitstreamWriter &Writer,
151
+ const NaClBitcodeAbbrevRecord &Record,
152
+ bool UsesDefaultAbbrev) {
153
+ if (UsesDefaultAbbrev)
154
+ Writer.EmitRecord (Record.Code , Record.Values );
155
+ else
156
+ Writer.EmitRecord (Record.Code , Record.Values , Record.Abbrev );
157
+ }
158
+
159
+ // Returns true if the abbreviation index defines an abbreviation
160
+ // that can be applied to the record.
161
+ bool LLVM_ATTRIBUTE_UNUSED_RESULT
162
+ canApplyAbbreviation (NaClBitstreamWriter &Writer,
163
+ const NaClBitcodeAbbrevRecord &Record);
164
+
121
165
// Completes the write.
122
166
NaClMungedBitcode::WriteResults &finish (NaClBitstreamWriter &Writer,
123
167
bool RecoverSilently);
@@ -185,6 +229,55 @@ bool WriteState::enterBlock(NaClBitstreamWriter &Writer, uint64_t WriteBlockID,
185
229
return true ;
186
230
}
187
231
232
+ bool WriteState::canApplyAbbreviation (
233
+ NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record) {
234
+ const NaClBitCodeAbbrev *Abbrev = Writer.getAbbreviation (Record.Abbrev );
235
+ if (Abbrev == nullptr )
236
+ return false ;
237
+
238
+ // Merge record code into values and then match abbreviation.
239
+ NaClBitcodeValues Values (Record);
240
+ size_t ValueIndex = 0 ;
241
+ size_t ValuesSize = Values.size ();
242
+ size_t AbbrevIndex = 0 ;
243
+ size_t AbbrevSize = Abbrev->getNumOperandInfos ();
244
+ bool FoundArray = false ;
245
+ while (ValueIndex < ValuesSize && AbbrevIndex < AbbrevSize) {
246
+ const NaClBitCodeAbbrevOp *Op = &Abbrev->getOperandInfo (AbbrevIndex++);
247
+ uint64_t Value = Values[ValueIndex++];
248
+ if (Op->getEncoding () == NaClBitCodeAbbrevOp::Array) {
249
+ if (AbbrevIndex + 1 != AbbrevSize)
250
+ return false ;
251
+ Op = &Abbrev->getOperandInfo (AbbrevIndex);
252
+ --AbbrevIndex; // i.e. don't advance to next abbreviation op.
253
+ FoundArray = true ;
254
+ }
255
+ switch (Op->getEncoding ()) {
256
+ case NaClBitCodeAbbrevOp::Literal:
257
+ if (Value != Op->getValue ())
258
+ return false ;
259
+ continue ;
260
+ case NaClBitCodeAbbrevOp::Fixed:
261
+ if (Value >= (static_cast <uint64_t >(1 )
262
+ << NaClBitstreamWriter::MaxEmitNumBits)
263
+ || NaClBitsNeededForValue (Value) > Op->getValue ())
264
+ return false ;
265
+ continue ;
266
+ case NaClBitCodeAbbrevOp::VBR:
267
+ if (Op->getValue () < 2 )
268
+ return false ;
269
+ continue ;
270
+ case NaClBitCodeAbbrevOp::Array:
271
+ llvm_unreachable (" Array(Array) abbreviation is not legal!" );
272
+ case NaClBitCodeAbbrevOp::Char6:
273
+ if (!Op->isChar6 (Value))
274
+ return false ;
275
+ continue ;
276
+ }
277
+ }
278
+ return ValueIndex == ValuesSize && (FoundArray || AbbrevIndex == AbbrevSize);
279
+ }
280
+
188
281
NaClMungedBitcode::WriteResults &WriteState::finish (
189
282
NaClBitstreamWriter &Writer, bool RecoverSilently) {
190
283
// Be sure blocks are balanced.
@@ -271,23 +364,24 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
271
364
break ;
272
365
}
273
366
case naclbitc::BLK_CODE_DEFINE_ABBREV: {
367
+ if (curBlockHasOmittedAbbreviations ()) {
368
+ // If reached, a previous abbreviation for the block was omitted. Can't
369
+ // generate more abbreviations without having to fix abbreviation indices.
370
+ RecoverableError () << " Ignoring abbreviation: " << Record << " \n " ;
371
+ return Flags.getTryToRecover ();
372
+ }
274
373
if (Record.Abbrev != naclbitc::DEFINE_ABBREV) {
275
374
RecoverableError ()
276
375
<< " Uses illegal abbreviation index in define abbreviation record: "
277
376
<< Record << " \n " ;
278
377
if (!Flags.getTryToRecover ())
279
378
return false ;
280
379
}
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
- }
288
380
NaClBitCodeAbbrev *Abbrev = buildAbbrev (Record);
289
- if (Abbrev == NULL )
381
+ if (Abbrev == nullptr ) {
382
+ markCurrentBlockWithOmittedAbbreviations ();
290
383
return Flags.getTryToRecover ();
384
+ }
291
385
if (getCurWriteBlockID () == naclbitc::BLOCKINFO_BLOCK_ID) {
292
386
Writer.EmitBlockInfoAbbrev (SetBID, Abbrev);
293
387
} else {
@@ -314,10 +408,21 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
314
408
}
315
409
UsesDefaultAbbrev = true ;
316
410
}
317
- if (!UsesDefaultAbbrev
318
- && !Writer.isUserRecordAbbreviation (Record.Abbrev )) {
319
- // Illegal abbreviation index found.
411
+ if (!UsesDefaultAbbrev && !canApplyAbbreviation (Writer, Record)) {
412
+ if (Writer.getAbbreviation (Record.Abbrev ) != nullptr ) {
413
+ RecoverableError () << " Abbreviation doesn't apply to record: "
414
+ << Record << " \n " ;
415
+ UsesDefaultAbbrev = true ;
416
+ if (!Flags.getTryToRecover ())
417
+ return false ;
418
+ WriteRecord (Writer, Record, UsesDefaultAbbrev);
419
+ return true ;
420
+ }
320
421
if (Flags.getWriteBadAbbrevIndex ()) {
422
+ // The abbreviation is not understood by the bitcode writer,
423
+ // and the flag value implies that we should still write it
424
+ // out so that unit tests for this error condition can be
425
+ // applied.
321
426
Error () << " Uses illegal abbreviation index: " << Record << " \n " ;
322
427
// Generate bad abbreviation index so that the bitcode reader
323
428
// can be tested, and then quit.
@@ -329,9 +434,11 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
329
434
}
330
435
RecoverableError () << " Uses illegal abbreviation index: "
331
436
<< Record << " \n " ;
437
+ UsesDefaultAbbrev = true ;
332
438
if (!Flags.getTryToRecover ())
333
439
return false ;
334
- UsesDefaultAbbrev = true ;
440
+ WriteRecord (Writer, Record, UsesDefaultAbbrev);
441
+ return true ;
335
442
}
336
443
if (getCurWriteBlockID () == naclbitc::BLOCKINFO_BLOCK_ID
337
444
&& Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) {
@@ -347,10 +454,8 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
347
454
SetBID = Record.Values [0 ];
348
455
return true ;
349
456
}
350
- if (UsesDefaultAbbrev)
351
- Writer.EmitRecord (Record.Code , Record.Values );
352
- else
353
- Writer.EmitRecord (Record.Code , Record.Values , Record.Abbrev );
457
+ WriteRecord (Writer, Record, UsesDefaultAbbrev);
458
+ break ;
354
459
}
355
460
return true ;
356
461
}
@@ -381,7 +486,7 @@ NaClBitCodeAbbrev *WriteState::buildAbbrev(
381
486
if (Index >= NumValues) {
382
487
RecoverableError ()
383
488
<< " Malformed abbreviation found. Expects " << NumAbbreviations
384
- << " operands but ound " << Count << " : " << Record << " \n " ;
489
+ << " operands but found " << Count << " : " << Record << " \n " ;
385
490
return deleteAbbrev (Abbrev);
386
491
}
387
492
switch (Record.Values [Index++]) {
@@ -438,8 +543,8 @@ NaClBitCodeAbbrev *WriteState::buildAbbrev(
438
543
break ;
439
544
}
440
545
default :
441
- RecoverableError () << " Error: Bad literal flag " << Record. Values [Index]
442
- << " : " << Record << " \n " ;
546
+ RecoverableError () << " Error: Bad abbreviation operand encoding "
547
+ << Record. Values [Index- 1 ] << " : " << Record << " \n " ;
443
548
return deleteAbbrev (Abbrev);
444
549
}
445
550
}
0 commit comments