diff --git a/llvm/lib/Bytecode/Writer/ConstantWriter.cpp b/llvm/lib/Bytecode/Writer/ConstantWriter.cpp index 12043b048a16..02569ec33d48 100644 --- a/llvm/lib/Bytecode/Writer/ConstantWriter.cpp +++ b/llvm/lib/Bytecode/Writer/ConstantWriter.cpp @@ -26,6 +26,12 @@ ConstantBytes("bytecodewriter", "Bytes of constants"); static Statistic<> NumConstants("bytecodewriter", "Number of constants"); +static Statistic<> +NumStrConstants("bytecodewriter", "Number of string constants"); +static Statistic<> +NumStrBytes("bytecodewriter", "Number of string constant bytes"); + + void BytecodeWriter::outputType(const Type *T) { TypeBytes -= Out.size(); output_vbr((unsigned)T->getPrimitiveID(), Out); @@ -109,7 +115,7 @@ void BytecodeWriter::outputType(const Type *T) { TypeBytes += Out.size(); } -bool BytecodeWriter::outputConstant(const Constant *CPV) { +void BytecodeWriter::outputConstant(const Constant *CPV) { ConstantBytes -= Out.size(); assert((CPV->getType()->isPrimitiveType() || !CPV->isNullValue()) && "Shouldn't output null constants!"); @@ -133,7 +139,7 @@ bool BytecodeWriter::outputConstant(const Constant *CPV) { output_vbr((unsigned)Slot, Out); } ConstantBytes += Out.size(); - return false; + return; } else { output_vbr(0U, Out); // flag as not a ConstantExpr } @@ -166,10 +172,9 @@ bool BytecodeWriter::outputConstant(const Constant *CPV) { case Type::ArrayTyID: { const ConstantArray *CPA = cast(CPV); - unsigned size = CPA->getValues().size(); - assert(size == cast(CPA->getType())->getNumElements() - && "ConstantArray out of whack!"); - for (unsigned i = 0; i < size; i++) { + assert(!CPA->isString() && "Constant strings should be handled specially!"); + + for (unsigned i = 0; i != CPA->getNumOperands(); ++i) { int Slot = Table.getSlot(CPA->getOperand(i)); assert(Slot != -1 && "Constant used but not available!!"); output_vbr((unsigned)Slot, Out); @@ -215,6 +220,38 @@ bool BytecodeWriter::outputConstant(const Constant *CPV) { << " type '" << CPV->getType()->getName() << "'\n"; break; } - ConstantBytes += Out.size(); - return false; + ConstantBytes += Out.size(); + return; +} + +void BytecodeWriter::outputConstantStrings() { + SlotCalculator::string_iterator I = Table.string_begin(); + SlotCalculator::string_iterator E = Table.string_end(); + if (I == E) return; // No strings to emit + + // If we have != 0 strings to emit, output them now. Strings are emitted into + // the 'void' type plane. + output_vbr(unsigned(E-I), Out); + output_vbr(Type::VoidTyID, Out); + + ConstantBytes -= Out.size(); + NumStrBytes -= Out.size();; + + // Emit all of the strings. + for (I = Table.string_begin(); I != E; ++I) { + const ConstantArray *Str = *I; + int Slot = Table.getSlot(Str->getType()); + assert(Slot != -1 && "Constant string of unknown type?"); + output_vbr((unsigned)Slot, Out); + + // Now that we emitted the type (which indicates the size of the string), + // emit all of the characters. + std::string Val = Str->getAsString(); + output_data(Val.c_str(), Val.c_str()+Val.size(), Out); + + ++NumConstants; + ++NumStrConstants; + } + ConstantBytes += Out.size(); + NumStrBytes += Out.size();; } diff --git a/llvm/lib/Bytecode/Writer/Writer.cpp b/llvm/lib/Bytecode/Writer/Writer.cpp index ca50b5a7bd38..2020a3a2bd64 100644 --- a/llvm/lib/Bytecode/Writer/Writer.cpp +++ b/llvm/lib/Bytecode/Writer/Writer.cpp @@ -24,9 +24,10 @@ #include "WriterInternals.h" #include "llvm/Bytecode/WriteBytecodePass.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/SymbolTable.h" -#include "llvm/DerivedTypes.h" #include "Support/STLExtras.h" #include "Support/Statistic.h" #include "Support/Debug.h" @@ -54,7 +55,9 @@ ModuleInfoBytes("bytecodewriter", "Bytes of module info"); BytecodeWriter::BytecodeWriter(std::deque &o, const Module *M) : Out(o), Table(M, true) { - outputSignature(); + // Emit the signature... + static const unsigned char *Sig = (const unsigned char*)"llvm"; + output_data(Sig, Sig+4, Out); // Emit the top level CLASS block. BytecodeBlock ModuleBlock(BytecodeFormat::Module, Out); @@ -111,9 +114,12 @@ void BytecodeWriter::outputConstantsInPlane(const std::vector &Plane, unsigned StartNo) { unsigned ValNo = StartNo; - // Scan through and ignore function arguments/global values... - for (; ValNo < Plane.size() && (isa(Plane[ValNo]) || - isa(Plane[ValNo])); ValNo++) + // Scan through and ignore function arguments, global values, and constant + // strings. + for (; ValNo < Plane.size() && + (isa(Plane[ValNo]) || isa(Plane[ValNo]) || + (isa(Plane[ValNo]) && + cast(Plane[ValNo])->isString())); ValNo++) /*empty*/; unsigned NC = ValNo; // Number of constants @@ -171,6 +177,10 @@ void BytecodeWriter::outputConstants(bool isFunction) { } } + // Output module-level string constants before any other constants.x + if (!isFunction) + outputConstantStrings(); + for (unsigned pno = 0; pno != NumPlanes; pno++) if (pno != Type::TypeTyID) { // Type plane handled above. const std::vector &Plane = Table.getPlane(pno); diff --git a/llvm/lib/Bytecode/Writer/WriterInternals.h b/llvm/lib/Bytecode/Writer/WriterInternals.h index 9fb778df2006..51ec362d846a 100644 --- a/llvm/lib/Bytecode/Writer/WriterInternals.h +++ b/llvm/lib/Bytecode/Writer/WriterInternals.h @@ -33,22 +33,17 @@ class BytecodeWriter { public: BytecodeWriter(std::deque &o, const Module *M); -protected: +private: void outputConstants(bool isFunction); + void outputConstantStrings(); void outputFunction(const Function *F); void processInstruction(const Instruction &I); -private : - inline void outputSignature() { - static const unsigned char *Sig = (const unsigned char*)"llvm"; - Out.insert(Out.end(), Sig, Sig+4); // output the bytecode signature... - } - void outputModuleInfoBlock(const Module *C); void outputSymbolTable(const SymbolTable &ST); void outputConstantsInPlane(const std::vector &Plane, unsigned StartNo); - bool outputConstant(const Constant *CPV); + void outputConstant(const Constant *CPV); void outputType(const Type *T); };