</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>
</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>
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>
/// @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:
// 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:
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(); }
/// 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
const char *getHiddenDirective() const {
return HiddenDirective;
}
+ const char *getProtectedDirective() const {
+ return ProtectedDirective;
+ }
bool isAbsoluteSectionOffsets() const {
return AbsoluteSectionOffsets;
}
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; }
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; }
%token NORETURN INREG SRET NOUNWIND
// Visibility Styles
-%token DEFAULT HIDDEN
+%token DEFAULT HIDDEN PROTECTED
%start Module
%%
;
GVVisibilityStyle
- : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
- | DEFAULT { $$ = GlobalValue::DefaultVisibility; }
- | HIDDEN { $$ = GlobalValue::HiddenVisibility; }
+ : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
+ | DEFAULT { $$ = GlobalValue::DefaultVisibility; }
+ | HIDDEN { $$ = GlobalValue::HiddenVisibility; }
+ | PROTECTED { $$ = GlobalValue::ProtectedVisibility; }
;
FunctionDeclareLinkage
%token NORETURN INREG SRET NOUNWIND
// Visibility Styles
-%token DEFAULT HIDDEN
+%token DEFAULT HIDDEN PROTECTED
%start Module
%%
;
GVVisibilityStyle
- : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
- | DEFAULT { $$ = GlobalValue::DefaultVisibility; }
- | HIDDEN { $$ = GlobalValue::HiddenVisibility; }
+ : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
+ | DEFAULT { $$ = GlobalValue::DefaultVisibility; }
+ | HIDDEN { $$ = GlobalValue::HiddenVisibility; }
+ | PROTECTED { $$ = GlobalValue::ProtectedVisibility; }
;
FunctionDeclareLinkage
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;
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;
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;
}
}
UsedDirective(0),
WeakRefDirective(0),
HiddenDirective("\t.hidden\t"),
+ ProtectedDirective("\t.protected\t"),
AbsoluteSectionOffsets(false),
HasLEB128(false),
HasDotLoc(false),
}
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";
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())
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";
default: assert(0 && "Invalid visibility style!");
case GlobalValue::DefaultVisibility: break;
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+ case GlobalValue::ProtectedVisibility: Out << "protected "; break;
}
}
default: assert(0 && "Invalid visibility style!");
case GlobalValue::DefaultVisibility: break;
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+ case GlobalValue::ProtectedVisibility: Out << "protected "; break;
}
Out << "alias ";
default: assert(0 && "Invalid visibility style!");
case GlobalValue::DefaultVisibility: break;
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+ case GlobalValue::ProtectedVisibility: Out << "protected "; break;
}
}