aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Bitcode
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Bitcode')
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp390
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.h10
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp113
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.cpp114
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.h3
5 files changed, 409 insertions, 221 deletions
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 963791f..1bdcfe9 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -31,7 +31,7 @@ void BitcodeReader::FreeState() {
if (BufferOwned)
delete Buffer;
Buffer = 0;
- std::vector<PATypeHolder>().swap(TypeList);
+ std::vector<Type*>().swap(TypeList);
ValueList.clear();
MDValueList.clear();
@@ -352,19 +352,28 @@ Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
return V;
}
-const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
- // If the TypeID is in range, return it.
- if (ID < TypeList.size())
- return TypeList[ID].get();
- if (!isTypeTable) return 0;
-
- // The type table allows forward references. Push as many Opaque types as
- // needed to get up to ID.
- while (TypeList.size() <= ID)
- TypeList.push_back(OpaqueType::get(Context));
- return TypeList.back().get();
+Type *BitcodeReader::getTypeByID(unsigned ID) {
+ // The type table size is always specified correctly.
+ if (ID >= TypeList.size())
+ return 0;
+
+ if (Type *Ty = TypeList[ID])
+ return Ty;
+
+ // If we have a forward reference, the only possible case is when it is to a
+ // named struct. Just create a placeholder for now.
+ return TypeList[ID] = StructType::createNamed(Context, "");
+}
+
+/// FIXME: Remove in LLVM 3.1, only used by ParseOldTypeTable.
+Type *BitcodeReader::getTypeByIDOrNull(unsigned ID) {
+ if (ID >= TypeList.size())
+ TypeList.resize(ID+1);
+
+ return TypeList[ID];
}
+
//===----------------------------------------------------------------------===//
// Functions for parsing blocks from the bitcode file
//===----------------------------------------------------------------------===//
@@ -471,17 +480,22 @@ bool BitcodeReader::ParseAttributeBlock() {
}
}
-
bool BitcodeReader::ParseTypeTable() {
- if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID))
+ if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
return Error("Malformed block record");
+
+ return ParseTypeTableBody();
+}
+bool BitcodeReader::ParseTypeTableBody() {
if (!TypeList.empty())
return Error("Multiple TYPE_BLOCKs found!");
SmallVector<uint64_t, 64> Record;
unsigned NumRecords = 0;
+ SmallString<64> TypeName;
+
// Read all the records for this type table.
while (1) {
unsigned Code = Stream.ReadCode();
@@ -508,17 +522,15 @@ bool BitcodeReader::ParseTypeTable() {
// Read a record.
Record.clear();
- const Type *ResultTy = 0;
+ Type *ResultTy = 0;
switch (Stream.ReadRecord(Code, Record)) {
- default: // Default behavior: unknown type.
- ResultTy = 0;
- break;
+ default: return Error("unknown type in type table");
case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
// TYPE_CODE_NUMENTRY contains a count of the number of types in the
// type list. This allows us to reserve space.
if (Record.size() < 1)
return Error("Invalid TYPE_CODE_NUMENTRY record");
- TypeList.reserve(Record[0]);
+ TypeList.resize(Record[0]);
continue;
case bitc::TYPE_CODE_VOID: // VOID
ResultTy = Type::getVoidTy(Context);
@@ -541,9 +553,6 @@ bool BitcodeReader::ParseTypeTable() {
case bitc::TYPE_CODE_LABEL: // LABEL
ResultTy = Type::getLabelTy(Context);
break;
- case bitc::TYPE_CODE_OPAQUE: // OPAQUE
- ResultTy = 0;
- break;
case bitc::TYPE_CODE_METADATA: // METADATA
ResultTy = Type::getMetadataTy(Context);
break;
@@ -563,8 +572,9 @@ bool BitcodeReader::ParseTypeTable() {
unsigned AddressSpace = 0;
if (Record.size() == 2)
AddressSpace = Record[1];
- ResultTy = PointerType::get(getTypeByID(Record[0], true),
- AddressSpace);
+ ResultTy = getTypeByID(Record[0]);
+ if (ResultTy == 0) return Error("invalid element type in pointer type");
+ ResultTy = PointerType::get(ResultTy, AddressSpace);
break;
}
case bitc::TYPE_CODE_FUNCTION: {
@@ -573,68 +583,305 @@ bool BitcodeReader::ParseTypeTable() {
if (Record.size() < 3)
return Error("Invalid FUNCTION type record");
std::vector<const Type*> ArgTys;
- for (unsigned i = 3, e = Record.size(); i != e; ++i)
- ArgTys.push_back(getTypeByID(Record[i], true));
+ for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ ArgTys.push_back(T);
+ else
+ break;
+ }
+
+ ResultTy = getTypeByID(Record[2]);
+ if (ResultTy == 0 || ArgTys.size() < Record.size()-3)
+ return Error("invalid type in function type");
- ResultTy = FunctionType::get(getTypeByID(Record[2], true), ArgTys,
- Record[0]);
+ ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
break;
}
- case bitc::TYPE_CODE_STRUCT: { // STRUCT: [ispacked, eltty x N]
+ case bitc::TYPE_CODE_STRUCT_ANON: { // STRUCT: [ispacked, eltty x N]
if (Record.size() < 1)
return Error("Invalid STRUCT type record");
- std::vector<const Type*> EltTys;
- for (unsigned i = 1, e = Record.size(); i != e; ++i)
- EltTys.push_back(getTypeByID(Record[i], true));
+ std::vector<Type*> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ EltTys.push_back(T);
+ else
+ break;
+ }
+ if (EltTys.size() != Record.size()-1)
+ return Error("invalid type in struct type");
ResultTy = StructType::get(Context, EltTys, Record[0]);
break;
}
+ case bitc::TYPE_CODE_STRUCT_NAME: // STRUCT_NAME: [strchr x N]
+ if (ConvertToString(Record, 0, TypeName))
+ return Error("Invalid STRUCT_NAME record");
+ continue;
+
+ case bitc::TYPE_CODE_STRUCT_NAMED: { // STRUCT: [ispacked, eltty x N]
+ if (Record.size() < 1)
+ return Error("Invalid STRUCT type record");
+
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ // Check to see if this was forward referenced, if so fill in the temp.
+ StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+ if (Res) {
+ Res->setName(TypeName);
+ TypeList[NumRecords] = 0;
+ } else // Otherwise, create a new struct.
+ Res = StructType::createNamed(Context, TypeName);
+ TypeName.clear();
+
+ SmallVector<Type*, 8> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ EltTys.push_back(T);
+ else
+ break;
+ }
+ if (EltTys.size() != Record.size()-1)
+ return Error("invalid STRUCT type record");
+ Res->setBody(EltTys, Record[0]);
+ ResultTy = Res;
+ break;
+ }
+ case bitc::TYPE_CODE_OPAQUE: { // OPAQUE: []
+ if (Record.size() != 1)
+ return Error("Invalid OPAQUE type record");
+
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ // Check to see if this was forward referenced, if so fill in the temp.
+ StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+ if (Res) {
+ Res->setName(TypeName);
+ TypeList[NumRecords] = 0;
+ } else // Otherwise, create a new struct with no body.
+ Res = StructType::createNamed(Context, TypeName);
+ TypeName.clear();
+ ResultTy = Res;
+ break;
+ }
case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid ARRAY type record");
- ResultTy = ArrayType::get(getTypeByID(Record[1], true), Record[0]);
+ if ((ResultTy = getTypeByID(Record[1])))
+ ResultTy = ArrayType::get(ResultTy, Record[0]);
+ else
+ return Error("Invalid ARRAY type element");
break;
case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid VECTOR type record");
- ResultTy = VectorType::get(getTypeByID(Record[1], true), Record[0]);
+ if ((ResultTy = getTypeByID(Record[1])))
+ ResultTy = VectorType::get(ResultTy, Record[0]);
+ else
+ return Error("Invalid ARRAY type element");
break;
}
- if (NumRecords == TypeList.size()) {
- // If this is a new type slot, just append it.
- TypeList.push_back(ResultTy ? ResultTy : OpaqueType::get(Context));
- ++NumRecords;
- } else if (ResultTy == 0) {
- // Otherwise, this was forward referenced, so an opaque type was created,
- // but the result type is actually just an opaque. Leave the one we
- // created previously.
- ++NumRecords;
- } else {
- // Otherwise, this was forward referenced, so an opaque type was created.
- // Resolve the opaque type to the real type now.
- assert(NumRecords < TypeList.size() && "Typelist imbalance");
- const OpaqueType *OldTy = cast<OpaqueType>(TypeList[NumRecords++].get());
-
- // Don't directly push the new type on the Tab. Instead we want to replace
- // the opaque type we previously inserted with the new concrete value. The
- // refinement from the abstract (opaque) type to the new type causes all
- // uses of the abstract type to use the concrete type (NewTy). This will
- // also cause the opaque type to be deleted.
- const_cast<OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
-
- // This should have replaced the old opaque type with the new type in the
- // value table... or with a preexisting type that was already in the
- // system. Let's just make sure it did.
- assert(TypeList[NumRecords-1].get() != OldTy &&
- "refineAbstractType didn't work!");
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+ assert(ResultTy && "Didn't read a type?");
+ assert(TypeList[NumRecords] == 0 && "Already read type?");
+ TypeList[NumRecords++] = ResultTy;
+ }
+}
+
+// FIXME: Remove in LLVM 3.1
+bool BitcodeReader::ParseOldTypeTable() {
+ if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_OLD))
+ return Error("Malformed block record");
+
+ if (!TypeList.empty())
+ return Error("Multiple TYPE_BLOCKs found!");
+
+
+ // While horrible, we have no good ordering of types in the bc file. Just
+ // iteratively parse types out of the bc file in multiple passes until we get
+ // them all. Do this by saving a cursor for the start of the type block.
+ BitstreamCursor StartOfTypeBlockCursor(Stream);
+
+ unsigned NumTypesRead = 0;
+
+ SmallVector<uint64_t, 64> Record;
+RestartScan:
+ unsigned NextTypeID = 0;
+ bool ReadAnyTypes = false;
+
+ // Read all the records for this type table.
+ while (1) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == bitc::END_BLOCK) {
+ if (NextTypeID != TypeList.size())
+ return Error("Invalid type forward reference in TYPE_BLOCK_ID_OLD");
+
+ // If we haven't read all of the types yet, iterate again.
+ if (NumTypesRead != TypeList.size()) {
+ // If we didn't successfully read any types in this pass, then we must
+ // have an unhandled forward reference.
+ if (!ReadAnyTypes)
+ return Error("Obsolete bitcode contains unhandled recursive type");
+
+ Stream = StartOfTypeBlockCursor;
+ goto RestartScan;
+ }
+
+ if (Stream.ReadBlockEnd())
+ return Error("Error at end of type table block");
+ return false;
+ }
+
+ if (Code == bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ continue;
}
+
+ if (Code == bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ Record.clear();
+ Type *ResultTy = 0;
+ switch (Stream.ReadRecord(Code, Record)) {
+ default: return Error("unknown type in type table");
+ case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+ // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+ // type list. This allows us to reserve space.
+ if (Record.size() < 1)
+ return Error("Invalid TYPE_CODE_NUMENTRY record");
+ TypeList.resize(Record[0]);
+ continue;
+ case bitc::TYPE_CODE_VOID: // VOID
+ ResultTy = Type::getVoidTy(Context);
+ break;
+ case bitc::TYPE_CODE_FLOAT: // FLOAT
+ ResultTy = Type::getFloatTy(Context);
+ break;
+ case bitc::TYPE_CODE_DOUBLE: // DOUBLE
+ ResultTy = Type::getDoubleTy(Context);
+ break;
+ case bitc::TYPE_CODE_X86_FP80: // X86_FP80
+ ResultTy = Type::getX86_FP80Ty(Context);
+ break;
+ case bitc::TYPE_CODE_FP128: // FP128
+ ResultTy = Type::getFP128Ty(Context);
+ break;
+ case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+ ResultTy = Type::getPPC_FP128Ty(Context);
+ break;
+ case bitc::TYPE_CODE_LABEL: // LABEL
+ ResultTy = Type::getLabelTy(Context);
+ break;
+ case bitc::TYPE_CODE_METADATA: // METADATA
+ ResultTy = Type::getMetadataTy(Context);
+ break;
+ case bitc::TYPE_CODE_X86_MMX: // X86_MMX
+ ResultTy = Type::getX86_MMXTy(Context);
+ break;
+ case bitc::TYPE_CODE_INTEGER: // INTEGER: [width]
+ if (Record.size() < 1)
+ return Error("Invalid Integer type record");
+ ResultTy = IntegerType::get(Context, Record[0]);
+ break;
+ case bitc::TYPE_CODE_OPAQUE: // OPAQUE
+ if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0)
+ ResultTy = StructType::createNamed(Context, "");
+ break;
+ case bitc::TYPE_CODE_STRUCT_OLD: {// STRUCT_OLD
+ if (NextTypeID >= TypeList.size()) break;
+ // If we already read it, don't reprocess.
+ if (TypeList[NextTypeID] &&
+ !cast<StructType>(TypeList[NextTypeID])->isOpaque())
+ break;
+
+ // Set a type.
+ if (TypeList[NextTypeID] == 0)
+ TypeList[NextTypeID] = StructType::createNamed(Context, "");
+
+ std::vector<Type*> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *Elt = getTypeByIDOrNull(Record[i]))
+ EltTys.push_back(Elt);
+ else
+ break;
+ }
+
+ if (EltTys.size() != Record.size()-1)
+ break; // Not all elements are ready.
+
+ cast<StructType>(TypeList[NextTypeID])->setBody(EltTys, Record[0]);
+ ResultTy = TypeList[NextTypeID];
+ TypeList[NextTypeID] = 0;
+ break;
+ }
+ case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+ // [pointee type, address space]
+ if (Record.size() < 1)
+ return Error("Invalid POINTER type record");
+ unsigned AddressSpace = 0;
+ if (Record.size() == 2)
+ AddressSpace = Record[1];
+ if ((ResultTy = getTypeByIDOrNull(Record[0])))
+ ResultTy = PointerType::get(ResultTy, AddressSpace);
+ break;
+ }
+ case bitc::TYPE_CODE_FUNCTION: {
+ // FIXME: attrid is dead, remove it in LLVM 3.0
+ // FUNCTION: [vararg, attrid, retty, paramty x N]
+ if (Record.size() < 3)
+ return Error("Invalid FUNCTION type record");
+ std::vector<const Type*> ArgTys;
+ for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+ if (Type *Elt = getTypeByIDOrNull(Record[i]))
+ ArgTys.push_back(Elt);
+ else
+ break;
+ }
+ if (ArgTys.size()+3 != Record.size())
+ break; // Something was null.
+ if ((ResultTy = getTypeByIDOrNull(Record[2])))
+ ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+ break;
+ }
+ case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
+ if (Record.size() < 2)
+ return Error("Invalid ARRAY type record");
+ if ((ResultTy = getTypeByIDOrNull(Record[1])))
+ ResultTy = ArrayType::get(ResultTy, Record[0]);
+ break;
+ case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
+ if (Record.size() < 2)
+ return Error("Invalid VECTOR type record");
+ if ((ResultTy = getTypeByIDOrNull(Record[1])))
+ ResultTy = VectorType::get(ResultTy, Record[0]);
+ break;
+ }
+
+ if (NextTypeID >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ if (ResultTy && TypeList[NextTypeID] == 0) {
+ ++NumTypesRead;
+ ReadAnyTypes = true;
+
+ TypeList[NextTypeID] = ResultTy;
+ }
+
+ ++NextTypeID;
}
}
-bool BitcodeReader::ParseTypeSymbolTable() {
- if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID))
+bool BitcodeReader::ParseOldTypeSymbolTable() {
+ if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID_OLD))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
@@ -674,7 +921,10 @@ bool BitcodeReader::ParseTypeSymbolTable() {
if (TypeID >= TypeList.size())
return Error("Invalid Type ID in TST_ENTRY record");
- TheModule->addTypeName(TypeName, TypeList[TypeID].get());
+ // Only apply the type name to a struct type with no name.
+ if (StructType *STy = dyn_cast<StructType>(TypeList[TypeID]))
+ if (!STy->isAnonymous() && !STy->hasName())
+ STy->setName(TypeName);
TypeName.clear();
break;
}
@@ -1310,12 +1560,16 @@ bool BitcodeReader::ParseModule() {
if (ParseAttributeBlock())
return true;
break;
- case bitc::TYPE_BLOCK_ID:
+ case bitc::TYPE_BLOCK_ID_NEW:
if (ParseTypeTable())
return true;
break;
- case bitc::TYPE_SYMTAB_BLOCK_ID:
- if (ParseTypeSymbolTable())
+ case bitc::TYPE_BLOCK_ID_OLD:
+ if (ParseOldTypeTable())
+ return true;
+ break;
+ case bitc::TYPE_SYMTAB_BLOCK_ID_OLD:
+ if (ParseOldTypeSymbolTable())
return true;
break;
case bitc::VALUE_SYMTAB_BLOCK_ID:
@@ -2307,7 +2561,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
SmallVector<Value*, 16> Args;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
- if (FTy->getParamType(i)->getTypeID()==Type::LabelTyID)
+ if (FTy->getParamType(i)->isLabelTy())
Args.push_back(getBasicBlock(Record[OpNum]));
else
Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index 14033b0..1b3bf1a 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -131,7 +131,7 @@ class BitcodeReader : public GVMaterializer {
const char *ErrorString;
- std::vector<PATypeHolder> TypeList;
+ std::vector<Type*> TypeList;
BitcodeReaderValueList ValueList;
BitcodeReaderMDValueList MDValueList;
SmallVector<Instruction *, 64> InstructionList;
@@ -210,7 +210,8 @@ public:
/// @returns true if an error occurred.
bool ParseTriple(std::string &Triple);
private:
- const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
+ Type *getTypeByID(unsigned ID);
+ Type *getTypeByIDOrNull(unsigned ID);
Value *getFnValueByID(unsigned ID, const Type *Ty) {
if (Ty && Ty->isMetadataTy())
return MDValueList.getValueFwdRef(ID);
@@ -258,7 +259,10 @@ private:
bool ParseModule();
bool ParseAttributeBlock();
bool ParseTypeTable();
- bool ParseTypeSymbolTable();
+ bool ParseOldTypeTable(); // FIXME: Remove in LLVM 3.1
+ bool ParseTypeTableBody();
+
+ bool ParseOldTypeSymbolTable(); // FIXME: Remove in LLVM 3.1
bool ParseValueSymbolTable();
bool ParseConstants();
bool RememberAndSkipFunctionBody();
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 24b5e2d..85d67ce 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -21,7 +21,6 @@
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Operator.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
@@ -29,6 +28,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Program.h"
#include <cctype>
+#include <map>
using namespace llvm;
/// These are manifest constants used by the bitcode writer. They do not need to
@@ -101,13 +101,16 @@ static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
}
}
-static void WriteStringRecord(unsigned Code, const std::string &Str,
+static void WriteStringRecord(unsigned Code, StringRef Str,
unsigned AbbrevToUse, BitstreamWriter &Stream) {
SmallVector<unsigned, 64> Vals;
// Code: [strchar x N]
- for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (AbbrevToUse && !BitCodeAbbrevOp::isChar6(Str[i]))
+ AbbrevToUse = 0;
Vals.push_back(Str[i]);
+ }
// Emit the finished record.
Stream.EmitRecord(Code, Vals, AbbrevToUse);
@@ -151,7 +154,7 @@ static void WriteAttributeTable(const ValueEnumerator &VE,
static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
const ValueEnumerator::TypeList &TypeList = VE.getTypes();
- Stream.EnterSubblock(bitc::TYPE_BLOCK_ID, 4 /*count from # abbrevs */);
+ Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */);
SmallVector<uint64_t, 64> TypeVals;
// Abbrev for TYPE_CODE_POINTER.
@@ -172,15 +175,32 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
Log2_32_Ceil(VE.getTypes().size()+1)));
unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv);
- // Abbrev for TYPE_CODE_STRUCT.
+ // Abbrev for TYPE_CODE_STRUCT_ANON.
+ Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_ANON));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
+ Log2_32_Ceil(VE.getTypes().size()+1)));
+ unsigned StructAnonAbbrev = Stream.EmitAbbrev(Abbv);
+
+ // Abbrev for TYPE_CODE_STRUCT_NAME.
+ Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAME));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
+ unsigned StructNameAbbrev = Stream.EmitAbbrev(Abbv);
+
+ // Abbrev for TYPE_CODE_STRUCT_NAMED.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT));
+ Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAMED));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getTypes().size()+1)));
- unsigned StructAbbrev = Stream.EmitAbbrev(Abbv);
+ unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv);
+
// Abbrev for TYPE_CODE_ARRAY.
Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY));
@@ -202,16 +222,15 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
switch (T->getTypeID()) {
default: llvm_unreachable("Unknown type!");
- case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
- case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
- case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
- case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
- case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
+ case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
+ case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
+ case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
+ case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
+ case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break;
- case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
- case Type::OpaqueTyID: Code = bitc::TYPE_CODE_OPAQUE; break;
- case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
- case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
+ case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
+ case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
+ case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
case Type::IntegerTyID:
// INTEGER: [width]
Code = bitc::TYPE_CODE_INTEGER;
@@ -242,13 +261,28 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
case Type::StructTyID: {
const StructType *ST = cast<StructType>(T);
// STRUCT: [ispacked, eltty x N]
- Code = bitc::TYPE_CODE_STRUCT;
TypeVals.push_back(ST->isPacked());
// Output all of the element types.
for (StructType::element_iterator I = ST->element_begin(),
E = ST->element_end(); I != E; ++I)
TypeVals.push_back(VE.getTypeID(*I));
- AbbrevToUse = StructAbbrev;
+
+ if (ST->isAnonymous()) {
+ Code = bitc::TYPE_CODE_STRUCT_ANON;
+ AbbrevToUse = StructAnonAbbrev;
+ } else {
+ if (ST->isOpaque()) {
+ Code = bitc::TYPE_CODE_OPAQUE;
+ } else {
+ Code = bitc::TYPE_CODE_STRUCT_NAMED;
+ AbbrevToUse = StructNamedAbbrev;
+ }
+
+ // Emit the name if it is present.
+ if (!ST->getName().empty())
+ WriteStringRecord(bitc::TYPE_CODE_STRUCT_NAME, ST->getName(),
+ StructNameAbbrev, Stream);
+ }
break;
}
case Type::ArrayTyID: {
@@ -1278,46 +1312,6 @@ static void WriteFunction(const Function &F, ValueEnumerator &VE,
Stream.ExitBlock();
}
-/// WriteTypeSymbolTable - Emit a block for the specified type symtab.
-static void WriteTypeSymbolTable(const TypeSymbolTable &TST,
- const ValueEnumerator &VE,
- BitstreamWriter &Stream) {
- if (TST.empty()) return;
-
- Stream.EnterSubblock(bitc::TYPE_SYMTAB_BLOCK_ID, 3);
-
- // 7-bit fixed width VST_CODE_ENTRY strings.
- BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
- Log2_32_Ceil(VE.getTypes().size()+1)));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
- unsigned V7Abbrev = Stream.EmitAbbrev(Abbv);
-
- SmallVector<unsigned, 64> NameVals;
-
- for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
- TI != TE; ++TI) {
- // TST_ENTRY: [typeid, namechar x N]
- NameVals.push_back(VE.getTypeID(TI->second));
-
- const std::string &Str = TI->first;
- bool is7Bit = true;
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- NameVals.push_back((unsigned char)Str[i]);
- if (Str[i] & 128)
- is7Bit = false;
- }
-
- // Emit the finished record.
- Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, is7Bit ? V7Abbrev : 0);
- NameVals.clear();
- }
-
- Stream.ExitBlock();
-}
-
// Emit blockinfo, which defines the standard abbreviations etc.
static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) {
// We only want to emit block info records for blocks that have multiple
@@ -1521,9 +1515,6 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
// Emit metadata.
WriteModuleMetadataStore(M, Stream);
- // Emit the type symbol table information.
- WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream);
-
// Emit names for globals/functions etc.
WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream);
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index 5138c3c..b68bf92 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -17,7 +17,6 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Instructions.h"
#include <algorithm>
@@ -59,9 +58,6 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
I != E; ++I)
EnumerateValue(I->getAliasee());
- // Enumerate types used by the type symbol table.
- EnumerateTypeSymbolTable(M->getTypeSymbolTable());
-
// Insert constants and metadata that are named at module level into the slot
// pool so that the module symbol table can refer to them...
EnumerateValueSymbolTable(M->getValueSymbolTable());
@@ -109,78 +105,12 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
// Optimize constant ordering.
OptimizeConstants(FirstConstant, Values.size());
-
- OptimizeTypes();
-
- // Now that we rearranged the type table, rebuild TypeMap.
- for (unsigned i = 0, e = Types.size(); i != e; ++i)
- TypeMap[Types[i]] = i+1;
-}
-
-struct TypeAndDeps {
- const Type *Ty;
- unsigned NumDeps;
-};
-
-static int CompareByDeps(const void *a, const void *b) {
- const TypeAndDeps &ta = *(const TypeAndDeps*) a;
- const TypeAndDeps &tb = *(const TypeAndDeps*) b;
- return ta.NumDeps - tb.NumDeps;
-}
-
-static void VisitType(const Type *Ty, SmallPtrSet<const Type*, 16> &Visited,
- std::vector<const Type*> &Out) {
- if (Visited.count(Ty))
- return;
-
- Visited.insert(Ty);
-
- for (Type::subtype_iterator I2 = Ty->subtype_begin(),
- E2 = Ty->subtype_end(); I2 != E2; ++I2) {
- const Type *InnerType = I2->get();
- VisitType(InnerType, Visited, Out);
- }
-
- Out.push_back(Ty);
}
-void ValueEnumerator::OptimizeTypes(void) {
- // If the types form a DAG, this will compute a topological sort and
- // no forward references will be needed when reading them in.
- // If there are cycles, this is a simple but reasonable heuristic for
- // the minimum feedback arc set problem.
- const unsigned NumTypes = Types.size();
- std::vector<TypeAndDeps> TypeDeps;
- TypeDeps.resize(NumTypes);
-
- for (unsigned I = 0; I < NumTypes; ++I) {
- const Type *Ty = Types[I];
- TypeDeps[I].Ty = Ty;
- TypeDeps[I].NumDeps = 0;
- }
-
- for (unsigned I = 0; I < NumTypes; ++I) {
- const Type *Ty = TypeDeps[I].Ty;
- for (Type::subtype_iterator I2 = Ty->subtype_begin(),
- E2 = Ty->subtype_end(); I2 != E2; ++I2) {
- const Type *InnerType = I2->get();
- unsigned InnerIndex = TypeMap.lookup(InnerType) - 1;
- TypeDeps[InnerIndex].NumDeps++;
- }
- }
- array_pod_sort(TypeDeps.begin(), TypeDeps.end(), CompareByDeps);
-
- SmallPtrSet<const Type*, 16> Visited;
- Types.clear();
- Types.reserve(NumTypes);
- for (unsigned I = 0; I < NumTypes; ++I) {
- VisitType(TypeDeps[I].Ty, Visited, Types);
- }
-}
unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const {
InstructionMapType::const_iterator I = InstructionMap.find(Inst);
- assert (I != InstructionMap.end() && "Instruction is not mapped!");
+ assert(I != InstructionMap.end() && "Instruction is not mapped!");
return I->second;
}
@@ -235,14 +165,6 @@ void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) {
}
-/// EnumerateTypeSymbolTable - Insert all of the types in the specified symbol
-/// table.
-void ValueEnumerator::EnumerateTypeSymbolTable(const TypeSymbolTable &TST) {
- for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
- TI != TE; ++TI)
- EnumerateType(TI->second);
-}
-
/// EnumerateValueSymbolTable - Insert all of the values in the specified symbol
/// table into the values table.
void ValueEnumerator::EnumerateValueSymbolTable(const ValueSymbolTable &VST) {
@@ -394,20 +316,40 @@ void ValueEnumerator::EnumerateValue(const Value *V) {
void ValueEnumerator::EnumerateType(const Type *Ty) {
- unsigned &TypeID = TypeMap[Ty];
+ unsigned *TypeID = &TypeMap[Ty];
// We've already seen this type.
- if (TypeID)
+ if (*TypeID)
return;
- // First time we saw this type, add it.
- Types.push_back(Ty);
- TypeID = Types.size();
-
- // Enumerate subtypes.
+ // If it is a non-anonymous struct, mark the type as being visited so that we
+ // don't recursively visit it. This is safe because we allow forward
+ // references of these in the bitcode reader.
+ if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (!STy->isAnonymous())
+ *TypeID = ~0U;
+
+ // Enumerate all of the subtypes before we enumerate this type. This ensures
+ // that the type will be enumerated in an order that can be directly built.
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
I != E; ++I)
EnumerateType(*I);
+
+ // Refresh the TypeID pointer in case the table rehashed.
+ TypeID = &TypeMap[Ty];
+
+ // Check to see if we got the pointer another way. This can happen when
+ // enumerating recursive types that hit the base case deeper than they start.
+ //
+ // If this is actually a struct that we are treating as forward ref'able,
+ // then emit the definition now that all of its contents are available.
+ if (*TypeID && *TypeID != ~0U)
+ return;
+
+ // Add this type now that its contents are all happily enumerated.
+ Types.push_back(Ty);
+
+ *TypeID = Types.size();
}
// Enumerate the types for the specified value. If the value is a constant,
diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h
index 1e42a26..6617b60 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.h
+++ b/lib/Bitcode/Writer/ValueEnumerator.h
@@ -30,7 +30,6 @@ class Module;
class MDNode;
class NamedMDNode;
class AttrListPtr;
-class TypeSymbolTable;
class ValueSymbolTable;
class MDSymbolTable;
@@ -135,7 +134,6 @@ public:
private:
void OptimizeConstants(unsigned CstStart, unsigned CstEnd);
- void OptimizeTypes();
void EnumerateMDNodeOperands(const MDNode *N);
void EnumerateMetadata(const Value *MD);
@@ -146,7 +144,6 @@ private:
void EnumerateOperandType(const Value *V);
void EnumerateAttributes(const AttrListPtr &PAL);
- void EnumerateTypeSymbolTable(const TypeSymbolTable &ST);
void EnumerateValueSymbolTable(const ValueSymbolTable &ST);
void EnumerateNamedMetadata(const Module *M);
};