Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(930)

Side by Side Diff: include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===// 1 //===- NaClBitstreamWriter.h - NaCl bitstream writer ------------*- 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 // This header defines the BitstreamWriter class. This class can be used to 10 // This header defines the BitstreamWriter class. This class can be used to
11 // write an arbitrary bitstream, regardless of its contents. 11 // write an arbitrary bitstream, regardless of its contents.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #ifndef LLVM_BITCODE_BITSTREAMWRITER_H 15 #ifndef LLVM_BITCODE_NACL_NACLBITSTREAMWRITER_H
16 #define LLVM_BITCODE_BITSTREAMWRITER_H 16 #define LLVM_BITCODE_NACL_NACLBITSTREAMWRITER_H
17 17
18 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Bitcode/BitCodes.h" 20 #include "llvm/Bitcode/NaCl/NaClBitCodes.h"
21 #include <vector> 21 #include <vector>
22 22
23 namespace llvm { 23 namespace llvm {
24 24
25 class BitstreamWriter { 25 class NaClBitstreamWriter {
26 SmallVectorImpl<char> &Out; 26 SmallVectorImpl<char> &Out;
27 27
28 /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. 28 /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use.
29 unsigned CurBit; 29 unsigned CurBit;
30 30
31 /// CurValue - The current value. Only bits < CurBit are valid. 31 /// CurValue - The current value. Only bits < CurBit are valid.
32 uint32_t CurValue; 32 uint32_t CurValue;
33 33
34 /// CurCodeSize - This is the declared size of code values used for the 34 /// CurCodeSize - This is the declared size of code values used for the
35 /// current block, in bits. 35 /// current block, in bits.
36 unsigned CurCodeSize; 36 NaClBitcodeSelectorAbbrev CurCodeSize;
37 37
38 /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently 38 /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently
39 /// selected BLOCK ID. 39 /// selected BLOCK ID.
40 unsigned BlockInfoCurBID; 40 unsigned BlockInfoCurBID;
41 41
42 /// CurAbbrevs - Abbrevs installed at in this block. 42 /// CurAbbrevs - Abbrevs installed at in this block.
43 std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs; 43 std::vector<NaClBitCodeAbbrev*> CurAbbrevs;
44 44
45 struct Block { 45 struct Block {
46 unsigned PrevCodeSize; 46 NaClBitcodeSelectorAbbrev PrevCodeSize;
47 unsigned StartSizeWord; 47 unsigned StartSizeWord;
48 std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs; 48 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) {}
50 }; 51 };
51 52
52 /// BlockScope - This tracks the current blocks that we have entered. 53 /// BlockScope - This tracks the current blocks that we have entered.
53 std::vector<Block> BlockScope; 54 std::vector<Block> BlockScope;
54 55
55 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. 56 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
56 /// These describe abbreviations that all blocks of the specified ID inherit. 57 /// These describe abbreviations that all blocks of the specified ID inherit.
57 struct BlockInfo { 58 struct BlockInfo {
58 unsigned BlockID; 59 unsigned BlockID;
59 std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs; 60 std::vector<NaClBitCodeAbbrev*> Abbrevs;
60 }; 61 };
61 std::vector<BlockInfo> BlockInfoRecords; 62 std::vector<BlockInfo> BlockInfoRecords;
62 63
64 /// AbbrevValues - Wrapper class that allows the bitstream writer to
65 /// prefix a code to the set of values, associated with a record to
66 /// emit, without having to destructively change the contents of
67 /// values.
68 template<typename uintty>
69 struct AbbrevValues {
70 AbbrevValues(uintty Code, const SmallVectorImpl<uintty> &Values)
71 : Code(Code), Values(Values) {}
72
73 size_t size() const {
74 return Values.size() + 1;
75 }
76
77 uintty operator[](size_t Index) const {
78 return Index == 0 ? Code : Values[Index-1];
79 }
80
81 private:
82 // The code to use (if not DONT_USE_CODE).
83 uintty Code;
84 const SmallVectorImpl<uintty> &Values;
85 };
86
87 public:
63 // BackpatchWord - Backpatch a 32-bit word in the output with the specified 88 // BackpatchWord - Backpatch a 32-bit word in the output with the specified
64 // value. 89 // value.
65 void BackpatchWord(unsigned ByteNo, unsigned NewWord) { 90 void BackpatchWord(unsigned ByteNo, unsigned NewWord) {
66 Out[ByteNo++] = (unsigned char)(NewWord >> 0); 91 Out[ByteNo++] = (unsigned char)(NewWord >> 0);
67 Out[ByteNo++] = (unsigned char)(NewWord >> 8); 92 Out[ByteNo++] = (unsigned char)(NewWord >> 8);
68 Out[ByteNo++] = (unsigned char)(NewWord >> 16); 93 Out[ByteNo++] = (unsigned char)(NewWord >> 16);
69 Out[ByteNo ] = (unsigned char)(NewWord >> 24); 94 Out[ByteNo ] = (unsigned char)(NewWord >> 24);
70 } 95 }
71 96
97 private:
72 void WriteByte(unsigned char Value) { 98 void WriteByte(unsigned char Value) {
73 Out.push_back(Value); 99 Out.push_back(Value);
74 } 100 }
75 101
76 void WriteWord(unsigned Value) { 102 void WriteWord(unsigned Value) {
77 unsigned char Bytes[4] = { 103 unsigned char Bytes[4] = {
78 (unsigned char)(Value >> 0), 104 (unsigned char)(Value >> 0),
79 (unsigned char)(Value >> 8), 105 (unsigned char)(Value >> 8),
80 (unsigned char)(Value >> 16), 106 (unsigned char)(Value >> 16),
81 (unsigned char)(Value >> 24) }; 107 (unsigned char)(Value >> 24) };
82 Out.append(&Bytes[0], &Bytes[4]); 108 Out.append(&Bytes[0], &Bytes[4]);
83 } 109 }
84 110
85 unsigned GetBufferOffset() const { 111 unsigned GetBufferOffset() const {
86 return Out.size(); 112 return Out.size();
87 } 113 }
88 114
89 unsigned GetWordIndex() const { 115 unsigned GetWordIndex() const {
90 unsigned Offset = GetBufferOffset(); 116 unsigned Offset = GetBufferOffset();
91 assert((Offset & 3) == 0 && "Not 32-bit aligned"); 117 assert((Offset & 3) == 0 && "Not 32-bit aligned");
92 return Offset / 4; 118 return Offset / 4;
93 } 119 }
94 120
95 public: 121 public:
96 explicit BitstreamWriter(SmallVectorImpl<char> &O) 122 explicit NaClBitstreamWriter(SmallVectorImpl<char> &O)
97 : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} 123 : Out(O), CurBit(0), CurValue(0), CurCodeSize() {}
98 124
99 ~BitstreamWriter() { 125 ~NaClBitstreamWriter() {
100 assert(CurBit == 0 && "Unflushed data remaining"); 126 assert(CurBit == 0 && "Unflused data remaining");
101 assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); 127 assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
128
129 // Free the BlockInfoRecords.
130 while (!BlockInfoRecords.empty()) {
131 BlockInfo &Info = BlockInfoRecords.back();
132 // Free blockinfo abbrev info.
133 for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
134 i != e; ++i)
135 Info.Abbrevs[i]->dropRef();
136 BlockInfoRecords.pop_back();
137 }
102 } 138 }
103 139
104 /// \brief Retrieve the current position in the stream, in bits. 140 /// \brief Retrieve the current position in the stream, in bits.
105 uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; } 141 uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
106 142
107 //===--------------------------------------------------------------------===// 143 //===--------------------------------------------------------------------===//
108 // Basic Primitives for emitting bits to the stream. 144 // Basic Primitives for emitting bits to the stream.
109 //===--------------------------------------------------------------------===// 145 //===--------------------------------------------------------------------===//
110 146
111 void Emit(uint32_t Val, unsigned NumBits) { 147 void Emit(uint32_t Val, unsigned NumBits) {
(...skipping 27 matching lines...) Expand all
139 void FlushToWord() { 175 void FlushToWord() {
140 if (CurBit) { 176 if (CurBit) {
141 WriteWord(CurValue); 177 WriteWord(CurValue);
142 CurBit = 0; 178 CurBit = 0;
143 CurValue = 0; 179 CurValue = 0;
144 } 180 }
145 } 181 }
146 182
147 void EmitVBR(uint32_t Val, unsigned NumBits) { 183 void EmitVBR(uint32_t Val, unsigned NumBits) {
148 assert(NumBits <= 32 && "Too many bits to emit!"); 184 assert(NumBits <= 32 && "Too many bits to emit!");
185 assert(NumBits > 1 && "Too few bits to emit!");
149 uint32_t Threshold = 1U << (NumBits-1); 186 uint32_t Threshold = 1U << (NumBits-1);
150 187
151 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 188 // Emit the bits with VBR encoding, NumBits-1 bits at a time.
152 while (Val >= Threshold) { 189 while (Val >= Threshold) {
153 Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits); 190 Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
154 Val >>= NumBits-1; 191 Val >>= NumBits-1;
155 } 192 }
156 193
157 Emit(Val, NumBits); 194 Emit(Val, NumBits);
158 } 195 }
159 196
160 void EmitVBR64(uint64_t Val, unsigned NumBits) { 197 void EmitVBR64(uint64_t Val, unsigned NumBits) {
161 assert(NumBits <= 32 && "Too many bits to emit!"); 198 assert(NumBits <= 32 && "Too many bits to emit!");
199 assert(NumBits > 1 && "Too few bits to emit!");
162 if ((uint32_t)Val == Val) 200 if ((uint32_t)Val == Val)
163 return EmitVBR((uint32_t)Val, NumBits); 201 return EmitVBR((uint32_t)Val, NumBits);
164 202
165 uint32_t Threshold = 1U << (NumBits-1); 203 uint32_t Threshold = 1U << (NumBits-1);
166 204
167 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 205 // Emit the bits with VBR encoding, NumBits-1 bits at a time.
168 while (Val >= Threshold) { 206 while (Val >= Threshold) {
169 Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) | 207 Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) |
170 (1 << (NumBits-1)), NumBits); 208 (1 << (NumBits-1)), NumBits);
171 Val >>= NumBits-1; 209 Val >>= NumBits-1;
172 } 210 }
173 211
174 Emit((uint32_t)Val, NumBits); 212 Emit((uint32_t)Val, NumBits);
175 } 213 }
176 214
177 /// EmitCode - Emit the specified code. 215 /// EmitCode - Emit the specified code.
178 void EmitCode(unsigned Val) { 216 void EmitCode(unsigned Val) {
179 Emit(Val, CurCodeSize); 217 if (CurCodeSize.IsFixed)
218 Emit(Val, CurCodeSize.NumBits);
219 else
220 EmitVBR(Val, CurCodeSize.NumBits);
180 } 221 }
181 222
182 //===--------------------------------------------------------------------===// 223 //===--------------------------------------------------------------------===//
183 // Block Manipulation 224 // Block Manipulation
184 //===--------------------------------------------------------------------===// 225 //===--------------------------------------------------------------------===//
185 226
186 /// getBlockInfo - If there is block info for the specified ID, return it, 227 /// getBlockInfo - If there is block info for the specified ID, return it,
187 /// otherwise return null. 228 /// otherwise return null.
188 BlockInfo *getBlockInfo(unsigned BlockID) { 229 BlockInfo *getBlockInfo(unsigned BlockID) {
189 // Common case, the most recent entry matches BlockID. 230 // Common case, the most recent entry matches BlockID.
190 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) 231 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
191 return &BlockInfoRecords.back(); 232 return &BlockInfoRecords.back();
192 233
193 for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size()); 234 for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
194 i != e; ++i) 235 i != e; ++i)
195 if (BlockInfoRecords[i].BlockID == BlockID) 236 if (BlockInfoRecords[i].BlockID == BlockID)
196 return &BlockInfoRecords[i]; 237 return &BlockInfoRecords[i];
197 return nullptr; 238 return 0;
198 } 239 }
199 240
200 void EnterSubblock(unsigned BlockID, unsigned CodeLen) { 241 private:
242 // Enter block using CodeLen bits to read the size of the code
243 // selector associated with the block.
244 void EnterSubblock(unsigned BlockID,
245 const NaClBitcodeSelectorAbbrev& CodeLen,
246 BlockInfo *Info) {
201 // Block header: 247 // Block header:
202 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] 248 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
203 EmitCode(bitc::ENTER_SUBBLOCK); 249 EmitCode(naclbitc::ENTER_SUBBLOCK);
204 EmitVBR(BlockID, bitc::BlockIDWidth); 250 EmitVBR(BlockID, naclbitc::BlockIDWidth);
205 EmitVBR(CodeLen, bitc::CodeLenWidth); 251 assert(CodeLen.IsFixed && "Block codelens must be fixed");
252 EmitVBR(CodeLen.NumBits, naclbitc::CodeLenWidth);
206 FlushToWord(); 253 FlushToWord();
207 254
208 unsigned BlockSizeWordIndex = GetWordIndex(); 255 unsigned BlockSizeWordIndex = GetWordIndex();
209 unsigned OldCodeSize = CurCodeSize; 256 NaClBitcodeSelectorAbbrev OldCodeSize(CurCodeSize);
210 257
211 // Emit a placeholder, which will be replaced when the block is popped. 258 // Emit a placeholder, which will be replaced when the block is popped.
212 Emit(0, bitc::BlockSizeWidth); 259 Emit(0, naclbitc::BlockSizeWidth);
213 260
214 CurCodeSize = CodeLen; 261 CurCodeSize = CodeLen;
215 262
216 // Push the outer block's abbrev set onto the stack, start out with an 263 // Push the outer block's abbrev set onto the stack, start out with an
217 // empty abbrev set. 264 // empty abbrev set.
218 BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex)); 265 BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex));
219 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); 266 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
220 267
221 // If there is a blockinfo for this BlockID, add all the predefined abbrevs 268 // If there is a blockinfo for this BlockID, add all the predefined abbrevs
222 // to the abbrev list. 269 // to the abbrev list.
223 if (BlockInfo *Info = getBlockInfo(BlockID)) { 270 if (Info) {
224 CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(), 271 for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size());
225 Info->Abbrevs.end()); 272 i != e; ++i) {
273 CurAbbrevs.push_back(Info->Abbrevs[i]);
274 Info->Abbrevs[i]->addRef();
275 }
226 } 276 }
227 } 277 }
228 278
279 public:
280 /// \brief Enter block using CodeLen bits to read the size of the code
281 /// selector associated with the block.
282 void EnterSubblock(unsigned BlockID,
283 const NaClBitcodeSelectorAbbrev& CodeLen) {
284 EnterSubblock(BlockID, CodeLen, getBlockInfo(BlockID));
285 }
286
287 /// \brief Enter block, using a code length based on the number of
288 /// (global) BlockInfo entries defined for the block. Note: This
289 /// should be used only if the block doesn't define any local abbreviations.
290 void EnterSubblock(unsigned BlockID) {
291 BlockInfo *Info = getBlockInfo(BlockID);
292 size_t NumAbbrevs = Info ? Info->Abbrevs.size() : 0;
293 NaClBitcodeSelectorAbbrev DefaultCodeLen(
294 naclbitc::DEFAULT_MAX_ABBREV+NumAbbrevs);
295 EnterSubblock(BlockID, DefaultCodeLen, Info);
296 }
297
298 /// \brief Enter block with the given number of abbreviations.
299 void EnterSubblock(unsigned BlockID, unsigned NumAbbrev) {
300 NaClBitcodeSelectorAbbrev CodeLenAbbrev(NumAbbrev);
301 EnterSubblock(BlockID, CodeLenAbbrev);
302 }
303
229 void ExitBlock() { 304 void ExitBlock() {
230 assert(!BlockScope.empty() && "Block scope imbalance!"); 305 assert(!BlockScope.empty() && "Block scope imbalance!");
306
307 // Delete all abbrevs.
308 for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
309 i != e; ++i)
310 CurAbbrevs[i]->dropRef();
311
231 const Block &B = BlockScope.back(); 312 const Block &B = BlockScope.back();
232 313
233 // Block tail: 314 // Block tail:
234 // [END_BLOCK, <align4bytes>] 315 // [END_BLOCK, <align4bytes>]
235 EmitCode(bitc::END_BLOCK); 316 EmitCode(naclbitc::END_BLOCK);
236 FlushToWord(); 317 FlushToWord();
237 318
238 // Compute the size of the block, in words, not counting the size field. 319 // Compute the size of the block, in words, not counting the size field.
239 unsigned SizeInWords = GetWordIndex() - B.StartSizeWord - 1; 320 unsigned SizeInWords = GetWordIndex() - B.StartSizeWord - 1;
240 unsigned ByteNo = B.StartSizeWord*4; 321 unsigned ByteNo = B.StartSizeWord*4;
241 322
242 // Update the block size field in the header of this sub-block. 323 // Update the block size field in the header of this sub-block.
243 BackpatchWord(ByteNo, SizeInWords); 324 BackpatchWord(ByteNo, SizeInWords);
244 325
245 // Restore the inner block's code size and abbrev table. 326 // Restore the inner block's code size and abbrev table.
246 CurCodeSize = B.PrevCodeSize; 327 CurCodeSize = B.PrevCodeSize;
247 CurAbbrevs = std::move(B.PrevAbbrevs); 328 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
248 BlockScope.pop_back(); 329 BlockScope.pop_back();
249 } 330 }
250 331
251 //===--------------------------------------------------------------------===// 332 //===--------------------------------------------------------------------===//
252 // Record Emission 333 // Record Emission
253 //===--------------------------------------------------------------------===// 334 //===--------------------------------------------------------------------===//
254 335
255 private: 336 private:
256 /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev
257 /// record. This is a no-op, since the abbrev specifies the literal to use.
258 template<typename uintty>
259 void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) {
260 assert(Op.isLiteral() && "Not a literal");
261 // If the abbrev specifies the literal value to use, don't emit
262 // anything.
263 assert(V == Op.getLiteralValue() &&
264 "Invalid abbrev for record!");
265 }
266
267 /// EmitAbbreviatedField - Emit a single scalar field value with the specified 337 /// EmitAbbreviatedField - Emit a single scalar field value with the specified
268 /// encoding. 338 /// encoding.
269 template<typename uintty> 339 template<typename uintty>
270 void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { 340 void EmitAbbreviatedField(const NaClBitCodeAbbrevOp &Op, uintty V) {
271 assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!");
272
273 // Encode the value as we are commanded.
274 switch (Op.getEncoding()) { 341 switch (Op.getEncoding()) {
275 default: llvm_unreachable("Unknown encoding!"); 342 case NaClBitCodeAbbrevOp::Literal:
276 case BitCodeAbbrevOp::Fixed: 343 // This is a no-op, since the abbrev specifies the literal to use.
277 if (Op.getEncodingData()) 344 assert(V == Op.getValue() && "Invalid abbrev for record!");
278 Emit((unsigned)V, (unsigned)Op.getEncodingData());
279 break; 345 break;
280 case BitCodeAbbrevOp::VBR: 346 case NaClBitCodeAbbrevOp::Fixed:
281 if (Op.getEncodingData()) 347 if (Op.getValue())
282 EmitVBR64(V, (unsigned)Op.getEncodingData()); 348 Emit((unsigned)V, (unsigned)Op.getValue());
283 break; 349 break;
284 case BitCodeAbbrevOp::Char6: 350 case NaClBitCodeAbbrevOp::VBR:
285 Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); 351 if (Op.getValue())
352 EmitVBR64(V, (unsigned)Op.getValue());
353 break;
354 case NaClBitCodeAbbrevOp::Array:
355 report_fatal_error("Not to be used with array abbreviation op!");
356 case NaClBitCodeAbbrevOp::Char6:
357 Emit(NaClBitCodeAbbrevOp::EncodeChar6((char)V), 6);
286 break; 358 break;
287 } 359 }
288 } 360 }
289 361
290 /// EmitRecordWithAbbrevImpl - This is the core implementation of the record 362 /// EmitRecordWithAbbrevImpl - This is the core implementation of the record
291 /// emission code. If BlobData is non-null, then it specifies an array of 363 /// emission code.
292 /// data that should be emitted as part of the Blob or Array operand that is
293 /// known to exist at the end of the record.
294 template<typename uintty> 364 template<typename uintty>
295 void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl<uintty> &Vals, 365 void EmitRecordWithAbbrevImpl(unsigned Abbrev,
296 StringRef Blob) { 366 const AbbrevValues<uintty> &Vals) {
297 const char *BlobData = Blob.data(); 367 unsigned AbbrevNo = Abbrev-naclbitc::FIRST_APPLICATION_ABBREV;
298 unsigned BlobLen = (unsigned) Blob.size();
299 unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV;
300 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); 368 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
301 const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get(); 369 NaClBitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo];
302 370
303 EmitCode(Abbrev); 371 EmitCode(Abbrev);
304 372
305 unsigned RecordIdx = 0; 373 unsigned RecordIdx = 0;
306 for (unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos()); 374 for (unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos());
307 i != e; ++i) { 375 i != e; ++i) {
308 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 376 const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
309 if (Op.isLiteral()) { 377 if (Op.getEncoding() == NaClBitCodeAbbrevOp::Array) {
310 assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
311 EmitAbbreviatedLiteral(Op, Vals[RecordIdx]);
312 ++RecordIdx;
313 } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
314 // Array case. 378 // Array case.
315 assert(i+2 == e && "array op not second to last?"); 379 assert(i+2 == e && "array op not second to last?");
316 const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); 380 const NaClBitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
317
318 // If this record has blob data, emit it, otherwise we must have record
319 // entries to encode this way.
320 if (BlobData) {
321 assert(RecordIdx == Vals.size() &&
322 "Blob data and record entries specified for array!");
323 // Emit a vbr6 to indicate the number of elements present.
324 EmitVBR(static_cast<uint32_t>(BlobLen), 6);
325
326 // Emit each field.
327 for (unsigned i = 0; i != BlobLen; ++i)
328 EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]);
329
330 // Know that blob data is consumed for assertion below.
331 BlobData = nullptr;
332 } else {
333 // Emit a vbr6 to indicate the number of elements present.
334 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
335
336 // Emit each field.
337 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx)
338 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
339 }
340 } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) {
341 // If this record has blob data, emit it, otherwise we must have record
342 // entries to encode this way.
343 381
344 // Emit a vbr6 to indicate the number of elements present. 382 // Emit a vbr6 to indicate the number of elements present.
345 if (BlobData) { 383 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
346 EmitVBR(static_cast<uint32_t>(BlobLen), 6);
347 assert(RecordIdx == Vals.size() &&
348 "Blob data and record entries specified for blob operand!");
349 } else {
350 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
351 }
352 384
353 // Flush to a 32-bit alignment boundary. 385 // Emit each field.
354 FlushToWord(); 386 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx)
355 387 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
356 // Emit each field as a literal byte. 388 } else {
357 if (BlobData) {
358 for (unsigned i = 0; i != BlobLen; ++i)
359 WriteByte((unsigned char)BlobData[i]);
360
361 // Know that blob data is consumed for assertion below.
362 BlobData = nullptr;
363 } else {
364 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) {
365 assert(isUInt<8>(Vals[RecordIdx]) &&
366 "Value too large to emit as blob");
367 WriteByte((unsigned char)Vals[RecordIdx]);
368 }
369 }
370
371 // Align end to 32-bits.
372 while (GetBufferOffset() & 3)
373 WriteByte(0);
374 } else { // Single scalar field.
375 assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); 389 assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
376 EmitAbbreviatedField(Op, Vals[RecordIdx]); 390 EmitAbbreviatedField(Op, Vals[RecordIdx]);
377 ++RecordIdx; 391 ++RecordIdx;
378 } 392 }
379 } 393 }
380 assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); 394 assert(RecordIdx == Vals.size() && "Not all record operands emitted!");
381 assert(BlobData == nullptr &&
382 "Blob data specified for record that doesn't use it!");
383 } 395 }
384 396
385 public: 397 public:
386 398
399 /// Returns true if the given abbreviation index corresponds to a user-defined
400 /// abbreviation.
401 bool isUserRecordAbbreviation(unsigned Abbrev) const {
402 return Abbrev >= naclbitc::FIRST_APPLICATION_ABBREV
403 && Abbrev < CurAbbrevs.size();
404 }
405
387 /// EmitRecord - Emit the specified record to the stream, using an abbrev if 406 /// EmitRecord - Emit the specified record to the stream, using an abbrev if
388 /// we have one to compress the output. 407 /// we have one to compress the output.
389 template<typename uintty> 408 template<typename uintty>
390 void EmitRecord(unsigned Code, SmallVectorImpl<uintty> &Vals, 409 void EmitRecord(unsigned Code, const SmallVectorImpl<uintty> &Vals,
391 unsigned Abbrev = 0) { 410 unsigned Abbrev = 0) {
392 if (!Abbrev) { 411 if (!Abbrev) {
393 // If we don't have an abbrev to use, emit this in its fully unabbreviated 412 // If we don't have an abbrev to use, emit this in its fully unabbreviated
394 // form. 413 // form.
395 EmitCode(bitc::UNABBREV_RECORD); 414 EmitCode(naclbitc::UNABBREV_RECORD);
396 EmitVBR(Code, 6); 415 EmitVBR(Code, 6);
397 EmitVBR(static_cast<uint32_t>(Vals.size()), 6); 416 EmitVBR(static_cast<uint32_t>(Vals.size()), 6);
398 for (unsigned i = 0, e = static_cast<unsigned>(Vals.size()); i != e; ++i) 417 for (unsigned i = 0, e = static_cast<unsigned>(Vals.size()); i != e; ++i)
399 EmitVBR64(Vals[i], 6); 418 EmitVBR64(Vals[i], 6);
400 return; 419 return;
401 } 420 }
402 421
403 // Insert the code into Vals to treat it uniformly. 422 // combine code and values, and then emit.
404 Vals.insert(Vals.begin(), Code); 423 AbbrevValues<uintty> AbbrevVals(Code, Vals);
405 424 EmitRecordWithAbbrevImpl(Abbrev, AbbrevVals);
406 EmitRecordWithAbbrev(Abbrev, Vals);
407 }
408
409 /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation.
410 /// Unlike EmitRecord, the code for the record should be included in Vals as
411 /// the first entry.
412 template<typename uintty>
413 void EmitRecordWithAbbrev(unsigned Abbrev, SmallVectorImpl<uintty> &Vals) {
414 EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef());
415 }
416
417 /// EmitRecordWithBlob - Emit the specified record to the stream, using an
418 /// abbrev that includes a blob at the end. The blob data to emit is
419 /// specified by the pointer and length specified at the end. In contrast to
420 /// EmitRecord, this routine expects that the first entry in Vals is the code
421 /// of the record.
422 template<typename uintty>
423 void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
424 StringRef Blob) {
425 EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob);
426 }
427 template<typename uintty>
428 void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
429 const char *BlobData, unsigned BlobLen) {
430 return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(BlobData, BlobLen));
431 }
432
433 /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records
434 /// that end with an array.
435 template<typename uintty>
436 void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
437 StringRef Array) {
438 EmitRecordWithAbbrevImpl(Abbrev, Vals, Array);
439 }
440 template<typename uintty>
441 void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
442 const char *ArrayData, unsigned ArrayLen) {
443 return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData,
444 ArrayLen));
445 } 425 }
446 426
447 //===--------------------------------------------------------------------===// 427 //===--------------------------------------------------------------------===//
448 // Abbrev Emission 428 // Abbrev Emission
449 //===--------------------------------------------------------------------===// 429 //===--------------------------------------------------------------------===//
450 430
451 private: 431 private:
452 // Emit the abbreviation as a DEFINE_ABBREV record. 432 // Emit the abbreviation as a DEFINE_ABBREV record.
453 void EncodeAbbrev(BitCodeAbbrev *Abbv) { 433 void EncodeAbbrev(NaClBitCodeAbbrev *Abbv) {
454 EmitCode(bitc::DEFINE_ABBREV); 434 EmitCode(naclbitc::DEFINE_ABBREV);
455 EmitVBR(Abbv->getNumOperandInfos(), 5); 435 EmitVBR(Abbv->getNumOperandInfos(), 5);
456 for (unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos()); 436 for (unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos());
457 i != e; ++i) { 437 i != e; ++i) {
458 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 438 const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
459 Emit(Op.isLiteral(), 1); 439 bool IsLiteral = Op.isLiteral();
460 if (Op.isLiteral()) { 440 Emit(IsLiteral, 1);
461 EmitVBR64(Op.getLiteralValue(), 8); 441 if (IsLiteral) {
442 EmitVBR64(Op.getValue(), 8);
462 } else { 443 } else {
463 Emit(Op.getEncoding(), 3); 444 Emit(Op.getEncoding(), 3);
464 if (Op.hasEncodingData()) 445 if (Op.hasValue())
465 EmitVBR64(Op.getEncodingData(), 5); 446 EmitVBR64(Op.getValue(), 5);
466 } 447 }
467 } 448 }
468 } 449 }
469 public: 450 public:
470 451
471 /// EmitAbbrev - This emits an abbreviation to the stream. Note that this 452 /// EmitAbbrev - This emits an abbreviation to the stream. Note that this
472 /// method takes ownership of the specified abbrev. 453 /// method takes ownership of the specified abbrev.
473 unsigned EmitAbbrev(BitCodeAbbrev *Abbv) { 454 unsigned EmitAbbrev(NaClBitCodeAbbrev *Abbv) {
455 assert(Abbv->isValid() && "Can't emit invalid abbreviation!");
474 // Emit the abbreviation as a record. 456 // Emit the abbreviation as a record.
475 EncodeAbbrev(Abbv); 457 EncodeAbbrev(Abbv);
476 CurAbbrevs.push_back(Abbv); 458 CurAbbrevs.push_back(Abbv);
477 return static_cast<unsigned>(CurAbbrevs.size())-1 + 459 return static_cast<unsigned>(CurAbbrevs.size())-1 +
478 bitc::FIRST_APPLICATION_ABBREV; 460 naclbitc::FIRST_APPLICATION_ABBREV;
479 } 461 }
480 462
481 //===--------------------------------------------------------------------===// 463 //===--------------------------------------------------------------------===//
482 // BlockInfo Block Emission 464 // BlockInfo Block Emission
483 //===--------------------------------------------------------------------===// 465 //===--------------------------------------------------------------------===//
484 466
485 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. 467 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
486 void EnterBlockInfoBlock(unsigned CodeWidth) { 468 void EnterBlockInfoBlock() {
487 EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth); 469 EnterSubblock(naclbitc::BLOCKINFO_BLOCK_ID);
488 BlockInfoCurBID = ~0U; 470 BlockInfoCurBID = ~0U;
489 } 471 }
490 private: 472 private:
491 /// SwitchToBlockID - If we aren't already talking about the specified block 473 /// SwitchToBlockID - If we aren't already talking about the specified block
492 /// ID, emit a BLOCKINFO_CODE_SETBID record. 474 /// ID, emit a BLOCKINFO_CODE_SETBID record.
493 void SwitchToBlockID(unsigned BlockID) { 475 void SwitchToBlockID(unsigned BlockID) {
494 if (BlockInfoCurBID == BlockID) return; 476 if (BlockInfoCurBID == BlockID) return;
495 SmallVector<unsigned, 2> V; 477 SmallVector<unsigned, 2> V;
496 V.push_back(BlockID); 478 V.push_back(BlockID);
497 EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V); 479 EmitRecord(naclbitc::BLOCKINFO_CODE_SETBID, V);
498 BlockInfoCurBID = BlockID; 480 BlockInfoCurBID = BlockID;
499 } 481 }
500 482
501 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { 483 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
502 if (BlockInfo *BI = getBlockInfo(BlockID)) 484 if (BlockInfo *BI = getBlockInfo(BlockID))
503 return *BI; 485 return *BI;
504 486
505 // Otherwise, add a new record. 487 // Otherwise, add a new record.
506 BlockInfoRecords.push_back(BlockInfo()); 488 BlockInfoRecords.push_back(BlockInfo());
507 BlockInfoRecords.back().BlockID = BlockID; 489 BlockInfoRecords.back().BlockID = BlockID;
508 return BlockInfoRecords.back(); 490 return BlockInfoRecords.back();
509 } 491 }
510 492
511 public: 493 public:
512 494
513 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified 495 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified
514 /// BlockID. 496 /// BlockID.
515 unsigned EmitBlockInfoAbbrev(unsigned BlockID, BitCodeAbbrev *Abbv) { 497 unsigned EmitBlockInfoAbbrev(unsigned BlockID, NaClBitCodeAbbrev *Abbv) {
516 SwitchToBlockID(BlockID); 498 SwitchToBlockID(BlockID);
517 EncodeAbbrev(Abbv); 499 EncodeAbbrev(Abbv);
518 500
519 // Add the abbrev to the specified block record. 501 // Add the abbrev to the specified block record.
520 BlockInfo &Info = getOrCreateBlockInfo(BlockID); 502 BlockInfo &Info = getOrCreateBlockInfo(BlockID);
521 Info.Abbrevs.push_back(Abbv); 503 Info.Abbrevs.push_back(Abbv);
522 504
523 return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; 505 return Info.Abbrevs.size()-1+naclbitc::FIRST_APPLICATION_ABBREV;
524 } 506 }
525 }; 507 };
526 508
527 509
528 } // End llvm namespace 510 } // End llvm namespace
529 511
530 #endif 512 #endif
OLDNEW
« no previous file with comments | « include/llvm/Bitcode/NaCl/NaClBitstreamReader.h ('k') | include/llvm/Bitcode/NaCl/NaClCompressBlockDist.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698