diff --git a/docs/BytecodeFormat.html b/docs/BytecodeFormat.html
index f479ca57b5f..1dc9c742bd9 100644
--- a/docs/BytecodeFormat.html
+++ b/docs/BytecodeFormat.html
@@ -1044,7 +1044,7 @@ and can includes more information:
bit(10-12) |
- Visibility style: 0=Default, 1=Hidden. |
+ Visibility style: 0=Default, 1=Hidden, 2=Protected. |
bit(13-31) |
@@ -1506,7 +1506,7 @@ other fields will be present as the function is defined elsewhere.
bit(16-18) |
- Visibility style: 0=Default, 1=Hidden. |
+ Visibility style: 0=Default, 1=Hidden, 2=Protected. |
bit(19-31) |
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 67a2fc8a4dd..58e0e3c5f39 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -591,6 +591,13 @@ All Global Variables and Functions have one of the following visibility styles:
directly.
+ "protected" - Protected style:
+
+ On ELF, protected visibility indicates that the symbol will be placed in
+ the dynamic symbol table, but that references within the defining module will
+ bind to the local symbol. That is, the symbol cannot be overridden by another
+ module.
+
diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h
index 014cdbe82af..4f6b1e6a9f9 100644
--- a/include/llvm/GlobalValue.h
+++ b/include/llvm/GlobalValue.h
@@ -43,7 +43,8 @@ public:
/// @brief An enumeration for the kinds of visibility of global values.
enum VisibilityTypes {
DefaultVisibility = 0, ///< The GV is visible
- HiddenVisibility ///< The GV is hidden
+ HiddenVisibility, ///< The GV is hidden
+ ProtectedVisibility ///< The GV is protected
};
protected:
@@ -58,7 +59,7 @@ protected:
// Note: VC++ treats enums as signed, so an extra bit is required to prevent
// Linkage and Visibility from turning into negative values.
LinkageTypes Linkage : 5; // The linkage of this global
- unsigned Visibility : 1; // The visibility style of this global
+ unsigned Visibility : 2; // The visibility style of this global
unsigned Alignment : 16; // Alignment of this symbol, must be power of two
std::string Section; // Section to emit this into, empty mean default
public:
@@ -74,6 +75,9 @@ public:
VisibilityTypes getVisibility() const { return (VisibilityTypes)Visibility; }
bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; }
+ bool hasProtectedVisibility() const {
+ return Visibility == ProtectedVisibility;
+ }
void setVisibility(VisibilityTypes V) { Visibility = V; }
bool hasSection() const { return !Section.empty(); }
diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h
index 60de43015dc..b13a3fb50f4 100644
--- a/include/llvm/Target/TargetAsmInfo.h
+++ b/include/llvm/Target/TargetAsmInfo.h
@@ -256,7 +256,11 @@ namespace llvm {
/// HiddenDirective - This directive, if non-null, is used to declare a
/// global or function as having hidden visibility.
const char *HiddenDirective; // Defaults to "\t.hidden\t".
-
+
+ /// ProtectedDirective - This directive, if non-null, is used to declare a
+ /// global or function as having protected visibility.
+ const char *ProtectedDirective; // Defaults to "\t.protected\t".
+
//===--- Dwarf Emission Directives -----------------------------------===//
/// AbsoluteSectionOffsets - True if we should emit abolute section
@@ -523,6 +527,9 @@ namespace llvm {
const char *getHiddenDirective() const {
return HiddenDirective;
}
+ const char *getProtectedDirective() const {
+ return ProtectedDirective;
+ }
bool isAbsoluteSectionOffsets() const {
return AbsoluteSectionOffsets;
}
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l
index 382ce24462a..b67f6ff1024 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -206,6 +206,7 @@ appending { return APPENDING; }
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 382ce24462a..b67f6ff1024 100644
--- a/lib/AsmParser/Lexer.l.cvs
+++ b/lib/AsmParser/Lexer.l.cvs
@@ -206,6 +206,7 @@ appending { return APPENDING; }
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 c47b6fc6ea9..63f2261fa11 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -1099,7 +1099,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%token NORETURN INREG SRET NOUNWIND
// Visibility Styles
-%token DEFAULT HIDDEN
+%token DEFAULT HIDDEN PROTECTED
%start Module
%%
@@ -1180,9 +1180,10 @@ GVExternalLinkage
;
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 c47b6fc6ea9..63f2261fa11 100644
--- a/lib/AsmParser/llvmAsmParser.y.cvs
+++ b/lib/AsmParser/llvmAsmParser.y.cvs
@@ -1099,7 +1099,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%token NORETURN INREG SRET NOUNWIND
// Visibility Styles
-%token DEFAULT HIDDEN
+%token DEFAULT HIDDEN PROTECTED
%start Module
%%
@@ -1180,9 +1180,10 @@ GVExternalLinkage
;
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 99aac056ff3..e75f0fcd610 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -1532,6 +1532,7 @@ void BytecodeReader::ParseFunctionBody(Function* F) {
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 @@ void BytecodeReader::ParseModuleGlobalInfo() {
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 f1c6f6c5619..b4a26916008 100644
--- a/lib/Bytecode/Writer/Writer.cpp
+++ b/lib/Bytecode/Writer/Writer.cpp
@@ -957,8 +957,9 @@ static unsigned getEncodedLinkage(const GlobalValue *GV) {
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 8deda9fe6a5..37ab073ffcd 100644
--- a/lib/Target/TargetAsmInfo.cpp
+++ b/lib/Target/TargetAsmInfo.cpp
@@ -74,6 +74,7 @@ TargetAsmInfo::TargetAsmInfo() :
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 03a22865e2c..634f41b9200 100755
--- a/lib/Target/X86/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/X86ATTAsmPrinter.cpp
@@ -125,9 +125,13 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
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 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
if (isCallOp && isa(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 76037f13bd5..7e7dc8861a7 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -155,9 +155,14 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
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 ac68e8d32fb..3a065b0cdfe 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -886,6 +886,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
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 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
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 @@ void AssemblyWriter::printFunction(const Function *F) {
default: assert(0 && "Invalid visibility style!");
case GlobalValue::DefaultVisibility: break;
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+ case GlobalValue::ProtectedVisibility: Out << "protected "; break;
}
}