Implement protected visibility. This partly implements PR1363. Linker
should be taught to deal with protected symbols.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36565 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l
index 382ce24..b67f6ff 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -206,6 +206,7 @@
 dllimport       { return DLLIMPORT; }
 dllexport       { return DLLEXPORT; }
 hidden          { return HIDDEN; }
+protected       { return PROTECTED; }
 extern_weak     { return EXTERN_WEAK; }
 external        { return EXTERNAL; }
 thread_local    { return THREAD_LOCAL; }
diff --git a/lib/AsmParser/Lexer.l.cvs b/lib/AsmParser/Lexer.l.cvs
index 382ce24..b67f6ff 100644
--- a/lib/AsmParser/Lexer.l.cvs
+++ b/lib/AsmParser/Lexer.l.cvs
@@ -206,6 +206,7 @@
 dllimport       { return DLLIMPORT; }
 dllexport       { return DLLEXPORT; }
 hidden          { return HIDDEN; }
+protected       { return PROTECTED; }
 extern_weak     { return EXTERN_WEAK; }
 external        { return EXTERNAL; }
 thread_local    { return THREAD_LOCAL; }
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index c47b6fc..63f2261 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -1099,7 +1099,7 @@
 %token NORETURN INREG SRET NOUNWIND
 
 // Visibility Styles
-%token DEFAULT HIDDEN
+%token DEFAULT HIDDEN PROTECTED
 
 %start Module
 %%
@@ -1180,9 +1180,10 @@
   ;
 
 GVVisibilityStyle
-  : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
-  | DEFAULT   { $$ = GlobalValue::DefaultVisibility; }
-  | HIDDEN    { $$ = GlobalValue::HiddenVisibility;  }
+  : /*empty*/ { $$ = GlobalValue::DefaultVisibility;   }
+  | DEFAULT   { $$ = GlobalValue::DefaultVisibility;   }
+  | HIDDEN    { $$ = GlobalValue::HiddenVisibility;    }
+  | PROTECTED { $$ = GlobalValue::ProtectedVisibility; }
   ;
 
 FunctionDeclareLinkage
diff --git a/lib/AsmParser/llvmAsmParser.y.cvs b/lib/AsmParser/llvmAsmParser.y.cvs
index c47b6fc..63f2261 100644
--- a/lib/AsmParser/llvmAsmParser.y.cvs
+++ b/lib/AsmParser/llvmAsmParser.y.cvs
@@ -1099,7 +1099,7 @@
 %token NORETURN INREG SRET NOUNWIND
 
 // Visibility Styles
-%token DEFAULT HIDDEN
+%token DEFAULT HIDDEN PROTECTED
 
 %start Module
 %%
@@ -1180,9 +1180,10 @@
   ;
 
 GVVisibilityStyle
-  : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
-  | DEFAULT   { $$ = GlobalValue::DefaultVisibility; }
-  | HIDDEN    { $$ = GlobalValue::HiddenVisibility;  }
+  : /*empty*/ { $$ = GlobalValue::DefaultVisibility;   }
+  | DEFAULT   { $$ = GlobalValue::DefaultVisibility;   }
+  | HIDDEN    { $$ = GlobalValue::HiddenVisibility;    }
+  | PROTECTED { $$ = GlobalValue::ProtectedVisibility; }
   ;
 
 FunctionDeclareLinkage
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
index 99aac05..e75f0fc 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -1532,6 +1532,7 @@
   switch (VisibilityID) {
   case 0: Visibility = GlobalValue::DefaultVisibility; break;
   case 1: Visibility = GlobalValue::HiddenVisibility; break;
+  case 2: Visibility = GlobalValue::ProtectedVisibility; break;
   default:
    error("Unknown visibility type: " + utostr(VisibilityID));
    Visibility = GlobalValue::DefaultVisibility;
@@ -1767,6 +1768,7 @@
     switch (VisibilityID) {
     case 0: Visibility = GlobalValue::DefaultVisibility; break;
     case 1: Visibility = GlobalValue::HiddenVisibility; break;
+    case 2: Visibility = GlobalValue::ProtectedVisibility; break;
     default:
       error("Unknown visibility type: " + utostr(VisibilityID));
       Visibility = GlobalValue::DefaultVisibility;
diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp
index f1c6f6c..b4a2691 100644
--- a/lib/Bytecode/Writer/Writer.cpp
+++ b/lib/Bytecode/Writer/Writer.cpp
@@ -957,8 +957,9 @@
 static unsigned getEncodedVisibility(const GlobalValue *GV) {
   switch (GV->getVisibility()) {
   default: assert(0 && "Invalid visibility!");
-  case GlobalValue::DefaultVisibility: return 0;
-  case GlobalValue::HiddenVisibility:  return 1;
+  case GlobalValue::DefaultVisibility:   return 0;
+  case GlobalValue::HiddenVisibility:    return 1;
+  case GlobalValue::ProtectedVisibility: return 2;
   }
 }
 
diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp
index 8deda9f..37ab073 100644
--- a/lib/Target/TargetAsmInfo.cpp
+++ b/lib/Target/TargetAsmInfo.cpp
@@ -74,6 +74,7 @@
   UsedDirective(0),
   WeakRefDirective(0),
   HiddenDirective("\t.hidden\t"),
+  ProtectedDirective("\t.protected\t"),
   AbsoluteSectionOffsets(false),
   HasLEB128(false),
   HasDotLoc(false),
diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp
index 03a2286..634f41b 100755
--- a/lib/Target/X86/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/X86ATTAsmPrinter.cpp
@@ -125,9 +125,13 @@
     }
     break;
   }
-  if (F->hasHiddenVisibility())
+  if (F->hasHiddenVisibility()) {
     if (const char *Directive = TAI->getHiddenDirective())
       O << Directive << CurrentFnName << "\n";
+  } else if (F->hasProtectedVisibility()) {
+    if (const char *Directive = TAI->getProtectedDirective())
+      O << Directive << CurrentFnName << "\n";
+  }
 
   if (Subtarget->isTargetELF())
     O << "\t.type " << CurrentFnName << ",@function\n";
@@ -322,7 +326,8 @@
       if (isCallOp && isa<Function>(GV)) {
         if (printGOT(TM, Subtarget)) {
           // Assemble call via PLT for non-local symbols
-          if (!GV->hasHiddenVisibility() || GV->isDeclaration())
+          if (!(GV->hasHiddenVisibility() || GV->hasProtectedVisibility()) ||
+              GV->isDeclaration())
             O << "@PLT";
         }
         if (Subtarget->isTargetCygMing() && GV->isDeclaration())
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 76037f1..7e7dc88 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -155,9 +155,14 @@
     unsigned Size = TD->getTypeSize(Type);
     unsigned Align = TD->getPreferredAlignmentLog(I);
 
-    if (I->hasHiddenVisibility())
+    if (I->hasHiddenVisibility()) {
       if (const char *Directive = TAI->getHiddenDirective())
         O << Directive << name << "\n";
+    } else if (I->hasProtectedVisibility()) {
+      if (const char *Directive = TAI->getProtectedDirective())
+        O << Directive << name << "\n";
+    }
+    
     if (Subtarget->isTargetELF())
       O << "\t.type " << name << ",@object\n";
     
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index ac68e8d..3a065b0 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -886,6 +886,7 @@
     default: assert(0 && "Invalid visibility style!");
     case GlobalValue::DefaultVisibility: break;
     case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+    case GlobalValue::ProtectedVisibility: Out << "protected "; break;
     }
   }
 
@@ -914,6 +915,7 @@
   default: assert(0 && "Invalid visibility style!");
   case GlobalValue::DefaultVisibility: break;
   case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+  case GlobalValue::ProtectedVisibility: Out << "protected "; break;
   }
 
   Out << "alias ";
@@ -998,6 +1000,7 @@
     default: assert(0 && "Invalid visibility style!");
     case GlobalValue::DefaultVisibility: break;
     case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+    case GlobalValue::ProtectedVisibility: Out << "protected "; break;
     }
   }