BitstreamWriter.h revision a0c96a068ca7027644b5f1972f9c388fa542d278
1//===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by Chris Lattner and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This header defines the BitstreamWriter class. This class can be used to 11// write an arbitrary bitstream, regardless of its contents. 12// 13//===----------------------------------------------------------------------===// 14 15#ifndef BITSTREAM_WRITER_H 16#define BITSTREAM_WRITER_H 17 18#include "llvm/Bitcode/BitCodes.h" 19#include "llvm/ADT/SmallVector.h" 20#include "llvm/Support/DataTypes.h" 21#include <cassert> 22#include <vector> 23 24namespace llvm { 25 26class BitstreamWriter { 27 std::vector<unsigned char> &Out; 28 29 /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. 30 unsigned CurBit; 31 32 /// CurValue - The current value. Only bits < CurBit are valid. 33 uint32_t CurValue; 34 35 // CurCodeSize - This is the declared size of code values used for the current 36 // block, in bits. 37 unsigned CurCodeSize; 38 39 struct Block { 40 unsigned PrevCodeSize; 41 unsigned StartSizeWord; 42 Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} 43 }; 44 45 /// BlockScope - This tracks the current blocks that we have entered. 46 std::vector<Block> BlockScope; 47public: 48 BitstreamWriter(std::vector<unsigned char> &O) 49 : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} 50 51 ~BitstreamWriter() { 52 assert(CurBit == 0 && "Unflused data remaining"); 53 assert(BlockScope.empty() && "Block imbalance"); 54 } 55 //===--------------------------------------------------------------------===// 56 // Basic Primitives for emitting bits to the stream. 57 //===--------------------------------------------------------------------===// 58 59 void Emit(uint32_t Val, unsigned NumBits) { 60 assert(NumBits <= 32 && "Invalid value size!"); 61 assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!"); 62 CurValue |= Val << CurBit; 63 if (CurBit + NumBits < 32) { 64 CurBit += NumBits; 65 return; 66 } 67 68 // Add the current word. 69 unsigned V = CurValue; 70 Out.push_back((unsigned char)(V >> 0)); 71 Out.push_back((unsigned char)(V >> 8)); 72 Out.push_back((unsigned char)(V >> 16)); 73 Out.push_back((unsigned char)(V >> 24)); 74 75 if (CurBit) 76 CurValue = Val >> (32-CurBit); 77 else 78 CurValue = 0; 79 CurBit = (CurBit+NumBits) & 31; 80 } 81 82 void Emit64(uint64_t Val, unsigned NumBits) { 83 if (NumBits <= 32) 84 Emit((uint32_t)Val, NumBits); 85 else { 86 Emit((uint32_t)Val, 32); 87 Emit((uint32_t)(Val >> 32), NumBits-32); 88 } 89 } 90 91 void FlushToWord() { 92 if (CurBit) { 93 unsigned V = CurValue; 94 Out.push_back((unsigned char)(V >> 0)); 95 Out.push_back((unsigned char)(V >> 8)); 96 Out.push_back((unsigned char)(V >> 16)); 97 Out.push_back((unsigned char)(V >> 24)); 98 CurBit = 0; 99 CurValue = 0; 100 } 101 } 102 103 void EmitVBR(uint32_t Val, unsigned NumBits) { 104 uint32_t Threshold = 1U << (NumBits-1); 105 106 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 107 while (Val >= Threshold) { 108 Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits); 109 Val >>= NumBits-1; 110 } 111 112 Emit(Val, NumBits); 113 } 114 115 void EmitVBR64(uint64_t Val, unsigned NumBits) { 116 if ((uint32_t)Val == Val) 117 return EmitVBR((uint32_t)Val, NumBits); 118 119 uint64_t Threshold = 1U << (NumBits-1); 120 121 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 122 while (Val >= Threshold) { 123 Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) | 124 (1 << (NumBits-1)), NumBits); 125 Val >>= NumBits-1; 126 } 127 128 Emit((uint32_t)Val, NumBits); 129 } 130 131 /// EmitCode - Emit the specified code. 132 void EmitCode(unsigned Val) { 133 Emit(Val, CurCodeSize); 134 } 135 136 //===--------------------------------------------------------------------===// 137 // Block Manipulation 138 //===--------------------------------------------------------------------===// 139 140 void EnterSubblock(unsigned BlockID, unsigned CodeLen) { 141 // Block header: 142 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] 143 EmitCode(bitc::ENTER_SUBBLOCK); 144 EmitVBR(BlockID, bitc::BlockIDWidth); 145 EmitVBR(CodeLen, bitc::CodeLenWidth); 146 FlushToWord(); 147 BlockScope.push_back(Block(CurCodeSize, Out.size()/4)); 148 // Emit a placeholder, which will be replaced when the block is popped. 149 Emit(0, bitc::BlockSizeWidth); 150 151 CurCodeSize = CodeLen; 152 } 153 154 void ExitBlock() { 155 assert(!BlockScope.empty() && "Block scope imbalance!"); 156 Block B = BlockScope.back(); 157 BlockScope.pop_back(); 158 159 // Block tail: 160 // [END_BLOCK, <align4bytes>] 161 EmitCode(bitc::END_BLOCK); 162 FlushToWord(); 163 164 // Compute the size of the block, in words, not counting the size field. 165 unsigned SizeInWords = Out.size()/4-B.StartSizeWord - 1; 166 unsigned ByteNo = B.StartSizeWord*4; 167 168 // Update the block size field in the header of this sub-block. 169 Out[ByteNo++] = (unsigned char)(SizeInWords >> 0); 170 Out[ByteNo++] = (unsigned char)(SizeInWords >> 8); 171 Out[ByteNo++] = (unsigned char)(SizeInWords >> 16); 172 Out[ByteNo++] = (unsigned char)(SizeInWords >> 24); 173 174 // Restore the outer block's code size. 175 CurCodeSize = B.PrevCodeSize; 176 } 177 178 //===--------------------------------------------------------------------===// 179 // Record Emission 180 //===--------------------------------------------------------------------===// 181 182 /// EmitRecord - Emit the specified record to the stream, using an abbrev if 183 /// we have one to compress the output. 184 void EmitRecord(unsigned Code, SmallVectorImpl<uint64_t> &Vals, 185 unsigned Abbrev = 0) { 186 if (Abbrev) { 187 assert(0 && "abbrevs not implemented yet!"); 188 } else { 189 // If we don't have an abbrev to use, emit this in its fully unabbreviated 190 // form. 191 EmitCode(bitc::UNABBREV_RECORD); 192 EmitVBR(Code, 6); 193 EmitVBR(Vals.size(), 6); 194 for (unsigned i = 0, e = Vals.size(); i != e; ++i) 195 EmitVBR64(Vals[i], 6); 196 } 197 } 198 199 /// EmitRecord - Emit the specified record to the stream, using an abbrev if 200 /// we have one to compress the output. 201 void EmitRecord(unsigned Code, SmallVectorImpl<unsigned> &Vals, 202 unsigned Abbrev = 0) { 203 if (Abbrev) { 204 assert(0 && "abbrevs not implemented yet!"); 205 } else { 206 // If we don't have an abbrev to use, emit this in its fully unabbreviated 207 // form. 208 EmitCode(bitc::UNABBREV_RECORD); 209 EmitVBR(Code, 6); 210 EmitVBR(Vals.size(), 6); 211 for (unsigned i = 0, e = Vals.size(); i != e; ++i) 212 EmitVBR(Vals[i], 6); 213 } 214 } 215}; 216 217 218} // End llvm namespace 219 220#endif 221