Skip to content

Commit 80b7ba7

Browse files
committed
Make abbreviations explicit in pnacl-freeze/thaw.
[1] Explicitly enumerate all abbreviation values, including the maximum abbreviation for each type of block. [2] Make "enter subblock" calculate number of bits needed by passing in maximum abbreviation (associated with block) rather than requiring the developer to compute this value every time a subblock is entered. *NOTE* This code changes encoding sizes to be based on the maximum allowed value, rather than requiring the developer to calculate out the number of bits needed. This change doesn't make the PNaCL bitcode files incompatable with LLVM bitcode files, since it does not effect the bitcode reader. BUG= https://code.google.com/p/nativeclient/issues/detail?id=3405 [email protected] Review URL: https://codereview.chromium.org/14813032
1 parent 5019000 commit 80b7ba7

File tree

8 files changed

+333
-115
lines changed

8 files changed

+333
-115
lines changed

include/llvm/Bitcode/NaCl/NaClBitCodes.h

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/ADT/SmallVector.h"
2222
#include "llvm/Support/DataTypes.h"
2323
#include "llvm/Support/ErrorHandling.h"
24+
#include "llvm/Support/MathExtras.h"
2425
#include <cassert>
2526

2627
namespace llvm {
@@ -49,7 +50,21 @@ namespace naclbitc {
4950
UNABBREV_RECORD = 3,
5051

5152
// This is not a code, this is a marker for the first abbrev assignment.
52-
FIRST_APPLICATION_ABBREV = 4
53+
// In addition, we assume up to two additional enumerated constants are
54+
// added for each extension. These constants are:
55+
//
56+
// PREFIX_MAX_FIXED_ABBREV
57+
// PREFIX_MAX_ABBREV
58+
//
59+
// PREFIX_MAX_ABBREV defines the maximal enumeration value used for
60+
// the code selector of a block. If Both PREFIX_MAX_FIXED_ABBREV
61+
// and PREFIX_MAX_ABBREV is defined, then PREFIX_MAX_FIXED_ABBREV
62+
// defines the last code selector of the block that must be read using
63+
// a single read (i.e. a FIXED read, or the first chunk of a VBR read.
64+
FIRST_APPLICATION_ABBREV = 4,
65+
// Defines default values for code length, if no additional selectors
66+
// are added.
67+
DEFAULT_MAX_ABBREV = FIRST_APPLICATION_ABBREV-1
5368
};
5469

5570
/// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO
@@ -184,6 +199,59 @@ class NaClBitCodeAbbrev {
184199
OperandList.push_back(OpInfo);
185200
}
186201
};
202+
203+
/// \brief Returns number of bits needed to encode
204+
/// value for dense FIXED encoding.
205+
inline unsigned NaClBitsNeededForValue(unsigned Value) {
206+
// Note: Need to handle case where Value=0xFFFFFFFF as special case,
207+
// since we can't add 1 to it.
208+
if (Value >= 0x80000000) return 32;
209+
return Log2_32_Ceil(Value+1);
210+
}
211+
212+
/// \brief Encode a signed value by moving the sign to the LSB for dense
213+
/// VBR encoding.
214+
inline uint64_t NaClEncodeSignRotatedValue(int64_t V) {
215+
return (V >= 0) ? (V << 1) : ((-V << 1) | 1);
216+
}
217+
218+
/// \brief Decode a signed value stored with the sign bit in
219+
/// the LSB for dense VBR encoding.
220+
inline uint64_t NaClDecodeSignRotatedValue(uint64_t V) {
221+
if ((V & 1) == 0)
222+
return V >> 1;
223+
if (V != 1)
224+
return -(V >> 1);
225+
// There is no such thing as -0 with integers. "-0" really means MININT.
226+
return 1ULL << 63;
227+
}
228+
229+
/// \brief This class determines whether a FIXED or VBR
230+
/// abbreviation should be used for the selector, and the number of bits
231+
/// needed to capture such selectors.
232+
class NaClBitcodeSelectorAbbrev {
233+
234+
public:
235+
// If true, use a FIXED abbreviation. Otherwise, use a VBR abbreviation.
236+
bool IsFixed;
237+
// Number of bits needed for selector.
238+
unsigned NumBits;
239+
240+
// Creates a selector range for the given values.
241+
NaClBitcodeSelectorAbbrev(bool IF, unsigned NB)
242+
: IsFixed(IF), NumBits(NB) {}
243+
244+
// Creates a selector range when no abbreviations are defined.
245+
NaClBitcodeSelectorAbbrev()
246+
: IsFixed(true),
247+
NumBits(NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV)) {}
248+
249+
// Creates a selector range to handle fixed abbrevations up to
250+
// the specified value.
251+
explicit NaClBitcodeSelectorAbbrev(unsigned MaxAbbrev)
252+
: IsFixed(true),
253+
NumBits(NaClBitsNeededForValue(MaxAbbrev)) {}
254+
};
187255
} // End llvm namespace
188256

189257
#endif

include/llvm/Bitcode/NaCl/NaClBitstreamReader.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ class NaClBitstreamCursor {
171171
NaClBitstreamReader *BitStream;
172172
size_t NextChar;
173173

174-
175174
/// CurWord/word_t - This is the current data we have pulled from the stream
176175
/// but have not returned to the client. This is specifically and
177176
/// intentionally defined to follow the word size of the host machine for
@@ -186,21 +185,22 @@ class NaClBitstreamCursor {
186185

187186
// CurCodeSize - This is the declared size of code values used for the current
188187
// block, in bits.
189-
unsigned CurCodeSize;
188+
NaClBitcodeSelectorAbbrev CurCodeSize;
190189

191190
/// CurAbbrevs - Abbrevs installed at in this block.
192191
std::vector<NaClBitCodeAbbrev*> CurAbbrevs;
193192

194193
struct Block {
195-
unsigned PrevCodeSize;
194+
NaClBitcodeSelectorAbbrev PrevCodeSize;
196195
std::vector<NaClBitCodeAbbrev*> PrevAbbrevs;
197-
explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
196+
explicit Block() : PrevCodeSize() {}
197+
explicit Block(const NaClBitcodeSelectorAbbrev& PCS)
198+
: PrevCodeSize(PCS) {}
198199
};
199200

200201
/// BlockScope - This tracks the codesize of parent blocks.
201202
SmallVector<Block, 8> BlockScope;
202203

203-
204204
public:
205205
NaClBitstreamCursor() : BitStream(0), NextChar(0) {
206206
}
@@ -213,7 +213,6 @@ class NaClBitstreamCursor {
213213
NextChar = 0;
214214
CurWord = 0;
215215
BitsInCurWord = 0;
216-
CurCodeSize = 2;
217216
}
218217

219218
void init(NaClBitstreamReader &R) {
@@ -223,7 +222,6 @@ class NaClBitstreamCursor {
223222
NextChar = 0;
224223
CurWord = 0;
225224
BitsInCurWord = 0;
226-
CurCodeSize = 2;
227225
}
228226

229227
~NaClBitstreamCursor() {
@@ -255,7 +253,7 @@ class NaClBitstreamCursor {
255253
}
256254

257255
/// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
258-
unsigned getAbbrevIDWidth() const { return CurCodeSize; }
256+
unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; }
259257

260258
/// GetCurrentBitNo - Return the bit # of the bit we are reading.
261259
uint64_t GetCurrentBitNo() const {
@@ -343,7 +341,6 @@ class NaClBitstreamCursor {
343341
}
344342
}
345343

346-
347344
uint32_t Read(unsigned NumBits) {
348345
assert(NumBits && NumBits <= 32 &&
349346
"Cannot return zero or more than 32 bits!");
@@ -459,10 +456,11 @@ class NaClBitstreamCursor {
459456
public:
460457

461458
unsigned ReadCode() {
462-
return Read(CurCodeSize);
459+
return CurCodeSize.IsFixed
460+
? Read(CurCodeSize.NumBits)
461+
: ReadVBR(CurCodeSize.NumBits);
463462
}
464463

465-
466464
// Block header:
467465
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
468466

include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class NaClBitstreamWriter {
3333

3434
/// CurCodeSize - This is the declared size of code values used for the
3535
/// current block, in bits.
36-
unsigned CurCodeSize;
36+
NaClBitcodeSelectorAbbrev CurCodeSize;
3737

3838
/// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently
3939
/// selected BLOCK ID.
@@ -43,10 +43,11 @@ class NaClBitstreamWriter {
4343
std::vector<NaClBitCodeAbbrev*> CurAbbrevs;
4444

4545
struct Block {
46-
unsigned PrevCodeSize;
46+
NaClBitcodeSelectorAbbrev PrevCodeSize;
4747
unsigned StartSizeWord;
4848
std::vector<NaClBitCodeAbbrev*> PrevAbbrevs;
49-
Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {}
49+
Block(const NaClBitcodeSelectorAbbrev& PCS, unsigned SSW)
50+
: PrevCodeSize(PCS), StartSizeWord(SSW) {}
5051
};
5152

5253
/// BlockScope - This tracks the current blocks that we have entered.
@@ -94,7 +95,7 @@ class NaClBitstreamWriter {
9495

9596
public:
9697
explicit NaClBitstreamWriter(SmallVectorImpl<char> &O)
97-
: Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {}
98+
: Out(O), CurBit(0), CurValue(0), CurCodeSize() {}
9899

99100
~NaClBitstreamWriter() {
100101
assert(CurBit == 0 && "Unflused data remaining");
@@ -156,6 +157,7 @@ class NaClBitstreamWriter {
156157

157158
void EmitVBR(uint32_t Val, unsigned NumBits) {
158159
assert(NumBits <= 32 && "Too many bits to emit!");
160+
assert(NumBits > 1 && "Too few bits to emit!");
159161
uint32_t Threshold = 1U << (NumBits-1);
160162

161163
// Emit the bits with VBR encoding, NumBits-1 bits at a time.
@@ -169,6 +171,7 @@ class NaClBitstreamWriter {
169171

170172
void EmitVBR64(uint64_t Val, unsigned NumBits) {
171173
assert(NumBits <= 32 && "Too many bits to emit!");
174+
assert(NumBits > 1 && "Too few bits to emit!");
172175
if ((uint32_t)Val == Val)
173176
return EmitVBR((uint32_t)Val, NumBits);
174177

@@ -186,7 +189,10 @@ class NaClBitstreamWriter {
186189

187190
/// EmitCode - Emit the specified code.
188191
void EmitCode(unsigned Val) {
189-
Emit(Val, CurCodeSize);
192+
if (CurCodeSize.IsFixed)
193+
Emit(Val, CurCodeSize.NumBits);
194+
else
195+
EmitVBR(Val, CurCodeSize.NumBits);
190196
}
191197

192198
//===--------------------------------------------------------------------===//
@@ -207,16 +213,22 @@ class NaClBitstreamWriter {
207213
return 0;
208214
}
209215

210-
void EnterSubblock(unsigned BlockID, unsigned CodeLen) {
216+
private:
217+
// Enter block using CodeLen bits to read the size of the code
218+
// selector associated with the block.
219+
void EnterSubblock(unsigned BlockID,
220+
const NaClBitcodeSelectorAbbrev& CodeLen,
221+
BlockInfo *Info) {
211222
// Block header:
212223
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
213224
EmitCode(naclbitc::ENTER_SUBBLOCK);
214225
EmitVBR(BlockID, naclbitc::BlockIDWidth);
215-
EmitVBR(CodeLen, naclbitc::CodeLenWidth);
226+
assert(CodeLen.IsFixed && "Block codelens must be fixed");
227+
EmitVBR(CodeLen.NumBits, naclbitc::CodeLenWidth);
216228
FlushToWord();
217229

218230
unsigned BlockSizeWordIndex = GetWordIndex();
219-
unsigned OldCodeSize = CurCodeSize;
231+
NaClBitcodeSelectorAbbrev OldCodeSize(CurCodeSize);
220232

221233
// Emit a placeholder, which will be replaced when the block is popped.
222234
Emit(0, naclbitc::BlockSizeWidth);
@@ -230,7 +242,7 @@ class NaClBitstreamWriter {
230242

231243
// If there is a blockinfo for this BlockID, add all the predefined abbrevs
232244
// to the abbrev list.
233-
if (BlockInfo *Info = getBlockInfo(BlockID)) {
245+
if (Info) {
234246
for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size());
235247
i != e; ++i) {
236248
CurAbbrevs.push_back(Info->Abbrevs[i]);
@@ -239,6 +251,31 @@ class NaClBitstreamWriter {
239251
}
240252
}
241253

254+
public:
255+
/// \brief Enter block using CodeLen bits to read the size of the code
256+
/// selector associated with the block.
257+
void EnterSubblock(unsigned BlockID,
258+
const NaClBitcodeSelectorAbbrev& CodeLen) {
259+
EnterSubblock(BlockID, CodeLen, getBlockInfo(BlockID));
260+
}
261+
262+
/// \brief Enter block, using a code length based on the number of
263+
/// (global) BlockInfo entries defined for the block. Note: This
264+
/// should be used only if the block doesn't define any local abbreviations.
265+
void EnterSubblock(unsigned BlockID) {
266+
BlockInfo *Info = getBlockInfo(BlockID);
267+
size_t NumAbbrevs = Info ? Info->Abbrevs.size() : 0;
268+
NaClBitcodeSelectorAbbrev DefaultCodeLen(
269+
naclbitc::DEFAULT_MAX_ABBREV+NumAbbrevs);
270+
EnterSubblock(BlockID, DefaultCodeLen, Info);
271+
}
272+
273+
/// \brief Enter block with the given number of abbreviations.
274+
void EnterSubblock(unsigned BlockID, unsigned NumAbbrev) {
275+
NaClBitcodeSelectorAbbrev CodeLenAbbrev(NumAbbrev);
276+
EnterSubblock(BlockID, CodeLenAbbrev);
277+
}
278+
242279
void ExitBlock() {
243280
assert(!BlockScope.empty() && "Block scope imbalance!");
244281

@@ -501,8 +538,8 @@ class NaClBitstreamWriter {
501538
//===--------------------------------------------------------------------===//
502539

503540
/// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
504-
void EnterBlockInfoBlock(unsigned CodeWidth) {
505-
EnterSubblock(naclbitc::BLOCKINFO_BLOCK_ID, CodeWidth);
541+
void EnterBlockInfoBlock() {
542+
EnterSubblock(naclbitc::BLOCKINFO_BLOCK_ID);
506543
BlockInfoCurBID = ~0U;
507544
}
508545
private:

0 commit comments

Comments
 (0)