Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 0a42736

Browse files
committed
Merge remote-tracking branch 'origin/master' into merge_37
2 parents 0c71e69 + e439162 commit 0a42736

File tree

3 files changed

+350
-60
lines changed

3 files changed

+350
-60
lines changed

include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@ class NaClBitstreamWriter {
4444
std::vector<NaClBitCodeAbbrev*> CurAbbrevs;
4545

4646
struct Block {
47-
NaClBitcodeSelectorAbbrev PrevCodeSize;
48-
unsigned StartSizeWord;
47+
const NaClBitcodeSelectorAbbrev PrevCodeSize;
48+
const unsigned StartSizeWord;
4949
std::vector<NaClBitCodeAbbrev*> PrevAbbrevs;
50-
Block(const NaClBitcodeSelectorAbbrev& PCS, unsigned SSW)
51-
: PrevCodeSize(PCS), StartSizeWord(SSW) {}
50+
const unsigned AbbreviationIndexLimit;
51+
Block(const NaClBitcodeSelectorAbbrev& PCS, unsigned SSW,
52+
unsigned AbbreviationIndexLimit)
53+
: PrevCodeSize(PCS), StartSizeWord(SSW),
54+
AbbreviationIndexLimit(AbbreviationIndexLimit) {}
5255
};
5356

5457
/// BlockScope - This tracks the current blocks that we have entered.
@@ -158,11 +161,15 @@ class NaClBitstreamWriter {
158161
// Basic Primitives for emitting bits to the stream.
159162
//===--------------------------------------------------------------------===//
160163

164+
// Max Number of bits that can be written using Emit.
165+
static const unsigned MaxEmitNumBits = 32;
166+
161167
void Emit(uint32_t Val, unsigned NumBits) {
162-
assert(NumBits && NumBits <= 32 && "Invalid value size!");
163-
assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!");
168+
assert(NumBits && NumBits <= MaxEmitNumBits && "Invalid value size!");
169+
assert((Val &
170+
~(~0U >> (MaxEmitNumBits-NumBits))) == 0 && "High bits set!");
164171
CurValue |= Val << CurBit;
165-
if (CurBit + NumBits < 32) {
172+
if (CurBit + NumBits < MaxEmitNumBits) {
166173
CurBit += NumBits;
167174
return;
168175
}
@@ -171,19 +178,19 @@ class NaClBitstreamWriter {
171178
WriteWord(CurValue);
172179

173180
if (CurBit)
174-
CurValue = Val >> (32-CurBit);
181+
CurValue = Val >> (MaxEmitNumBits-CurBit);
175182
else
176183
CurValue = 0;
177-
CurBit = (CurBit+NumBits) & 31;
184+
CurBit = (CurBit+NumBits) & (MaxEmitNumBits-1);
178185
}
179186

180187
void Emit64(uint64_t Val, unsigned NumBits) {
181-
if (NumBits <= 32)
182-
Emit((uint32_t)Val, NumBits);
183-
else {
184-
Emit((uint32_t)Val, 32);
185-
Emit((uint32_t)(Val >> 32), NumBits-32);
188+
while (NumBits > MaxEmitNumBits) {
189+
Emit((uint32_t)Val, MaxEmitNumBits);
190+
Val >>= MaxEmitNumBits;
191+
NumBits -= MaxEmitNumBits;
186192
}
193+
Emit((uint32_t)Val, NumBits);
187194
}
188195

189196
void flushToByte() {
@@ -287,7 +294,8 @@ class NaClBitstreamWriter {
287294

288295
// Push the outer block's abbrev set onto the stack, start out with an
289296
// empty abbrev set.
290-
BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex));
297+
BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex,
298+
1 << CodeLen.NumBits));
291299
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
292300

293301
// If there is a blockinfo for this BlockID, add all the predefined abbrevs
@@ -389,9 +397,8 @@ class NaClBitstreamWriter {
389397
template<typename uintty>
390398
void EmitRecordWithAbbrevImpl(unsigned Abbrev,
391399
const AbbrevValues<uintty> &Vals) {
392-
unsigned AbbrevNo = Abbrev-naclbitc::FIRST_APPLICATION_ABBREV;
393-
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
394-
NaClBitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo];
400+
const NaClBitCodeAbbrev *Abbv = getAbbreviation(Abbrev);
401+
assert(Abbv && "Abbreviation index is invalid");
395402

396403
EmitCode(Abbrev);
397404

@@ -421,11 +428,17 @@ class NaClBitstreamWriter {
421428

422429
public:
423430

424-
/// Returns true if the given abbreviation index corresponds to a user-defined
425-
/// abbreviation.
426-
bool isUserRecordAbbreviation(unsigned Abbrev) const {
427-
return Abbrev >= naclbitc::FIRST_APPLICATION_ABBREV
428-
&& Abbrev < (CurAbbrevs.size() + naclbitc::FIRST_APPLICATION_ABBREV);
431+
/// Returns a pointer to the abbreviation currently associated with
432+
/// the abbreviation index. Returns nullptr if no such abbreviation.
433+
const NaClBitCodeAbbrev *getAbbreviation(unsigned Index) const {
434+
if (Index < naclbitc::FIRST_APPLICATION_ABBREV)
435+
return nullptr;
436+
if (Index >= BlockScope.back().AbbreviationIndexLimit)
437+
return nullptr;
438+
unsigned AbbrevNo = Index - naclbitc::FIRST_APPLICATION_ABBREV;
439+
if (AbbrevNo >= CurAbbrevs.size())
440+
return nullptr;
441+
return CurAbbrevs[AbbrevNo];
429442
}
430443

431444
/// EmitRecord - Emit the specified record to the stream, using an abbrev if

lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp

Lines changed: 128 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
1717
#include "llvm/Support/raw_ostream.h"
1818

19+
#include <set>
20+
1921
using namespace llvm;
2022

2123
namespace {
@@ -27,13 +29,19 @@ static bool DebugEmit = false;
2729
// Description of current block scope
2830
struct BlockScope {
2931
BlockScope(unsigned CurBlockID, size_t AbbrevIndexLimit)
30-
: CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit) {}
32+
: CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit),
33+
OmittedAbbreviations(false) {}
3134
unsigned CurBlockID;
3235
// Defines the maximum value for abbreviation indices in block.
3336
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;
3441
void print(raw_ostream &Out) const {
3542
Out << "BlockScope(ID=" << CurBlockID << ", AbbrevIndexLimit="
36-
<< AbbrevIndexLimit << ")";
43+
<< AbbrevIndexLimit << "OmittedAbbreviations="
44+
<< OmittedAbbreviations << ")";
3745
}
3846
};
3947

@@ -49,13 +57,16 @@ struct WriteState {
4957
// The SetBID for the blockinfo block.
5058
unsigned SetBID = UnknownWriteBlockID;
5159
// The stack of scopes the writer is in.
52-
SmallVector<BlockScope, 3> ScopeStack;
60+
SmallVector<BlockScope, 4> ScopeStack;
5361
// The set of write flags to use.
5462
const NaClMungedBitcode::WriteFlags &Flags;
5563
// The results of the attempted write.
5664
NaClMungedBitcode::WriteResults Results;
5765
// The minimum number of bits allowed to be specified in a block.
5866
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;
5970

6071
WriteState(const NaClMungedBitcode::WriteFlags &Flags)
6172
: Flags(Flags),
@@ -90,14 +101,32 @@ struct WriteState {
90101
return ScopeStack.back().AbbrevIndexLimit;
91102
}
92103

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+
93121
// Converts the abbreviation record to the corresponding abbreviation.
94122
// Returns nullptr if unable to build abbreviation.
95123
NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record);
96124

97125
// Emits the given record to the bitcode file. Returns true if
98126
// successful.
99127
bool LLVM_ATTRIBUTE_UNUSED_RESULT
100-
emitRecord(NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record);
128+
emitRecord(NaClBitstreamWriter &Writer,
129+
const NaClBitcodeAbbrevRecord &Record);
101130

102131
// Enter the given block
103132
bool LLVM_ATTRIBUTE_UNUSED_RESULT
@@ -118,6 +147,21 @@ struct WriteState {
118147
return true;
119148
}
120149

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+
121165
// Completes the write.
122166
NaClMungedBitcode::WriteResults &finish(NaClBitstreamWriter &Writer,
123167
bool RecoverSilently);
@@ -185,6 +229,55 @@ bool WriteState::enterBlock(NaClBitstreamWriter &Writer, uint64_t WriteBlockID,
185229
return true;
186230
}
187231

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+
188281
NaClMungedBitcode::WriteResults &WriteState::finish(
189282
NaClBitstreamWriter &Writer, bool RecoverSilently) {
190283
// Be sure blocks are balanced.
@@ -271,23 +364,24 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
271364
break;
272365
}
273366
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+
}
274373
if (Record.Abbrev != naclbitc::DEFINE_ABBREV) {
275374
RecoverableError()
276375
<< "Uses illegal abbreviation index in define abbreviation record: "
277376
<< Record << "\n";
278377
if (!Flags.getTryToRecover())
279378
return false;
280379
}
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-
}
288380
NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record);
289-
if (Abbrev == NULL)
381+
if (Abbrev == nullptr) {
382+
markCurrentBlockWithOmittedAbbreviations();
290383
return Flags.getTryToRecover();
384+
}
291385
if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) {
292386
Writer.EmitBlockInfoAbbrev(SetBID, Abbrev);
293387
} else {
@@ -314,10 +408,21 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
314408
}
315409
UsesDefaultAbbrev = true;
316410
}
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+
}
320421
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.
321426
Error() << "Uses illegal abbreviation index: " << Record << "\n";
322427
// Generate bad abbreviation index so that the bitcode reader
323428
// can be tested, and then quit.
@@ -329,9 +434,11 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
329434
}
330435
RecoverableError() << "Uses illegal abbreviation index: "
331436
<< Record << "\n";
437+
UsesDefaultAbbrev = true;
332438
if (!Flags.getTryToRecover())
333439
return false;
334-
UsesDefaultAbbrev = true;
440+
WriteRecord(Writer, Record, UsesDefaultAbbrev);
441+
return true;
335442
}
336443
if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID
337444
&& Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) {
@@ -347,10 +454,8 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
347454
SetBID = Record.Values[0];
348455
return true;
349456
}
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;
354459
}
355460
return true;
356461
}
@@ -381,7 +486,7 @@ NaClBitCodeAbbrev *WriteState::buildAbbrev(
381486
if (Index >= NumValues) {
382487
RecoverableError()
383488
<< "Malformed abbreviation found. Expects " << NumAbbreviations
384-
<< " operands but ound " << Count << ": " << Record << "\n";
489+
<< " operands but found " << Count << ": " << Record << "\n";
385490
return deleteAbbrev(Abbrev);
386491
}
387492
switch (Record.Values[Index++]) {
@@ -438,8 +543,8 @@ NaClBitCodeAbbrev *WriteState::buildAbbrev(
438543
break;
439544
}
440545
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";
443548
return deleteAbbrev(Abbrev);
444549
}
445550
}

0 commit comments

Comments
 (0)