Implement protected visibility. This partly implements PR1363. Linker
should be taught to deal with protected symbols. llvm-svn: 36565
This commit is contained in:
parent
546ea7ea88
commit
39f3cffbe3
|
@ -1044,7 +1044,7 @@ and can includes more information:</p>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="#bit">bit(10-12)</a></td>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="#bit">bit(13-31)</a></td>
|
<td><a href="#bit">bit(13-31)</a></td>
|
||||||
|
@ -1506,7 +1506,7 @@ other fields will be present as the function is defined elsewhere.</li>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="#bit">bit(16-18)</a></td>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="#bit">bit(19-31)</a></td>
|
<td><a href="#bit">bit(19-31)</a></td>
|
||||||
|
|
|
@ -591,6 +591,13 @@ All Global Variables and Functions have one of the following visibility styles:
|
||||||
directly.
|
directly.
|
||||||
</dd>
|
</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>
|
</dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -43,7 +43,8 @@ public:
|
||||||
/// @brief An enumeration for the kinds of visibility of global values.
|
/// @brief An enumeration for the kinds of visibility of global values.
|
||||||
enum VisibilityTypes {
|
enum VisibilityTypes {
|
||||||
DefaultVisibility = 0, ///< The GV is visible
|
DefaultVisibility = 0, ///< The GV is visible
|
||||||
HiddenVisibility ///< The GV is hidden
|
HiddenVisibility, ///< The GV is hidden
|
||||||
|
ProtectedVisibility ///< The GV is protected
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -58,7 +59,7 @@ protected:
|
||||||
// Note: VC++ treats enums as signed, so an extra bit is required to prevent
|
// Note: VC++ treats enums as signed, so an extra bit is required to prevent
|
||||||
// Linkage and Visibility from turning into negative values.
|
// Linkage and Visibility from turning into negative values.
|
||||||
LinkageTypes Linkage : 5; // The linkage of this global
|
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
|
unsigned Alignment : 16; // Alignment of this symbol, must be power of two
|
||||||
std::string Section; // Section to emit this into, empty mean default
|
std::string Section; // Section to emit this into, empty mean default
|
||||||
public:
|
public:
|
||||||
|
@ -74,6 +75,9 @@ public:
|
||||||
|
|
||||||
VisibilityTypes getVisibility() const { return (VisibilityTypes)Visibility; }
|
VisibilityTypes getVisibility() const { return (VisibilityTypes)Visibility; }
|
||||||
bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; }
|
bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; }
|
||||||
|
bool hasProtectedVisibility() const {
|
||||||
|
return Visibility == ProtectedVisibility;
|
||||||
|
}
|
||||||
void setVisibility(VisibilityTypes V) { Visibility = V; }
|
void setVisibility(VisibilityTypes V) { Visibility = V; }
|
||||||
|
|
||||||
bool hasSection() const { return !Section.empty(); }
|
bool hasSection() const { return !Section.empty(); }
|
||||||
|
|
|
@ -256,7 +256,11 @@ namespace llvm {
|
||||||
/// HiddenDirective - This directive, if non-null, is used to declare a
|
/// HiddenDirective - This directive, if non-null, is used to declare a
|
||||||
/// global or function as having hidden visibility.
|
/// global or function as having hidden visibility.
|
||||||
const char *HiddenDirective; // Defaults to "\t.hidden\t".
|
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 -----------------------------------===//
|
//===--- Dwarf Emission Directives -----------------------------------===//
|
||||||
|
|
||||||
/// AbsoluteSectionOffsets - True if we should emit abolute section
|
/// AbsoluteSectionOffsets - True if we should emit abolute section
|
||||||
|
@ -523,6 +527,9 @@ namespace llvm {
|
||||||
const char *getHiddenDirective() const {
|
const char *getHiddenDirective() const {
|
||||||
return HiddenDirective;
|
return HiddenDirective;
|
||||||
}
|
}
|
||||||
|
const char *getProtectedDirective() const {
|
||||||
|
return ProtectedDirective;
|
||||||
|
}
|
||||||
bool isAbsoluteSectionOffsets() const {
|
bool isAbsoluteSectionOffsets() const {
|
||||||
return AbsoluteSectionOffsets;
|
return AbsoluteSectionOffsets;
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,6 +206,7 @@ appending { return APPENDING; }
|
||||||
dllimport { return DLLIMPORT; }
|
dllimport { return DLLIMPORT; }
|
||||||
dllexport { return DLLEXPORT; }
|
dllexport { return DLLEXPORT; }
|
||||||
hidden { return HIDDEN; }
|
hidden { return HIDDEN; }
|
||||||
|
protected { return PROTECTED; }
|
||||||
extern_weak { return EXTERN_WEAK; }
|
extern_weak { return EXTERN_WEAK; }
|
||||||
external { return EXTERNAL; }
|
external { return EXTERNAL; }
|
||||||
thread_local { return THREAD_LOCAL; }
|
thread_local { return THREAD_LOCAL; }
|
||||||
|
|
|
@ -206,6 +206,7 @@ appending { return APPENDING; }
|
||||||
dllimport { return DLLIMPORT; }
|
dllimport { return DLLIMPORT; }
|
||||||
dllexport { return DLLEXPORT; }
|
dllexport { return DLLEXPORT; }
|
||||||
hidden { return HIDDEN; }
|
hidden { return HIDDEN; }
|
||||||
|
protected { return PROTECTED; }
|
||||||
extern_weak { return EXTERN_WEAK; }
|
extern_weak { return EXTERN_WEAK; }
|
||||||
external { return EXTERNAL; }
|
external { return EXTERNAL; }
|
||||||
thread_local { return THREAD_LOCAL; }
|
thread_local { return THREAD_LOCAL; }
|
||||||
|
|
|
@ -1099,7 +1099,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||||
%token NORETURN INREG SRET NOUNWIND
|
%token NORETURN INREG SRET NOUNWIND
|
||||||
|
|
||||||
// Visibility Styles
|
// Visibility Styles
|
||||||
%token DEFAULT HIDDEN
|
%token DEFAULT HIDDEN PROTECTED
|
||||||
|
|
||||||
%start Module
|
%start Module
|
||||||
%%
|
%%
|
||||||
|
@ -1180,9 +1180,10 @@ GVExternalLinkage
|
||||||
;
|
;
|
||||||
|
|
||||||
GVVisibilityStyle
|
GVVisibilityStyle
|
||||||
: /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
|
: /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
|
||||||
| DEFAULT { $$ = GlobalValue::DefaultVisibility; }
|
| DEFAULT { $$ = GlobalValue::DefaultVisibility; }
|
||||||
| HIDDEN { $$ = GlobalValue::HiddenVisibility; }
|
| HIDDEN { $$ = GlobalValue::HiddenVisibility; }
|
||||||
|
| PROTECTED { $$ = GlobalValue::ProtectedVisibility; }
|
||||||
;
|
;
|
||||||
|
|
||||||
FunctionDeclareLinkage
|
FunctionDeclareLinkage
|
||||||
|
|
|
@ -1099,7 +1099,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
|
||||||
%token NORETURN INREG SRET NOUNWIND
|
%token NORETURN INREG SRET NOUNWIND
|
||||||
|
|
||||||
// Visibility Styles
|
// Visibility Styles
|
||||||
%token DEFAULT HIDDEN
|
%token DEFAULT HIDDEN PROTECTED
|
||||||
|
|
||||||
%start Module
|
%start Module
|
||||||
%%
|
%%
|
||||||
|
@ -1180,9 +1180,10 @@ GVExternalLinkage
|
||||||
;
|
;
|
||||||
|
|
||||||
GVVisibilityStyle
|
GVVisibilityStyle
|
||||||
: /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
|
: /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
|
||||||
| DEFAULT { $$ = GlobalValue::DefaultVisibility; }
|
| DEFAULT { $$ = GlobalValue::DefaultVisibility; }
|
||||||
| HIDDEN { $$ = GlobalValue::HiddenVisibility; }
|
| HIDDEN { $$ = GlobalValue::HiddenVisibility; }
|
||||||
|
| PROTECTED { $$ = GlobalValue::ProtectedVisibility; }
|
||||||
;
|
;
|
||||||
|
|
||||||
FunctionDeclareLinkage
|
FunctionDeclareLinkage
|
||||||
|
|
|
@ -1532,6 +1532,7 @@ void BytecodeReader::ParseFunctionBody(Function* F) {
|
||||||
switch (VisibilityID) {
|
switch (VisibilityID) {
|
||||||
case 0: Visibility = GlobalValue::DefaultVisibility; break;
|
case 0: Visibility = GlobalValue::DefaultVisibility; break;
|
||||||
case 1: Visibility = GlobalValue::HiddenVisibility; break;
|
case 1: Visibility = GlobalValue::HiddenVisibility; break;
|
||||||
|
case 2: Visibility = GlobalValue::ProtectedVisibility; break;
|
||||||
default:
|
default:
|
||||||
error("Unknown visibility type: " + utostr(VisibilityID));
|
error("Unknown visibility type: " + utostr(VisibilityID));
|
||||||
Visibility = GlobalValue::DefaultVisibility;
|
Visibility = GlobalValue::DefaultVisibility;
|
||||||
|
@ -1767,6 +1768,7 @@ void BytecodeReader::ParseModuleGlobalInfo() {
|
||||||
switch (VisibilityID) {
|
switch (VisibilityID) {
|
||||||
case 0: Visibility = GlobalValue::DefaultVisibility; break;
|
case 0: Visibility = GlobalValue::DefaultVisibility; break;
|
||||||
case 1: Visibility = GlobalValue::HiddenVisibility; break;
|
case 1: Visibility = GlobalValue::HiddenVisibility; break;
|
||||||
|
case 2: Visibility = GlobalValue::ProtectedVisibility; break;
|
||||||
default:
|
default:
|
||||||
error("Unknown visibility type: " + utostr(VisibilityID));
|
error("Unknown visibility type: " + utostr(VisibilityID));
|
||||||
Visibility = GlobalValue::DefaultVisibility;
|
Visibility = GlobalValue::DefaultVisibility;
|
||||||
|
|
|
@ -957,8 +957,9 @@ static unsigned getEncodedLinkage(const GlobalValue *GV) {
|
||||||
static unsigned getEncodedVisibility(const GlobalValue *GV) {
|
static unsigned getEncodedVisibility(const GlobalValue *GV) {
|
||||||
switch (GV->getVisibility()) {
|
switch (GV->getVisibility()) {
|
||||||
default: assert(0 && "Invalid visibility!");
|
default: assert(0 && "Invalid visibility!");
|
||||||
case GlobalValue::DefaultVisibility: return 0;
|
case GlobalValue::DefaultVisibility: return 0;
|
||||||
case GlobalValue::HiddenVisibility: return 1;
|
case GlobalValue::HiddenVisibility: return 1;
|
||||||
|
case GlobalValue::ProtectedVisibility: return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ TargetAsmInfo::TargetAsmInfo() :
|
||||||
UsedDirective(0),
|
UsedDirective(0),
|
||||||
WeakRefDirective(0),
|
WeakRefDirective(0),
|
||||||
HiddenDirective("\t.hidden\t"),
|
HiddenDirective("\t.hidden\t"),
|
||||||
|
ProtectedDirective("\t.protected\t"),
|
||||||
AbsoluteSectionOffsets(false),
|
AbsoluteSectionOffsets(false),
|
||||||
HasLEB128(false),
|
HasLEB128(false),
|
||||||
HasDotLoc(false),
|
HasDotLoc(false),
|
||||||
|
|
|
@ -125,9 +125,13 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (F->hasHiddenVisibility())
|
if (F->hasHiddenVisibility()) {
|
||||||
if (const char *Directive = TAI->getHiddenDirective())
|
if (const char *Directive = TAI->getHiddenDirective())
|
||||||
O << Directive << CurrentFnName << "\n";
|
O << Directive << CurrentFnName << "\n";
|
||||||
|
} else if (F->hasProtectedVisibility()) {
|
||||||
|
if (const char *Directive = TAI->getProtectedDirective())
|
||||||
|
O << Directive << CurrentFnName << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (Subtarget->isTargetELF())
|
if (Subtarget->isTargetELF())
|
||||||
O << "\t.type " << CurrentFnName << ",@function\n";
|
O << "\t.type " << CurrentFnName << ",@function\n";
|
||||||
|
@ -322,7 +326,8 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
if (isCallOp && isa<Function>(GV)) {
|
if (isCallOp && isa<Function>(GV)) {
|
||||||
if (printGOT(TM, Subtarget)) {
|
if (printGOT(TM, Subtarget)) {
|
||||||
// Assemble call via PLT for non-local symbols
|
// Assemble call via PLT for non-local symbols
|
||||||
if (!GV->hasHiddenVisibility() || GV->isDeclaration())
|
if (!(GV->hasHiddenVisibility() || GV->hasProtectedVisibility()) ||
|
||||||
|
GV->isDeclaration())
|
||||||
O << "@PLT";
|
O << "@PLT";
|
||||||
}
|
}
|
||||||
if (Subtarget->isTargetCygMing() && GV->isDeclaration())
|
if (Subtarget->isTargetCygMing() && GV->isDeclaration())
|
||||||
|
|
|
@ -155,9 +155,14 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
|
||||||
unsigned Size = TD->getTypeSize(Type);
|
unsigned Size = TD->getTypeSize(Type);
|
||||||
unsigned Align = TD->getPreferredAlignmentLog(I);
|
unsigned Align = TD->getPreferredAlignmentLog(I);
|
||||||
|
|
||||||
if (I->hasHiddenVisibility())
|
if (I->hasHiddenVisibility()) {
|
||||||
if (const char *Directive = TAI->getHiddenDirective())
|
if (const char *Directive = TAI->getHiddenDirective())
|
||||||
O << Directive << name << "\n";
|
O << Directive << name << "\n";
|
||||||
|
} else if (I->hasProtectedVisibility()) {
|
||||||
|
if (const char *Directive = TAI->getProtectedDirective())
|
||||||
|
O << Directive << name << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (Subtarget->isTargetELF())
|
if (Subtarget->isTargetELF())
|
||||||
O << "\t.type " << name << ",@object\n";
|
O << "\t.type " << name << ",@object\n";
|
||||||
|
|
||||||
|
|
|
@ -886,6 +886,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
|
||||||
default: assert(0 && "Invalid visibility style!");
|
default: assert(0 && "Invalid visibility style!");
|
||||||
case GlobalValue::DefaultVisibility: break;
|
case GlobalValue::DefaultVisibility: break;
|
||||||
case GlobalValue::HiddenVisibility: Out << "hidden "; 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!");
|
default: assert(0 && "Invalid visibility style!");
|
||||||
case GlobalValue::DefaultVisibility: break;
|
case GlobalValue::DefaultVisibility: break;
|
||||||
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
|
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
|
||||||
|
case GlobalValue::ProtectedVisibility: Out << "protected "; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Out << "alias ";
|
Out << "alias ";
|
||||||
|
@ -998,6 +1000,7 @@ void AssemblyWriter::printFunction(const Function *F) {
|
||||||
default: assert(0 && "Invalid visibility style!");
|
default: assert(0 && "Invalid visibility style!");
|
||||||
case GlobalValue::DefaultVisibility: break;
|
case GlobalValue::DefaultVisibility: break;
|
||||||
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
|
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
|
||||||
|
case GlobalValue::ProtectedVisibility: Out << "protected "; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue