mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 21:00:29 +00:00
Add a new "available_externally" linkage type. This is intended
to support C99 inline, GNU extern inline, etc. Related bugzilla's include PR3517, PR3100, & PR2933. Nothing uses this yet, but it appears to work. llvm-svn: 68940
This commit is contained in:
parent
57077413f1
commit
c1bfdc9bb2
@ -509,6 +509,17 @@ All Global Variables and Functions have one of the following types of linkage:
|
||||
'<tt>static</tt>' keyword in C.
|
||||
</dd>
|
||||
|
||||
<dt><tt><b><a name="available_externally">available_externally</a></b></tt>:
|
||||
</dt>
|
||||
|
||||
<dd>Globals with "<tt>available_externally</tt>" linkage are never emitted
|
||||
into the object file corresponding to the LLVM module. They exist to
|
||||
allow inlining and other optimizations to take place given knowledge of the
|
||||
definition of the global, which is known to be somewhere outside the module.
|
||||
Globals with <tt>available_externally</tt> linkage are allowed to be discarded
|
||||
at will, and are otherwise the same as <tt>linkonce_odr</tt>. This linkage
|
||||
type is only allowed on definitions, not declarations.</dd>
|
||||
|
||||
<dt><tt><b><a name="linkage_linkonce">linkonce</a></b></tt>: </dt>
|
||||
|
||||
<dd>Globals with "<tt>linkonce</tt>" linkage are merged with other globals of
|
||||
@ -554,10 +565,10 @@ All Global Variables and Functions have one of the following types of linkage:
|
||||
|
||||
<dt><tt><b><a name="linkage_linkonce">linkonce_odr</a></b></tt>: </dt>
|
||||
<dt><tt><b><a name="linkage_weak">weak_odr</a></b></tt>: </dt>
|
||||
<dd>Some languages allow inequivalent globals to be merged, such as two
|
||||
<dd>Some languages allow differing globals to be merged, such as two
|
||||
functions with different semantics. Other languages, such as <tt>C++</tt>,
|
||||
ensure that only equivalent globals are ever merged (the "one definition
|
||||
rule" - <tt>odr</tt>). Such languages can use the <tt>linkonce_odr</tt>
|
||||
rule" - "ODR"). Such languages can use the <tt>linkonce_odr</tt>
|
||||
and <tt>weak_odr</tt> linkage types to indicate that the global will only
|
||||
be merged with equivalent globals. These linkage types are otherwise the
|
||||
same as their non-<tt>odr</tt> versions.
|
||||
|
@ -24,8 +24,9 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// FIXME: This pass should declare that the pass does not invalidate any LLVM
|
||||
// passes.
|
||||
struct MachineFunctionPass : public FunctionPass {
|
||||
|
||||
explicit MachineFunctionPass(intptr_t ID) : FunctionPass(ID) {}
|
||||
explicit MachineFunctionPass(void *ID) : FunctionPass(ID) {}
|
||||
|
||||
@ -36,14 +37,7 @@ protected:
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF) = 0;
|
||||
|
||||
public:
|
||||
// FIXME: This pass should declare that the pass does not invalidate any LLVM
|
||||
// passes.
|
||||
bool runOnFunction(Function &F) {
|
||||
return runOnMachineFunction(MachineFunction::get(&F));
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void virtfn(); // out of line virtual fn to give class a home.
|
||||
bool runOnFunction(Function &F);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
/// @brief An enumeration for the kinds of linkage for global values.
|
||||
enum LinkageTypes {
|
||||
ExternalLinkage = 0,///< Externally visible function
|
||||
AvailableExternallyLinkage, ///< Available for inspection, not emission.
|
||||
LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline)
|
||||
LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent.
|
||||
WeakAnyLinkage, ///< Keep one copy of named function when linking (weak)
|
||||
@ -109,6 +110,9 @@ public:
|
||||
}
|
||||
|
||||
bool hasExternalLinkage() const { return Linkage == ExternalLinkage; }
|
||||
bool hasAvailableExternallyLinkage() const {
|
||||
return Linkage == AvailableExternallyLinkage;
|
||||
}
|
||||
bool hasLinkOnceLinkage() const {
|
||||
return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage;
|
||||
}
|
||||
@ -119,7 +123,8 @@ public:
|
||||
bool hasInternalLinkage() const { return Linkage == InternalLinkage; }
|
||||
bool hasPrivateLinkage() const { return Linkage == PrivateLinkage; }
|
||||
bool hasLocalLinkage() const {
|
||||
return Linkage == InternalLinkage || Linkage == PrivateLinkage;
|
||||
return Linkage == InternalLinkage || Linkage == PrivateLinkage ||
|
||||
Linkage == AvailableExternallyLinkage;
|
||||
}
|
||||
bool hasDLLImportLinkage() const { return Linkage == DLLImportLinkage; }
|
||||
bool hasDLLExportLinkage() const { return Linkage == DLLExportLinkage; }
|
||||
@ -141,9 +146,10 @@ public:
|
||||
}
|
||||
|
||||
/// isWeakForLinker - Whether the definition of this global may be replaced at
|
||||
/// link time, whether the replacement is equivalent to the original or not.
|
||||
/// link time.
|
||||
bool isWeakForLinker() const {
|
||||
return (Linkage == WeakAnyLinkage ||
|
||||
return (Linkage == AvailableExternallyLinkage ||
|
||||
Linkage == WeakAnyLinkage ||
|
||||
Linkage == WeakODRLinkage ||
|
||||
Linkage == LinkOnceAnyLinkage ||
|
||||
Linkage == LinkOnceODRLinkage ||
|
||||
|
@ -487,6 +487,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
|
||||
KEYWORD(private);
|
||||
KEYWORD(internal);
|
||||
KEYWORD(available_externally);
|
||||
KEYWORD(linkonce);
|
||||
KEYWORD(linkonce_odr);
|
||||
KEYWORD(weak);
|
||||
|
@ -764,6 +764,9 @@ bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) {
|
||||
case lltok::kw_weak_odr: Res = GlobalValue::WeakODRLinkage; break;
|
||||
case lltok::kw_linkonce: Res = GlobalValue::LinkOnceAnyLinkage; break;
|
||||
case lltok::kw_linkonce_odr: Res = GlobalValue::LinkOnceODRLinkage; break;
|
||||
case lltok::kw_available_externally:
|
||||
Res = GlobalValue::AvailableExternallyLinkage;
|
||||
break;
|
||||
case lltok::kw_appending: Res = GlobalValue::AppendingLinkage; break;
|
||||
case lltok::kw_dllexport: Res = GlobalValue::DLLExportLinkage; break;
|
||||
case lltok::kw_common: Res = GlobalValue::CommonLinkage; break;
|
||||
|
@ -37,7 +37,7 @@ namespace lltok {
|
||||
kw_global, kw_constant,
|
||||
|
||||
kw_private, kw_internal, kw_linkonce, kw_linkonce_odr, kw_weak, kw_weak_odr,
|
||||
kw_appending, kw_dllimport, kw_dllexport, kw_common,
|
||||
kw_appending, kw_dllimport, kw_dllexport, kw_common,kw_available_externally,
|
||||
kw_default, kw_hidden, kw_protected,
|
||||
kw_extern_weak,
|
||||
kw_external, kw_thread_local,
|
||||
|
@ -70,6 +70,7 @@ static GlobalValue::LinkageTypes GetDecodedLinkage(unsigned Val) {
|
||||
case 9: return GlobalValue::PrivateLinkage;
|
||||
case 10: return GlobalValue::WeakODRLinkage;
|
||||
case 11: return GlobalValue::LinkOnceODRLinkage;
|
||||
case 12: return GlobalValue::AvailableExternallyLinkage;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,6 +287,7 @@ static unsigned getEncodedLinkage(const GlobalValue *GV) {
|
||||
case GlobalValue::PrivateLinkage: return 9;
|
||||
case GlobalValue::WeakODRLinkage: return 10;
|
||||
case GlobalValue::LinkOnceODRLinkage: return 11;
|
||||
case GlobalValue::AvailableExternallyLinkage: return 12;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,7 +443,9 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
|
||||
}
|
||||
|
||||
// Ignore debug and non-emitted data.
|
||||
if (GV->getSection() == "llvm.metadata") return true;
|
||||
if (GV->getSection() == "llvm.metadata" ||
|
||||
GV->hasAvailableExternallyLinkage())
|
||||
return true;
|
||||
|
||||
if (!GV->hasAppendingLinkage()) return false;
|
||||
|
||||
|
@ -3519,6 +3519,9 @@ class DwarfException : public Dwarf {
|
||||
///
|
||||
void EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) {
|
||||
Function::LinkageTypes linkage = EHFrameInfo.function->getLinkage();
|
||||
|
||||
assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() &&
|
||||
"Should not emit 'available externally' functions at all");
|
||||
|
||||
Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection());
|
||||
|
||||
|
@ -38,8 +38,14 @@ using namespace llvm;
|
||||
static AnnotationID MF_AID(
|
||||
AnnotationManager::getID("CodeGen::MachineCodeForFunction"));
|
||||
|
||||
// Out of line virtual function to home classes.
|
||||
void MachineFunctionPass::virtfn() {}
|
||||
bool MachineFunctionPass::runOnFunction(Function &F) {
|
||||
// Do not codegen any 'available_externally' functions at all, they have
|
||||
// definitions outside the translation unit.
|
||||
if (F.hasAvailableExternallyLinkage())
|
||||
return false;
|
||||
|
||||
return runOnMachineFunction(MachineFunction::get(&F));
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct VISIBILITY_HIDDEN Printer : public MachineFunctionPass {
|
||||
|
@ -480,9 +480,10 @@ static bool GetLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
|
||||
} else if (Src->isWeakForLinker()) {
|
||||
// At this point we know that Dest has LinkOnce, External*, Weak, Common,
|
||||
// or DLL* linkage.
|
||||
if ((Dest->hasLinkOnceLinkage() &&
|
||||
(Src->hasWeakLinkage() || Src->hasCommonLinkage())) ||
|
||||
Dest->hasExternalWeakLinkage()) {
|
||||
if (Dest->hasExternalWeakLinkage() ||
|
||||
Dest->hasAvailableExternallyLinkage() ||
|
||||
(Dest->hasLinkOnceLinkage() &&
|
||||
(Src->hasWeakLinkage() || Src->hasCommonLinkage()))) {
|
||||
LinkFromSrc = true;
|
||||
LT = Src->getLinkage();
|
||||
} else {
|
||||
|
@ -294,6 +294,8 @@ namespace {
|
||||
Out << "GlobalValue::InternalLinkage"; break;
|
||||
case GlobalValue::PrivateLinkage:
|
||||
Out << "GlobalValue::PrivateLinkage"; break;
|
||||
case GlobalValue::AvailableExternallyLinkage:
|
||||
Out << "GlobalValue::AvailableExternallyLinkage "; break;
|
||||
case GlobalValue::LinkOnceAnyLinkage:
|
||||
Out << "GlobalValue::LinkOnceAnyLinkage "; break;
|
||||
case GlobalValue::LinkOnceODRLinkage:
|
||||
|
@ -1225,6 +1225,9 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT, raw_ostream &Out) {
|
||||
switch (LT) {
|
||||
case GlobalValue::PrivateLinkage: Out << "private "; break;
|
||||
case GlobalValue::InternalLinkage: Out << "internal "; break;
|
||||
case GlobalValue::AvailableExternallyLinkage:
|
||||
Out << "available_externally ";
|
||||
break;
|
||||
case GlobalValue::LinkOnceAnyLinkage: Out << "linkonce "; break;
|
||||
case GlobalValue::LinkOnceODRLinkage: Out << "linkonce_odr "; break;
|
||||
case GlobalValue::WeakAnyLinkage: Out << "weak "; break;
|
||||
|
10
test/CodeGen/Generic/externally_available.ll
Normal file
10
test/CodeGen/Generic/externally_available.ll
Normal file
@ -0,0 +1,10 @@
|
||||
; RUN: llvm-as < %s | llc | not grep test_
|
||||
|
||||
; test_function should not be emitted to the .s file.
|
||||
define available_externally i32 @test_function() {
|
||||
ret i32 4
|
||||
}
|
||||
|
||||
; test_global should not be emitted to the .s file.
|
||||
@test_global = available_externally global i32 4
|
||||
|
10
test/Transforms/GlobalDCE/externally_available.ll
Normal file
10
test/Transforms/GlobalDCE/externally_available.ll
Normal file
@ -0,0 +1,10 @@
|
||||
; RUN: llvm-as < %s | opt -globaldce | llvm-dis | not grep test_
|
||||
|
||||
; test_function should not be emitted to the .s file.
|
||||
define available_externally i32 @test_function() {
|
||||
ret i32 4
|
||||
}
|
||||
|
||||
; test_global should not be emitted to the .s file.
|
||||
@test_global = available_externally global i32 4
|
||||
|
16
test/Transforms/Inline/externally_available.ll
Normal file
16
test/Transforms/Inline/externally_available.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; RUN: llvm-as < %s | opt -inline -constprop | llvm-dis > %t
|
||||
; RUN: not grep test_function %t
|
||||
; RUN: grep {ret i32 5} %t
|
||||
|
||||
|
||||
; test_function should not be emitted to the .s file.
|
||||
define available_externally i32 @test_function() {
|
||||
ret i32 4
|
||||
}
|
||||
|
||||
|
||||
define i32 @result() {
|
||||
%A = call i32 @test_function()
|
||||
%B = add i32 %A, 1
|
||||
ret i32 %B
|
||||
}
|
19
test/Transforms/InstCombine/odr-linkage.ll
Normal file
19
test/Transforms/InstCombine/odr-linkage.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ret i32 10}
|
||||
|
||||
@g1 = available_externally constant i32 1
|
||||
@g2 = linkonce_odr constant i32 2
|
||||
@g3 = weak_odr constant i32 3
|
||||
@g4 = internal constant i32 4
|
||||
|
||||
define i32 @test() {
|
||||
%A = load i32* @g1
|
||||
%B = load i32* @g2
|
||||
%C = load i32* @g3
|
||||
%D = load i32* @g4
|
||||
|
||||
%a = add i32 %A, %B
|
||||
%b = add i32 %a, %C
|
||||
%c = add i32 %b, %D
|
||||
ret i32 %c
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ namespace {
|
||||
}
|
||||
|
||||
static char TypeCharForSymbol(GlobalValue &GV) {
|
||||
/* FIXME: what to do with private linkage? */
|
||||
if (GV.isDeclaration()) return 'U';
|
||||
if (GV.hasLinkOnceLinkage()) return 'C';
|
||||
if (GV.hasCommonLinkage()) return 'C';
|
||||
@ -87,8 +86,11 @@ static char TypeCharForSymbol(GlobalValue &GV) {
|
||||
}
|
||||
|
||||
static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
|
||||
// Private linkage and available_externally linkage don't exist in symtab.
|
||||
if (GV.hasPrivateLinkage() || GV.hasAvailableExternallyLinkage()) return;
|
||||
|
||||
const std::string SymbolAddrStr = " "; // Not used yet...
|
||||
char TypeChar = TypeCharForSymbol (GV);
|
||||
char TypeChar = TypeCharForSymbol(GV);
|
||||
if ((TypeChar != 'U') && UndefinedOnly)
|
||||
return;
|
||||
if ((TypeChar == 'U') && DefinedOnly)
|
||||
@ -96,17 +98,17 @@ static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
|
||||
if (GV.hasLocalLinkage () && ExternalOnly)
|
||||
return;
|
||||
if (OutputFormat == posix) {
|
||||
std::cout << GV.getName () << " " << TypeCharForSymbol (GV) << " "
|
||||
std::cout << GV.getName () << " " << TypeCharForSymbol(GV) << " "
|
||||
<< SymbolAddrStr << "\n";
|
||||
} else if (OutputFormat == bsd) {
|
||||
std::cout << SymbolAddrStr << " " << TypeCharForSymbol (GV) << " "
|
||||
std::cout << SymbolAddrStr << " " << TypeCharForSymbol(GV) << " "
|
||||
<< GV.getName () << "\n";
|
||||
} else if (OutputFormat == sysv) {
|
||||
std::string PaddedName (GV.getName ());
|
||||
while (PaddedName.length () < 20)
|
||||
PaddedName += " ";
|
||||
std::cout << PaddedName << "|" << SymbolAddrStr << "| "
|
||||
<< TypeCharForSymbol (GV)
|
||||
<< TypeCharForSymbol(GV)
|
||||
<< " | | | |\n";
|
||||
}
|
||||
}
|
||||
@ -122,10 +124,10 @@ static void DumpSymbolNamesFromModule(Module *M) {
|
||||
<< "Name Value Class Type"
|
||||
<< " Size Line Section\n";
|
||||
}
|
||||
std::for_each (M->begin (), M->end (), DumpSymbolNameForGlobalValue);
|
||||
std::for_each (M->global_begin (), M->global_end (),
|
||||
std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue);
|
||||
std::for_each (M->global_begin(), M->global_end(),
|
||||
DumpSymbolNameForGlobalValue);
|
||||
std::for_each (M->alias_begin (), M->alias_end (),
|
||||
std::for_each (M->alias_begin(), M->alias_end(),
|
||||
DumpSymbolNameForGlobalValue);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user