diff options
author | Logan Chien <loganchien@google.com> | 2011-12-16 09:08:45 +0800 |
---|---|---|
committer | Logan Chien <loganchien@google.com> | 2011-12-16 13:28:58 +0800 |
commit | a1e6e241a813f81be2d2f36ab60c950ca297574b (patch) | |
tree | cf2d7ec5c63f40e2b66d8be7737496719a0d7902 /lib/Bitcode/Writer/BitcodeWriter.cpp | |
parent | ac212abcc6d858470ad35ce7d660af0c1800364a (diff) | |
parent | ddecfe54a35ffbe0675f7f33e493734fd60b2495 (diff) | |
download | external_llvm-a1e6e241a813f81be2d2f36ab60c950ca297574b.zip external_llvm-a1e6e241a813f81be2d2f36ab60c950ca297574b.tar.gz external_llvm-a1e6e241a813f81be2d2f36ab60c950ca297574b.tar.bz2 |
Merge with LLVM upstream r146714 (Dec 16th 2011)
Change-Id: Ied458adb08bf9a69250cbcee9b14b44d17e8701a
Diffstat (limited to 'lib/Bitcode/Writer/BitcodeWriter.cpp')
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 133 |
1 files changed, 121 insertions, 12 deletions
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index e758f94..d980163 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -23,6 +23,7 @@ #include "llvm/Operator.h" #include "llvm/ValueSymbolTable.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -31,6 +32,12 @@ #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 { @@ -194,11 +201,12 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */); SmallVector<uint64_t, 64> TypeVals; + uint64_t NumBits = Log2_32_Ceil(VE.getTypes().size()+1); + // Abbrev for TYPE_CODE_POINTER. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_POINTER)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); Abbv->Add(BitCodeAbbrevOp(0)); // Addrspace = 0 unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv); @@ -207,8 +215,8 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_FUNCTION)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isvararg Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); + unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_STRUCT_ANON. @@ -216,8 +224,8 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { 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))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); + unsigned StructAnonAbbrev = Stream.EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_STRUCT_NAME. @@ -232,16 +240,16 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { 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))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); + unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_ARRAY. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // size - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); + unsigned ArrayAbbrev = Stream.EmitAbbrev(Abbv); // Emit an entry count so the reader can reserve space. @@ -497,8 +505,8 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, // Emit the function proto information. for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { - // FUNCTION: [type, callingconv, isproto, paramattr, - // linkage, alignment, section, visibility, gc, unnamed_addr] + // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment, + // section, visibility, gc, unnamed_addr] Vals.push_back(VE.getTypeID(F->getType())); Vals.push_back(F->getCallingConv()); Vals.push_back(F->isDeclaration()); @@ -518,6 +526,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, // Emit the alias information. for (Module::const_alias_iterator AI = M->alias_begin(), E = M->alias_end(); AI != E; ++AI) { + // 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)); @@ -1571,6 +1580,102 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { 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); + } + + // 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) { @@ -1616,6 +1721,10 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) { // Emit names for globals/functions etc. WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream); + // Emit use-lists. + if (EnablePreserveUseListOrdering) + WriteModuleUseLists(M, VE, Stream); + Stream.ExitBlock(); } |