#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
+#include "llvm/IR/UseListOrder.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include <map>
using namespace llvm;
-static cl::opt<bool>
-EnablePreserveUseListOrdering("enable-bc-uselist-preserve",
- cl::desc("Turn on experimental support for "
- "use-list order preservation."),
- cl::init(false), cl::Hidden);
-
/// These are manifest constants used by the bitcode writer. They do not need to
/// be kept in sync with the reader, but need to be consistent within this file.
enum {
return bitc::ATTR_KIND_BUILTIN;
case Attribute::ByVal:
return bitc::ATTR_KIND_BY_VAL;
+ case Attribute::InAlloca:
+ return bitc::ATTR_KIND_IN_ALLOCA;
case Attribute::Cold:
return bitc::ATTR_KIND_COLD;
case Attribute::InlineHint:
return bitc::ATTR_KIND_INLINE_HINT;
case Attribute::InReg:
return bitc::ATTR_KIND_IN_REG;
+ case Attribute::JumpTable:
+ return bitc::ATTR_KIND_JUMP_TABLE;
case Attribute::MinSize:
return bitc::ATTR_KIND_MIN_SIZE;
case Attribute::Naked:
return bitc::ATTR_KIND_NO_INLINE;
case Attribute::NonLazyBind:
return bitc::ATTR_KIND_NON_LAZY_BIND;
+ case Attribute::NonNull:
+ return bitc::ATTR_KIND_NON_NULL;
+ case Attribute::Dereferenceable:
+ return bitc::ATTR_KIND_DEREFERENCEABLE;
case Attribute::NoRedZone:
return bitc::ATTR_KIND_NO_RED_ZONE;
case Attribute::NoReturn:
if (Attr.isEnumAttribute()) {
Record.push_back(0);
Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
- } else if (Attr.isAlignAttribute()) {
+ } else if (Attr.isIntAttribute()) {
Record.push_back(1);
Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
Record.push_back(Attr.getValueAsInt());
unsigned Code = 0;
switch (T->getTypeID()) {
- default: llvm_unreachable("Unknown type!");
case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
case Type::HalfTyID: Code = bitc::TYPE_CODE_HALF; break;
case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
Stream.ExitBlock();
}
-static unsigned getEncodedLinkage(const GlobalValue *GV) {
- switch (GV->getLinkage()) {
+static unsigned getEncodedLinkage(const GlobalValue &GV) {
+ switch (GV.getLinkage()) {
case GlobalValue::ExternalLinkage: return 0;
case GlobalValue::WeakAnyLinkage: return 1;
case GlobalValue::AppendingLinkage: return 2;
case GlobalValue::InternalLinkage: return 3;
case GlobalValue::LinkOnceAnyLinkage: return 4;
- case GlobalValue::DLLImportLinkage: return 5;
- case GlobalValue::DLLExportLinkage: return 6;
case GlobalValue::ExternalWeakLinkage: return 7;
case GlobalValue::CommonLinkage: return 8;
case GlobalValue::PrivateLinkage: return 9;
case GlobalValue::WeakODRLinkage: return 10;
case GlobalValue::LinkOnceODRLinkage: return 11;
case GlobalValue::AvailableExternallyLinkage: return 12;
- case GlobalValue::LinkerPrivateLinkage: return 13;
- case GlobalValue::LinkerPrivateWeakLinkage: return 14;
}
llvm_unreachable("Invalid linkage");
}
-static unsigned getEncodedVisibility(const GlobalValue *GV) {
- switch (GV->getVisibility()) {
+static unsigned getEncodedVisibility(const GlobalValue &GV) {
+ switch (GV.getVisibility()) {
case GlobalValue::DefaultVisibility: return 0;
case GlobalValue::HiddenVisibility: return 1;
case GlobalValue::ProtectedVisibility: return 2;
llvm_unreachable("Invalid visibility");
}
-static unsigned getEncodedThreadLocalMode(const GlobalVariable *GV) {
- switch (GV->getThreadLocalMode()) {
+static unsigned getEncodedDLLStorageClass(const GlobalValue &GV) {
+ switch (GV.getDLLStorageClass()) {
+ case GlobalValue::DefaultStorageClass: return 0;
+ case GlobalValue::DLLImportStorageClass: return 1;
+ case GlobalValue::DLLExportStorageClass: return 2;
+ }
+ llvm_unreachable("Invalid DLL storage class");
+}
+
+static unsigned getEncodedThreadLocalMode(const GlobalValue &GV) {
+ switch (GV.getThreadLocalMode()) {
case GlobalVariable::NotThreadLocal: return 0;
case GlobalVariable::GeneralDynamicTLSModel: return 1;
case GlobalVariable::LocalDynamicTLSModel: return 2;
llvm_unreachable("Invalid TLS model");
}
+static unsigned getEncodedComdatSelectionKind(const Comdat &C) {
+ switch (C.getSelectionKind()) {
+ case Comdat::Any:
+ return bitc::COMDAT_SELECTION_KIND_ANY;
+ case Comdat::ExactMatch:
+ return bitc::COMDAT_SELECTION_KIND_EXACT_MATCH;
+ case Comdat::Largest:
+ return bitc::COMDAT_SELECTION_KIND_LARGEST;
+ case Comdat::NoDuplicates:
+ return bitc::COMDAT_SELECTION_KIND_NO_DUPLICATES;
+ case Comdat::SameSize:
+ return bitc::COMDAT_SELECTION_KIND_SAME_SIZE;
+ }
+ llvm_unreachable("Invalid selection kind");
+}
+
+static void writeComdats(const ValueEnumerator &VE, BitstreamWriter &Stream) {
+ SmallVector<uint8_t, 64> Vals;
+ for (const Comdat *C : VE.getComdats()) {
+ // COMDAT: [selection_kind, name]
+ Vals.push_back(getEncodedComdatSelectionKind(*C));
+ Vals.push_back(C->getName().size());
+ for (char Chr : C->getName())
+ Vals.push_back((unsigned char)Chr);
+ Stream.EmitRecord(bitc::MODULE_CODE_COMDAT, Vals, /*AbbrevToUse=*/0);
+ Vals.clear();
+ }
+}
+
// Emit top-level description of module, including target triple, inline asm,
// descriptors for global variables, and function prototype info.
static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
if (!M->getTargetTriple().empty())
WriteStringRecord(bitc::MODULE_CODE_TRIPLE, M->getTargetTriple(),
0/*TODO*/, Stream);
- if (!M->getDataLayout().empty())
- WriteStringRecord(bitc::MODULE_CODE_DATALAYOUT, M->getDataLayout(),
- 0/*TODO*/, Stream);
+ const std::string &DL = M->getDataLayoutStr();
+ if (!DL.empty())
+ WriteStringRecord(bitc::MODULE_CODE_DATALAYOUT, DL, 0 /*TODO*/, Stream);
if (!M->getModuleInlineAsm().empty())
WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(),
0/*TODO*/, Stream);
std::map<std::string, unsigned> GCMap;
unsigned MaxAlignment = 0;
unsigned MaxGlobalType = 0;
- for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end();
- GV != E; ++GV) {
- MaxAlignment = std::max(MaxAlignment, GV->getAlignment());
- MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV->getType()));
- if (GV->hasSection()) {
+ for (const GlobalValue &GV : M->globals()) {
+ MaxAlignment = std::max(MaxAlignment, GV.getAlignment());
+ MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV.getType()));
+ if (GV.hasSection()) {
// Give section names unique ID's.
- unsigned &Entry = SectionMap[GV->getSection()];
+ unsigned &Entry = SectionMap[GV.getSection()];
if (!Entry) {
- WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV->getSection(),
+ WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV.getSection(),
0/*TODO*/, Stream);
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()) {
+ for (const Function &F : *M) {
+ MaxAlignment = std::max(MaxAlignment, F.getAlignment());
+ if (F.hasSection()) {
// Give section names unique ID's.
- unsigned &Entry = SectionMap[F->getSection()];
+ unsigned &Entry = SectionMap[F.getSection()];
if (!Entry) {
- WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F->getSection(),
+ WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F.getSection(),
0/*TODO*/, Stream);
Entry = SectionMap.size();
}
}
- if (F->hasGC()) {
+ if (F.hasGC()) {
// Same for GC names.
- unsigned &Entry = GCMap[F->getGC()];
+ unsigned &Entry = GCMap[F.getGC()];
if (!Entry) {
- WriteStringRecord(bitc::MODULE_CODE_GCNAME, F->getGC(),
+ WriteStringRecord(bitc::MODULE_CODE_GCNAME, F.getGC(),
0/*TODO*/, Stream);
Entry = GCMap.size();
}
// Emit the global variable information.
SmallVector<unsigned, 64> Vals;
- for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end();
- GV != E; ++GV) {
+ for (const GlobalVariable &GV : M->globals()) {
unsigned AbbrevToUse = 0;
// GLOBALVAR: [type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal,
- // unnamed_addr, externally_initialized]
- Vals.push_back(VE.getTypeID(GV->getType()));
- Vals.push_back(GV->isConstant());
- Vals.push_back(GV->isDeclaration() ? 0 :
- (VE.getValueID(GV->getInitializer()) + 1));
+ // unnamed_addr, externally_initialized, dllstorageclass]
+ Vals.push_back(VE.getTypeID(GV.getType()));
+ Vals.push_back(GV.isConstant());
+ Vals.push_back(GV.isDeclaration() ? 0 :
+ (VE.getValueID(GV.getInitializer()) + 1));
Vals.push_back(getEncodedLinkage(GV));
- Vals.push_back(Log2_32(GV->getAlignment())+1);
- Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0);
- if (GV->isThreadLocal() ||
- GV->getVisibility() != GlobalValue::DefaultVisibility ||
- GV->hasUnnamedAddr() || GV->isExternallyInitialized()) {
+ Vals.push_back(Log2_32(GV.getAlignment())+1);
+ Vals.push_back(GV.hasSection() ? SectionMap[GV.getSection()] : 0);
+ if (GV.isThreadLocal() ||
+ GV.getVisibility() != GlobalValue::DefaultVisibility ||
+ GV.hasUnnamedAddr() || GV.isExternallyInitialized() ||
+ GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||
+ GV.hasComdat()) {
Vals.push_back(getEncodedVisibility(GV));
Vals.push_back(getEncodedThreadLocalMode(GV));
- Vals.push_back(GV->hasUnnamedAddr());
- Vals.push_back(GV->isExternallyInitialized());
+ Vals.push_back(GV.hasUnnamedAddr());
+ Vals.push_back(GV.isExternallyInitialized());
+ Vals.push_back(getEncodedDLLStorageClass(GV));
+ Vals.push_back(GV.hasComdat() ? VE.getComdatID(GV.getComdat()) : 0);
} else {
AbbrevToUse = SimpleGVarAbbrev;
}
}
// Emit the function proto information.
- for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
+ for (const Function &F : *M) {
// FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
// section, visibility, gc, unnamed_addr, prefix]
- Vals.push_back(VE.getTypeID(F->getType()));
- Vals.push_back(F->getCallingConv());
- Vals.push_back(F->isDeclaration());
+ Vals.push_back(VE.getTypeID(F.getType()));
+ Vals.push_back(F.getCallingConv());
+ Vals.push_back(F.isDeclaration());
Vals.push_back(getEncodedLinkage(F));
- Vals.push_back(VE.getAttributeID(F->getAttributes()));
- Vals.push_back(Log2_32(F->getAlignment())+1);
- Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0);
+ Vals.push_back(VE.getAttributeID(F.getAttributes()));
+ Vals.push_back(Log2_32(F.getAlignment())+1);
+ Vals.push_back(F.hasSection() ? SectionMap[F.getSection()] : 0);
Vals.push_back(getEncodedVisibility(F));
- Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0);
- Vals.push_back(F->hasUnnamedAddr());
- Vals.push_back(F->hasPrefixData() ? (VE.getValueID(F->getPrefixData()) + 1)
+ Vals.push_back(F.hasGC() ? GCMap[F.getGC()] : 0);
+ Vals.push_back(F.hasUnnamedAddr());
+ Vals.push_back(F.hasPrefixData() ? (VE.getValueID(F.getPrefixData()) + 1)
: 0);
+ Vals.push_back(getEncodedDLLStorageClass(F));
+ Vals.push_back(F.hasComdat() ? VE.getComdatID(F.getComdat()) : 0);
unsigned AbbrevToUse = 0;
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
}
// Emit the alias information.
- for (Module::const_alias_iterator AI = M->alias_begin(), E = M->alias_end();
- AI != E; ++AI) {
+ for (const GlobalAlias &A : M->aliases()) {
// ALIAS: [alias type, aliasee val#, linkage, visibility]
- Vals.push_back(VE.getTypeID(AI->getType()));
- Vals.push_back(VE.getValueID(AI->getAliasee()));
- Vals.push_back(getEncodedLinkage(AI));
- Vals.push_back(getEncodedVisibility(AI));
+ Vals.push_back(VE.getTypeID(A.getType()));
+ Vals.push_back(VE.getValueID(A.getAliasee()));
+ Vals.push_back(getEncodedLinkage(A));
+ Vals.push_back(getEncodedVisibility(A));
+ Vals.push_back(getEncodedDLLStorageClass(A));
+ Vals.push_back(getEncodedThreadLocalMode(A));
+ Vals.push_back(A.hasUnnamedAddr());
unsigned AbbrevToUse = 0;
Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
Vals.clear();
SmallVector<uint64_t, 64> Record;
const ValueEnumerator::ValueList &Vals = VE.getValues();
- Type *LastTy = 0;
+ Type *LastTy = nullptr;
for (unsigned i = FirstVal; i != LastVal; ++i) {
const Value *V = Vals[i].first;
// If we need to switch types, do so now.
Code = bitc::CST_CODE_CE_EXTRACTELT;
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getValueID(C->getOperand(0)));
+ Record.push_back(VE.getTypeID(C->getOperand(1)->getType()));
Record.push_back(VE.getValueID(C->getOperand(1)));
break;
case Instruction::InsertElement:
Code = bitc::CST_CODE_CE_INSERTELT;
Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(1)));
+ Record.push_back(VE.getTypeID(C->getOperand(2)->getType()));
Record.push_back(VE.getValueID(C->getOperand(2)));
break;
case Instruction::ShuffleVector:
case Instruction::ExtractElement:
Code = bitc::FUNC_CODE_INST_EXTRACTELT;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
- pushValue(I.getOperand(1), InstID, Vals, VE);
+ PushValueAndType(I.getOperand(1), InstID, Vals, VE);
break;
case Instruction::InsertElement:
Code = bitc::FUNC_CODE_INST_INSERTELT;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
pushValue(I.getOperand(1), InstID, Vals, VE);
- pushValue(I.getOperand(2), InstID, Vals, VE);
+ PushValueAndType(I.getOperand(2), InstID, Vals, VE);
break;
case Instruction::ShuffleVector:
Code = bitc::FUNC_CODE_INST_SHUFFLEVEC;
break;
}
- case Instruction::Alloca:
+ case Instruction::Alloca: {
Code = bitc::FUNC_CODE_INST_ALLOCA;
Vals.push_back(VE.getTypeID(I.getType()));
Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
Vals.push_back(VE.getValueID(I.getOperand(0))); // size.
- Vals.push_back(Log2_32(cast<AllocaInst>(I).getAlignment())+1);
+ const AllocaInst &AI = cast<AllocaInst>(I);
+ unsigned AlignRecord = Log2_32(AI.getAlignment()) + 1;
+ assert(Log2_32(Value::MaximumAlignment) + 1 < 1 << 5 &&
+ "not enough bits for maximum alignment");
+ assert(AlignRecord < 1 << 5 && "alignment greater than 1 << 64");
+ AlignRecord |= AI.isUsedWithInAlloca() << 5;
+ Vals.push_back(AlignRecord);
break;
+ }
case Instruction::Load:
if (cast<LoadInst>(I).isAtomic()) {
pushValue(I.getOperand(2), InstID, Vals, VE); // newval.
Vals.push_back(cast<AtomicCmpXchgInst>(I).isVolatile());
Vals.push_back(GetEncodedOrdering(
- cast<AtomicCmpXchgInst>(I).getOrdering()));
+ cast<AtomicCmpXchgInst>(I).getSuccessOrdering()));
Vals.push_back(GetEncodedSynchScope(
cast<AtomicCmpXchgInst>(I).getSynchScope()));
+ Vals.push_back(GetEncodedOrdering(
+ cast<AtomicCmpXchgInst>(I).getFailureOrdering()));
+ Vals.push_back(cast<AtomicCmpXchgInst>(I).isWeak());
break;
case Instruction::AtomicRMW:
Code = bitc::FUNC_CODE_INST_ATOMICRMW;
Code = bitc::FUNC_CODE_INST_CALL;
Vals.push_back(VE.getAttributeID(CI.getAttributes()));
- Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall()));
+ Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall()) |
+ unsigned(CI.isMustTailCall()) << 14);
PushValueAndType(CI.getCalledValue(), InstID, Vals, VE); // Callee
// Emit value #'s for the fixed parameters.
Stream.ExitBlock();
}
+static void WriteUseList(ValueEnumerator &VE, UseListOrder &&Order,
+ BitstreamWriter &Stream) {
+ assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
+ unsigned Code;
+ if (isa<BasicBlock>(Order.V))
+ Code = bitc::USELIST_CODE_BB;
+ else
+ Code = bitc::USELIST_CODE_DEFAULT;
+
+ SmallVector<uint64_t, 64> Record;
+ for (unsigned I : Order.Shuffle)
+ Record.push_back(I);
+ Record.push_back(VE.getValueID(Order.V));
+ Stream.EmitRecord(Code, Record);
+}
+
+static void WriteUseListBlock(const Function *F, ValueEnumerator &VE,
+ BitstreamWriter &Stream) {
+ auto hasMore = [&]() {
+ return !VE.UseListOrders.empty() && VE.UseListOrders.back().F == F;
+ };
+ if (!hasMore())
+ // Nothing to do.
+ return;
+
+ Stream.EnterSubblock(bitc::USELIST_BLOCK_ID, 3);
+ while (hasMore()) {
+ WriteUseList(VE, std::move(VE.UseListOrders.back()), Stream);
+ VE.UseListOrders.pop_back();
+ }
+ Stream.ExitBlock();
+}
+
/// WriteFunction - Emit a function body to the module stream.
static void WriteFunction(const Function &F, ValueEnumerator &VE,
BitstreamWriter &Stream) {
if (NeedsMetadataAttachment)
WriteMetadataAttachment(F, VE, Stream);
+ if (shouldPreserveBitcodeUseListOrder())
+ WriteUseListBlock(&F, VE, Stream);
VE.purgeFunction();
Stream.ExitBlock();
}
Stream.ExitBlock();
}
-// Sort the Users based on the order in which the reader parses the bitcode
-// file.
-static bool bitcodereader_order(const User *lhs, const User *rhs) {
- // TODO: Implement.
- return true;
-}
-
-static void WriteUseList(const Value *V, const ValueEnumerator &VE,
- BitstreamWriter &Stream) {
-
- // One or zero uses can't get out of order.
- if (V->use_empty() || V->hasNUses(1))
- return;
-
- // Make a copy of the in-memory use-list for sorting.
- unsigned UseListSize = std::distance(V->use_begin(), V->use_end());
- SmallVector<const User*, 8> UseList;
- UseList.reserve(UseListSize);
- for (Value::const_use_iterator I = V->use_begin(), E = V->use_end();
- I != E; ++I) {
- const User *U = *I;
- UseList.push_back(U);
- }
-
- // Sort the copy based on the order read by the BitcodeReader.
- std::sort(UseList.begin(), UseList.end(), bitcodereader_order);
-
- // TODO: Generate a diff between the BitcodeWriter in-memory use-list and the
- // sorted list (i.e., the expected BitcodeReader in-memory use-list).
-
- // TODO: Emit the USELIST_CODE_ENTRYs.
-}
-
-static void WriteFunctionUseList(const Function *F, ValueEnumerator &VE,
- BitstreamWriter &Stream) {
- VE.incorporateFunction(*F);
-
- for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
- AI != AE; ++AI)
- WriteUseList(AI, VE, Stream);
- for (Function::const_iterator BB = F->begin(), FE = F->end(); BB != FE;
- ++BB) {
- WriteUseList(BB, VE, Stream);
- for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); II != IE;
- ++II) {
- WriteUseList(II, VE, Stream);
- for (User::const_op_iterator OI = II->op_begin(), E = II->op_end();
- OI != E; ++OI) {
- if ((isa<Constant>(*OI) && !isa<GlobalValue>(*OI)) ||
- isa<InlineAsm>(*OI))
- WriteUseList(*OI, VE, Stream);
- }
- }
- }
- VE.purgeFunction();
-}
-
-// Emit use-lists.
-static void WriteModuleUseLists(const Module *M, ValueEnumerator &VE,
- BitstreamWriter &Stream) {
- Stream.EnterSubblock(bitc::USELIST_BLOCK_ID, 3);
-
- // XXX: this modifies the module, but in a way that should never change the
- // behavior of any pass or codegen in LLVM. The problem is that GVs may
- // contain entries in the use_list that do not exist in the Module and are
- // not stored in the .bc file.
- for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
- I != E; ++I)
- I->removeDeadConstantUsers();
-
- // Write the global variables.
- for (Module::const_global_iterator GI = M->global_begin(),
- GE = M->global_end(); GI != GE; ++GI) {
- WriteUseList(GI, VE, Stream);
-
- // Write the global variable initializers.
- if (GI->hasInitializer())
- WriteUseList(GI->getInitializer(), VE, Stream);
- }
-
- // Write the functions.
- for (Module::const_iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) {
- WriteUseList(FI, VE, Stream);
- if (!FI->isDeclaration())
- WriteFunctionUseList(FI, VE, Stream);
- if (FI->hasPrefixData())
- WriteUseList(FI->getPrefixData(), VE, Stream);
- }
-
- // Write the aliases.
- for (Module::const_alias_iterator AI = M->alias_begin(), AE = M->alias_end();
- AI != AE; ++AI) {
- WriteUseList(AI, VE, Stream);
- WriteUseList(AI->getAliasee(), VE, Stream);
- }
-
- Stream.ExitBlock();
-}
-
/// WriteModule - Emit the specified module to the bitstream.
static void WriteModule(const Module *M, BitstreamWriter &Stream) {
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
// Emit information describing all of the types in the module.
WriteTypeTable(VE, Stream);
+ writeComdats(VE, Stream);
+
// Emit top-level description of module, including target triple, inline asm,
// descriptors for global variables, and function prototype info.
WriteModuleInfo(M, VE, Stream);
// Emit names for globals/functions etc.
WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream);
- // Emit use-lists.
- if (EnablePreserveUseListOrdering)
- WriteModuleUseLists(M, VE, Stream);
+ // Emit module-level use-lists.
+ if (shouldPreserveBitcodeUseListOrder())
+ WriteUseListBlock(nullptr, VE, Stream);
// Emit function bodies.
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F)