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/docs/BytecodeFormat.html b/docs/BytecodeFormat.html
index f479ca5..1dc9c74 100644
--- a/docs/BytecodeFormat.html
+++ b/docs/BytecodeFormat.html
@@ -1044,7 +1044,7 @@
</tr>
<tr>
<td><a href="#bit">bit(10-12)</a></td>
- <td class="td_left">Visibility style: 0=Default, 1=Hidden.</td>
+ <td class="td_left">Visibility style: 0=Default, 1=Hidden, 2=Protected.</td>
</tr>
<tr>
<td><a href="#bit">bit(13-31)</a></td>
@@ -1506,7 +1506,7 @@
</tr>
<tr>
<td><a href="#bit">bit(16-18)</a></td>
- <td class="td_left">Visibility style: 0=Default, 1=Hidden.</td>
+ <td class="td_left">Visibility style: 0=Default, 1=Hidden, 2=Protected.</td>
</tr>
<tr>
<td><a href="#bit">bit(19-31)</a></td>
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 67a2fc8..58e0e3c 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -591,6 +591,13 @@
directly.
</dd>
+ <dt><b>"<tt>protected</tt>" - Protected style</b>:</dt>
+
+ <dd>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.
+ </dd>
</dl>
</div>
diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h
index 014cdbe..4f6b1e6 100644
--- a/include/llvm/GlobalValue.h
+++ b/include/llvm/GlobalValue.h
@@ -43,7 +43,8 @@
/// @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 @@
// 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 @@
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 60de430..b13a3fb 100644
--- a/include/llvm/Target/TargetAsmInfo.h
+++ b/include/llvm/Target/TargetAsmInfo.h
@@ -256,7 +256,11 @@
/// 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 @@
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 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;
}
}