From: Chris Lattner Date: Mon, 23 Apr 2007 16:04:05 +0000 (+0000) Subject: first part of implementation of abbrevs. The writer isn't fully there yet and the X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=36d5e7d31be61f631ace0488f0d6cd71b8f31a16;p=oota-llvm.git first part of implementation of abbrevs. The writer isn't fully there yet and the reader doesn't handle them at all yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36363 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index a3b741b2e92..98d18b194bd 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -18,6 +18,10 @@ #ifndef LLVM_BITCODE_BITCODES_H #define LLVM_BITCODE_BITCODES_H +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include + namespace llvm { namespace bitc { enum StandardWidths { @@ -31,16 +35,71 @@ namespace bitc { enum FixedCodes { END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode. ENTER_SUBBLOCK = 1, + + /// DEFINE_ABBREV - Defines an abbrev for the current block. It consists + /// of a vbr5 for # operand infos. Each operand info is emitted with a + /// single bit to indicate if it is a literal encoding. If so, the value is + /// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed + /// by the info value as a vbr5 if needed. + DEFINE_ABBREV = 2, - // Two codes are reserved for defining abbrevs and for emitting an - // unabbreviated record. - DEFINE_ABBREVS = 2, + // UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by + // a vbr6 for the # operands, followed by vbr6's for each operand. UNABBREV_RECORD = 3, // This is not a code, this is a marker for the first abbrev assignment. FIRST_ABBREV = 4 }; } // End bitc namespace + +/// BitCodeAbbrevOp - This describes one or more operands in an abbreviation. +/// This is actually a union of two different things: +/// 1. It could be a literal integer value ("the operand is always 17"). +/// 2. It could be an encoding specification ("this operand encoded like so"). +/// +class BitCodeAbbrevOp { + uint64_t Val; // A literal value or data for an encoding. + bool IsLiteral : 1; // Indicate whether this is a literal value or not. + unsigned Enc : 3; // The encoding to use. +public: + enum Encoding { + FixedWidth = 1, // A fixed with field, Val specifies number of bits. + VBR = 2 // A VBR field where Val specifies the width of each chunk. + }; + + BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {} + BitCodeAbbrevOp(Encoding E, uint64_t Data) + : Val(Data), IsLiteral(false), Enc(E) {} + + bool isLiteral() const { return IsLiteral; } + bool isEncoding() const { return !IsLiteral; } + + // Accessors for literals. + uint64_t getLiteralValue() const { assert(isLiteral()); return Val; } + + // Accessors for encoding info. + Encoding getEncoding() const { assert(isEncoding()); return (Encoding)Enc; } + uint64_t getEncodingData() const { assert(isEncoding()); return Val; } + + bool hasEncodingData() const { return hasEncodingData(getEncoding()); } + static bool hasEncodingData(Encoding E) { + return true; + } +}; + +class BitCodeAbbrev { + SmallVector OperandList; +public: + + unsigned getNumOperandInfos() const { return OperandList.size(); } + const BitCodeAbbrevOp &getOperandInfo(unsigned N) const { + return OperandList[N]; + } + + void Add(const BitCodeAbbrevOp &OpInfo) { + OperandList.push_back(OpInfo); + } +}; } // End llvm namespace #endif diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index acb76237f1c..0ac71cd9da7 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -16,9 +16,6 @@ #define BITSTREAM_READER_H #include "llvm/Bitcode/BitCodes.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/DataTypes.h" -#include namespace llvm { diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 5de82932784..104508578d5 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -16,9 +16,6 @@ #define BITSTREAM_WRITER_H #include "llvm/Bitcode/BitCodes.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/DataTypes.h" -#include #include namespace llvm { @@ -39,11 +36,14 @@ class BitstreamWriter { struct Block { unsigned PrevCodeSize; unsigned StartSizeWord; + std::vector PrevAbbrevs; Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} }; /// BlockScope - This tracks the current blocks that we have entered. std::vector BlockScope; + + std::vector CurAbbrevs; public: BitstreamWriter(std::vector &O) : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} @@ -145,6 +145,12 @@ public: EmitVBR(CodeLen, bitc::CodeLenWidth); FlushToWord(); BlockScope.push_back(Block(CurCodeSize, Out.size()/4)); + + // Delete all abbrevs. + for (unsigned i = 0, e = CurAbbrevs.size(); i != e; ++i) + delete CurAbbrevs[i]; + + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); // Emit a placeholder, which will be replaced when the block is popped. Emit(0, bitc::BlockSizeWidth); @@ -153,8 +159,7 @@ public: void ExitBlock() { assert(!BlockScope.empty() && "Block scope imbalance!"); - Block B = BlockScope.back(); - BlockScope.pop_back(); + const Block &B = BlockScope.back(); // Block tail: // [END_BLOCK, ] @@ -171,8 +176,10 @@ public: Out[ByteNo++] = (unsigned char)(SizeInWords >> 16); Out[ByteNo++] = (unsigned char)(SizeInWords >> 24); - // Restore the outer block's code size. + // Restore the inner block's code size and abbrev table. CurCodeSize = B.PrevCodeSize; + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); } //===--------------------------------------------------------------------===// @@ -184,7 +191,14 @@ public: void EmitRecord(unsigned Code, SmallVectorImpl &Vals, unsigned Abbrev = 0) { if (Abbrev) { - assert(0 && "abbrevs not implemented yet!"); + unsigned AbbrevNo = Abbrev-bitc::FIRST_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + assert(0 && "TODO"); + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + } + + } else { // If we don't have an abbrev to use, emit this in its fully unabbreviated // form. @@ -212,6 +226,32 @@ public: EmitVBR(Vals[i], 6); } } + + //===--------------------------------------------------------------------===// + // Abbrev Emission + //===--------------------------------------------------------------------===// + + /// EmitAbbrev - This emits an abbreviation to the stream. Note that this + /// method takes ownership of the specified abbrev. + unsigned EmitAbbrev(BitCodeAbbrev *Abbv) { + // Emit the abbreviation as a record. + EmitCode(bitc::DEFINE_ABBREV); + EmitVBR(Abbv->getNumOperandInfos(), 5); + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + Emit(Op.isLiteral(), 1); + if (Op.isLiteral()) { + EmitVBR64(Op.getLiteralValue(), 8); + } else { + Emit(Op.getEncoding(), 3); + if (Op.hasEncodingData()) + EmitVBR64(Op.getEncodingData(), 5); + } + } + + CurAbbrevs.push_back(Abbv); + return CurAbbrevs.size()-1+bitc::FIRST_ABBREV; + } }; diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index be05f45619c..f464e33f6a0 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -93,7 +93,7 @@ bool BitcodeReader::ParseTypeTable(BitstreamReader &Stream) { continue; } - if (Code == bitc::DEFINE_ABBREVS) { + if (Code == bitc::DEFINE_ABBREV) { assert(0 && "Abbrevs not implemented yet!"); } @@ -230,7 +230,7 @@ bool BitcodeReader::ParseTypeSymbolTable(BitstreamReader &Stream) { continue; } - if (Code == bitc::DEFINE_ABBREVS) { + if (Code == bitc::DEFINE_ABBREV) { assert(0 && "Abbrevs not implemented yet!"); } @@ -293,7 +293,7 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream, continue; } - if (Code == bitc::DEFINE_ABBREVS) { + if (Code == bitc::DEFINE_ABBREV) { assert(0 && "Abbrevs not implemented yet!"); } @@ -345,7 +345,7 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream, // GLOBALVAR: [type, isconst, initid, // linkage, alignment, section, visibility, threadlocal] case bitc::MODULE_CODE_GLOBALVAR: { - if (Record.size() < 8) + if (Record.size() < 6) return Error("Invalid MODULE_CODE_GLOBALVAR record"); const Type *Ty = getTypeByID(Record[0]); if (!isa(Ty)) @@ -361,8 +361,10 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream, return Error("Invalid section ID"); Section = SectionTable[Record[5]-1]; } - GlobalValue::VisibilityTypes Visibility = GetDecodedVisibility(Record[6]); - bool isThreadLocal = Record[7]; + GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility; + if (Record.size() >= 6) Visibility = GetDecodedVisibility(Record[6]); + bool isThreadLocal = false; + if (Record.size() >= 7) isThreadLocal = Record[7]; GlobalVariable *NewGV = new GlobalVariable(Ty, isConstant, Linkage, 0, "", TheModule); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index b22d00c6acf..d78ea29b564 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -200,10 +200,14 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(), 0/*TODO*/, Stream); - // Emit information about sections. + // Emit information about sections, computing how many there are. Also + // compute the maximum alignment value. std::map SectionMap; + unsigned MaxAlignment = 0; for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); GV != E; ++GV) { + MaxAlignment = std::max(MaxAlignment, GV->getAlignment()); + if (!GV->hasSection()) continue; // Give section names unique ID's. unsigned &Entry = SectionMap[GV->getSection()]; @@ -213,6 +217,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Entry = SectionMap.size(); } for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { + MaxAlignment = std::max(MaxAlignment, F->getAlignment()); if (!F->hasSection()) continue; // Give section names unique ID's. unsigned &Entry = SectionMap[F->getSection()]; @@ -222,13 +227,37 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Entry = SectionMap.size(); } - // TODO: Emit abbrev, now that we know # sections. + // Emit abbrev for globals, now that we know # sections and max alignment. + unsigned SimpleGVarAbbrev = 0; + if (!M->global_empty() && 0) { + // Add an abbrev for common globals with no visibility or thread localness. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::FixedWidth, 1)); // Constant. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Initializer. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::FixedWidth, 3)); // Linkage. + if (MaxAlignment == 0) // Alignment. + Abbv->Add(BitCodeAbbrevOp(0)); + else { + unsigned MaxEncAlignment = Log2_32(MaxAlignment)+1; + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::FixedWidth, + Log2_32_Ceil(MaxEncAlignment))); + } + if (SectionMap.empty()) // Section. + Abbv->Add(BitCodeAbbrevOp(0)); + else + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::FixedWidth, + Log2_32_Ceil(SectionMap.size()))); + // Don't bother emitting vis + thread local. + SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv); + } // Emit the global variable information. SmallVector Vals; for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); GV != E; ++GV) { - + unsigned AbbrevToUse = 0; + // GLOBALVAR: [type, isconst, initid, // linkage, alignment, section, visibility, threadlocal] Vals.push_back(VE.getTypeID(GV->getType())); @@ -238,10 +267,14 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Vals.push_back(getEncodedLinkage(GV)); Vals.push_back(Log2_32(GV->getAlignment())+1); Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0); - Vals.push_back(getEncodedVisibility(GV)); - Vals.push_back(GV->isThreadLocal()); + if (GV->isThreadLocal() || + GV->getVisibility() != GlobalValue::DefaultVisibility) { + Vals.push_back(getEncodedVisibility(GV)); + Vals.push_back(GV->isThreadLocal()); + } else { + AbbrevToUse = SimpleGVarAbbrev; + } - unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse); Vals.clear(); }