Add support to the bytecode reader/writer for the new linkage types


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5790 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
index fb561aa..c8bf5af 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -301,14 +301,24 @@
     return true;  // Unexpected function!
   }
 
-  unsigned isInternal;
-  if (read_vbr(Buf, EndBuf, isInternal)) return true;
+  GlobalValue::LinkageTypes Linkage = GlobalValue::ExternalLinkage;
+
+  if (!hasInternalMarkerOnly) {
+    unsigned LinkageType;
+    if (read_vbr(Buf, EndBuf, LinkageType)) return true;
+    if (LinkageType & 0x3) return true;
+    Linkage = (GlobalValue::LinkageTypes)LinkageType;
+  } else {
+    // We used to only support two linkage models: internal and external
+    unsigned isInternal;
+    if (read_vbr(Buf, EndBuf, isInternal)) return true;
+    if (isInternal) Linkage = GlobalValue::InternalLinkage;
+  }
 
   Function *F = FunctionSignatureList.back().first;
   unsigned FunctionSlot = FunctionSignatureList.back().second;
   FunctionSignatureList.pop_back();
-  F->setLinkage(isInternal ? GlobalValue::InternalLinkage :
-                             GlobalValue::ExternalLinkage);
+  F->setLinkage(Linkage);
 
   const FunctionType::ParamTypes &Params =F->getFunctionType()->getParamTypes();
   Function::aiterator AI = F->abegin();
@@ -390,9 +400,23 @@
   unsigned VarType;
   if (read_vbr(Buf, End, VarType)) return true;
   while (VarType != Type::VoidTyID) { // List is terminated by Void
-    // VarType Fields: bit0 = isConstant, bit1 = hasInitializer,
-    // bit2 = isInternal, bit3+ = slot#
-    const Type *Ty = getType(VarType >> 3);
+    unsigned SlotNo;
+    GlobalValue::LinkageTypes Linkage;
+
+    if (!hasInternalMarkerOnly) {
+      // VarType Fields: bit0 = isConstant, bit1 = hasInitializer,
+      // bit2,3 = Linkage, bit4+ = slot#
+      SlotNo = VarType >> 4;
+      Linkage = (GlobalValue::LinkageTypes)((VarType >> 2) & 3);
+    } else {
+      // VarType Fields: bit0 = isConstant, bit1 = hasInitializer,
+      // bit2 = isInternal, bit3+ = slot#
+      SlotNo = VarType >> 3;
+      Linkage = (VarType & 4) ? GlobalValue::InternalLinkage :
+        GlobalValue::ExternalLinkage;
+    }
+
+    const Type *Ty = getType(SlotNo);
     if (!Ty || !isa<PointerType>(Ty)) { 
       Error = "Global not pointer type!  Ty = " + Ty->getDescription();
       return true; 
@@ -400,11 +424,6 @@
 
     const Type *ElTy = cast<PointerType>(Ty)->getElementType();
 
-
-    GlobalValue::LinkageTypes Linkage = 
-      (VarType & 4) ? GlobalValue::InternalLinkage :
-                      GlobalValue::ExternalLinkage;
-
     // Create the global variable...
     GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, Linkage,
                                             0, "", TheModule);
@@ -477,7 +496,11 @@
   isBigEndian     = Version & 1;
   hasLongPointers = Version & 2;
   RevisionNum     = Version >> 4;
+
+  // Default values for the current bytecode version
   HasImplicitZeroInitializer = true;
+  hasInternalMarkerOnly = false;
+  FirstDerivedTyID = 14;
 
   switch (RevisionNum) {
   case 0:                  // Initial revision
@@ -486,13 +509,17 @@
     // encoding zero initializers for arrays compactly.
     //
     if (Version != 14) return true;  // Unknown revision 0 flags?
-    FirstDerivedTyID = 14;
     HasImplicitZeroInitializer = false;
     isBigEndian = hasLongPointers = true;
+    hasInternalMarkerOnly = true;
     break;
   case 1:
     // Version #1 has two bit fields: isBigEndian and hasLongPointers
-    FirstDerivedTyID = 14;
+    hasInternalMarkerOnly = true;
+    break;
+  case 2:
+    // Version #2 added information about all 4 linkage types instead of just
+    // having internal and external.
     break;
   default:
     Error = "Unknown bytecode version number!";
diff --git a/lib/Bytecode/Reader/ReaderInternals.h b/lib/Bytecode/Reader/ReaderInternals.h
index 3e571f2..dd2a08f 100644
--- a/lib/Bytecode/Reader/ReaderInternals.h
+++ b/lib/Bytecode/Reader/ReaderInternals.h
@@ -85,6 +85,7 @@
   unsigned char FirstDerivedTyID;   // First variable index to use for type
   bool HasImplicitZeroInitializer;  // Is entry 0 of every slot implicity zeros?
   bool isBigEndian, hasLongPointers;// Information about the target compiled for
+  bool hasInternalMarkerOnly;       // Only types of linkage are intern/external
 
   typedef std::vector<ValueList*> ValueTable;
   ValueTable Values, LateResolveValues;
diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp
index 8f4f785..03a6c46 100644
--- a/lib/Bytecode/Writer/Writer.cpp
+++ b/lib/Bytecode/Writer/Writer.cpp
@@ -46,8 +46,8 @@
   bool isBigEndian = true;
   bool hasLongPointers = true;
 
-  // Output the version identifier... we are currently on bytecode version #1
-  unsigned Version = (1 << 4) | isBigEndian | (hasLongPointers << 1);
+  // Output the version identifier... we are currently on bytecode version #2
+  unsigned Version = (2 << 4) | isBigEndian | (hasLongPointers << 1);
   output_vbr(Version, Out);
   align32(Out);
 
@@ -154,9 +154,9 @@
     int Slot = Table.getValSlot(I->getType());
     assert(Slot != -1 && "Module global vars is broken!");
 
-    // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2=InternalLinkage,
-    // bit3+ = Slot # for type
-    unsigned oSlot = ((unsigned)Slot << 3) | (I->hasInternalLinkage() << 2) |
+    // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2,3=Linkage,
+    // bit4+ = Slot # for type
+    unsigned oSlot = ((unsigned)Slot << 4) | ((unsigned)I->getLinkage() << 2) |
                      (I->hasInitializer() << 1) | I->isConstant();
     output_vbr(oSlot, Out);
 
@@ -183,7 +183,7 @@
 
 void BytecodeWriter::outputFunction(const Function *F) {
   BytecodeBlock FunctionBlock(BytecodeFormat::Function, Out);
-  output_vbr((unsigned)F->hasInternalLinkage(), Out);
+  output_vbr((unsigned)F->getLinkage(), Out);
   // Only output the constant pool and other goodies if needed...
   if (!F->isExternal()) {