mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Implement function prefix data as an IR feature.
Previous discussion: http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/063909.html Differential Revision: http://llvm-reviews.chandlerc.com/D1191 llvm-svn: 190773
This commit is contained in:
parent
5bb449bca0
commit
cf3b1a2910
@ -718,7 +718,7 @@ global variable. The operand fields are:
|
|||||||
MODULE_CODE_FUNCTION Record
|
MODULE_CODE_FUNCTION Record
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc]``
|
``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix]``
|
||||||
|
|
||||||
The ``FUNCTION`` record (code 8) marks the declaration or definition of a
|
The ``FUNCTION`` record (code 8) marks the declaration or definition of a
|
||||||
function. The operand fields are:
|
function. The operand fields are:
|
||||||
@ -757,6 +757,9 @@ function. The operand fields are:
|
|||||||
* *unnamed_addr*: If present and non-zero, indicates that the function has
|
* *unnamed_addr*: If present and non-zero, indicates that the function has
|
||||||
``unnamed_addr``
|
``unnamed_addr``
|
||||||
|
|
||||||
|
* *prefix*: If non-zero, the value index of the prefix data for this function,
|
||||||
|
plus 1.
|
||||||
|
|
||||||
MODULE_CODE_ALIAS Record
|
MODULE_CODE_ALIAS Record
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -552,16 +552,16 @@ an optional ``unnamed_addr`` attribute, a return type, an optional
|
|||||||
name, a (possibly empty) argument list (each with optional :ref:`parameter
|
name, a (possibly empty) argument list (each with optional :ref:`parameter
|
||||||
attributes <paramattrs>`), optional :ref:`function attributes <fnattrs>`,
|
attributes <paramattrs>`), optional :ref:`function attributes <fnattrs>`,
|
||||||
an optional section, an optional alignment, an optional :ref:`garbage
|
an optional section, an optional alignment, an optional :ref:`garbage
|
||||||
collector name <gc>`, an opening curly brace, a list of basic blocks,
|
collector name <gc>`, an optional :ref:`prefix <prefixdata>`, an opening
|
||||||
and a closing curly brace.
|
curly brace, a list of basic blocks, and a closing curly brace.
|
||||||
|
|
||||||
LLVM function declarations consist of the "``declare``" keyword, an
|
LLVM function declarations consist of the "``declare``" keyword, an
|
||||||
optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
|
optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
|
||||||
style <visibility>`, an optional :ref:`calling convention <callingconv>`,
|
style <visibility>`, an optional :ref:`calling convention <callingconv>`,
|
||||||
an optional ``unnamed_addr`` attribute, a return type, an optional
|
an optional ``unnamed_addr`` attribute, a return type, an optional
|
||||||
:ref:`parameter attribute <paramattrs>` for the return type, a function
|
:ref:`parameter attribute <paramattrs>` for the return type, a function
|
||||||
name, a possibly empty list of arguments, an optional alignment, and an
|
name, a possibly empty list of arguments, an optional alignment, an optional
|
||||||
optional :ref:`garbage collector name <gc>`.
|
:ref:`garbage collector name <gc>` and an optional :ref:`prefix <prefixdata>`.
|
||||||
|
|
||||||
A function definition contains a list of basic blocks, forming the CFG
|
A function definition contains a list of basic blocks, forming the CFG
|
||||||
(Control Flow Graph) for the function. Each basic block may optionally
|
(Control Flow Graph) for the function. Each basic block may optionally
|
||||||
@ -598,7 +598,7 @@ Syntax::
|
|||||||
[cconv] [ret attrs]
|
[cconv] [ret attrs]
|
||||||
<ResultType> @<FunctionName> ([argument list])
|
<ResultType> @<FunctionName> ([argument list])
|
||||||
[fn Attrs] [section "name"] [align N]
|
[fn Attrs] [section "name"] [align N]
|
||||||
[gc] { ... }
|
[gc] [prefix Constant] { ... }
|
||||||
|
|
||||||
.. _langref_aliases:
|
.. _langref_aliases:
|
||||||
|
|
||||||
@ -757,6 +757,50 @@ The compiler declares the supported values of *name*. Specifying a
|
|||||||
collector which will cause the compiler to alter its output in order to
|
collector which will cause the compiler to alter its output in order to
|
||||||
support the named garbage collection algorithm.
|
support the named garbage collection algorithm.
|
||||||
|
|
||||||
|
.. _prefixdata:
|
||||||
|
|
||||||
|
Prefix Data
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Prefix data is data associated with a function which the code generator
|
||||||
|
will emit immediately before the function body. The purpose of this feature
|
||||||
|
is to allow frontends to associate language-specific runtime metadata with
|
||||||
|
specific functions and make it available through the function pointer while
|
||||||
|
still allowing the function pointer to be called. To access the data for a
|
||||||
|
given function, a program may bitcast the function pointer to a pointer to
|
||||||
|
the constant's type. This implies that the IR symbol points to the start
|
||||||
|
of the prefix data.
|
||||||
|
|
||||||
|
To maintain the semantics of ordinary function calls, the prefix data must
|
||||||
|
have a particular format. Specifically, it must begin with a sequence of
|
||||||
|
bytes which decode to a sequence of machine instructions, valid for the
|
||||||
|
module's target, which transfer control to the point immediately succeeding
|
||||||
|
the prefix data, without performing any other visible action. This allows
|
||||||
|
the inliner and other passes to reason about the semantics of the function
|
||||||
|
definition without needing to reason about the prefix data. Obviously this
|
||||||
|
makes the format of the prefix data highly target dependent.
|
||||||
|
|
||||||
|
A trivial example of valid prefix data for the x86 architecture is ``i8 144``,
|
||||||
|
which encodes the ``nop`` instruction:
|
||||||
|
|
||||||
|
.. code-block:: llvm
|
||||||
|
|
||||||
|
define void @f() prefix i8 144 { ... }
|
||||||
|
|
||||||
|
Generally prefix data can be formed by encoding a relative branch instruction
|
||||||
|
which skips the metadata, as in this example of valid prefix data for the
|
||||||
|
x86_64 architecture, where the first two bytes encode ``jmp .+10``:
|
||||||
|
|
||||||
|
.. code-block:: llvm
|
||||||
|
|
||||||
|
%0 = type <{ i8, i8, i8* }>
|
||||||
|
|
||||||
|
define void @f() prefix %0 <{ i8 235, i8 8, i8* @md}> { ... }
|
||||||
|
|
||||||
|
A function may have prefix data but no body. This has similar semantics
|
||||||
|
to the ``available_externally`` linkage in that the data may be used by the
|
||||||
|
optimizers but will not be emitted in the object file.
|
||||||
|
|
||||||
.. _attrgrp:
|
.. _attrgrp:
|
||||||
|
|
||||||
Attribute Groups
|
Attribute Groups
|
||||||
|
@ -159,11 +159,11 @@ public:
|
|||||||
/// calling convention of this function. The enum values for the known
|
/// calling convention of this function. The enum values for the known
|
||||||
/// calling conventions are defined in CallingConv.h.
|
/// calling conventions are defined in CallingConv.h.
|
||||||
CallingConv::ID getCallingConv() const {
|
CallingConv::ID getCallingConv() const {
|
||||||
return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 1);
|
return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2);
|
||||||
}
|
}
|
||||||
void setCallingConv(CallingConv::ID CC) {
|
void setCallingConv(CallingConv::ID CC) {
|
||||||
setValueSubclassData((getSubclassDataFromValue() & 1) |
|
setValueSubclassData((getSubclassDataFromValue() & 3) |
|
||||||
(static_cast<unsigned>(CC) << 1));
|
(static_cast<unsigned>(CC) << 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Return the attribute list for this Function.
|
/// @brief Return the attribute list for this Function.
|
||||||
@ -427,6 +427,13 @@ public:
|
|||||||
size_t arg_size() const;
|
size_t arg_size() const;
|
||||||
bool arg_empty() const;
|
bool arg_empty() const;
|
||||||
|
|
||||||
|
bool hasPrefixData() const {
|
||||||
|
return getSubclassDataFromValue() & 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constant *getPrefixData() const;
|
||||||
|
void setPrefixData(Constant *PrefixData);
|
||||||
|
|
||||||
/// viewCFG - This function is meant for use from the debugger. You can just
|
/// viewCFG - This function is meant for use from the debugger. You can just
|
||||||
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
|
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
|
||||||
/// program, displaying the CFG of the current function with the code for each
|
/// program, displaying the CFG of the current function with the code for each
|
||||||
|
@ -540,6 +540,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
|||||||
KEYWORD(alignstack);
|
KEYWORD(alignstack);
|
||||||
KEYWORD(inteldialect);
|
KEYWORD(inteldialect);
|
||||||
KEYWORD(gc);
|
KEYWORD(gc);
|
||||||
|
KEYWORD(prefix);
|
||||||
|
|
||||||
KEYWORD(ccc);
|
KEYWORD(ccc);
|
||||||
KEYWORD(fastcc);
|
KEYWORD(fastcc);
|
||||||
|
@ -2922,7 +2922,7 @@ bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
|
|||||||
/// FunctionHeader
|
/// FunctionHeader
|
||||||
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
|
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
|
||||||
/// OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
|
/// OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
|
||||||
/// OptionalAlign OptGC
|
/// OptionalAlign OptGC OptionalPrefix
|
||||||
bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
||||||
// Parse the linkage.
|
// Parse the linkage.
|
||||||
LocTy LinkageLoc = Lex.getLoc();
|
LocTy LinkageLoc = Lex.getLoc();
|
||||||
@ -3001,6 +3001,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
|||||||
std::string GC;
|
std::string GC;
|
||||||
bool UnnamedAddr;
|
bool UnnamedAddr;
|
||||||
LocTy UnnamedAddrLoc;
|
LocTy UnnamedAddrLoc;
|
||||||
|
Constant *Prefix = 0;
|
||||||
|
|
||||||
if (ParseArgumentList(ArgList, isVarArg) ||
|
if (ParseArgumentList(ArgList, isVarArg) ||
|
||||||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
|
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
|
||||||
@ -3011,7 +3012,9 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
|||||||
ParseStringConstant(Section)) ||
|
ParseStringConstant(Section)) ||
|
||||||
ParseOptionalAlignment(Alignment) ||
|
ParseOptionalAlignment(Alignment) ||
|
||||||
(EatIfPresent(lltok::kw_gc) &&
|
(EatIfPresent(lltok::kw_gc) &&
|
||||||
ParseStringConstant(GC)))
|
ParseStringConstant(GC)) ||
|
||||||
|
(EatIfPresent(lltok::kw_prefix) &&
|
||||||
|
ParseGlobalTypeAndValue(Prefix)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (FuncAttrs.contains(Attribute::Builtin))
|
if (FuncAttrs.contains(Attribute::Builtin))
|
||||||
@ -3109,6 +3112,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
|||||||
Fn->setAlignment(Alignment);
|
Fn->setAlignment(Alignment);
|
||||||
Fn->setSection(Section);
|
Fn->setSection(Section);
|
||||||
if (!GC.empty()) Fn->setGC(GC.c_str());
|
if (!GC.empty()) Fn->setGC(GC.c_str());
|
||||||
|
Fn->setPrefixData(Prefix);
|
||||||
ForwardRefAttrGroups[Fn] = FwdRefAttrGrps;
|
ForwardRefAttrGroups[Fn] = FwdRefAttrGrps;
|
||||||
|
|
||||||
// Add all of the arguments we parsed to the function.
|
// Add all of the arguments we parsed to the function.
|
||||||
|
@ -81,6 +81,7 @@ namespace lltok {
|
|||||||
kw_alignstack,
|
kw_alignstack,
|
||||||
kw_inteldialect,
|
kw_inteldialect,
|
||||||
kw_gc,
|
kw_gc,
|
||||||
|
kw_prefix,
|
||||||
kw_c,
|
kw_c,
|
||||||
|
|
||||||
kw_cc, kw_ccc, kw_fastcc, kw_coldcc,
|
kw_cc, kw_ccc, kw_fastcc, kw_coldcc,
|
||||||
|
@ -1106,9 +1106,11 @@ uint64_t BitcodeReader::decodeSignRotatedValue(uint64_t V) {
|
|||||||
bool BitcodeReader::ResolveGlobalAndAliasInits() {
|
bool BitcodeReader::ResolveGlobalAndAliasInits() {
|
||||||
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
|
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
|
||||||
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
|
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
|
||||||
|
std::vector<std::pair<Function*, unsigned> > FunctionPrefixWorklist;
|
||||||
|
|
||||||
GlobalInitWorklist.swap(GlobalInits);
|
GlobalInitWorklist.swap(GlobalInits);
|
||||||
AliasInitWorklist.swap(AliasInits);
|
AliasInitWorklist.swap(AliasInits);
|
||||||
|
FunctionPrefixWorklist.swap(FunctionPrefixes);
|
||||||
|
|
||||||
while (!GlobalInitWorklist.empty()) {
|
while (!GlobalInitWorklist.empty()) {
|
||||||
unsigned ValID = GlobalInitWorklist.back().second;
|
unsigned ValID = GlobalInitWorklist.back().second;
|
||||||
@ -1136,6 +1138,20 @@ bool BitcodeReader::ResolveGlobalAndAliasInits() {
|
|||||||
}
|
}
|
||||||
AliasInitWorklist.pop_back();
|
AliasInitWorklist.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!FunctionPrefixWorklist.empty()) {
|
||||||
|
unsigned ValID = FunctionPrefixWorklist.back().second;
|
||||||
|
if (ValID >= ValueList.size()) {
|
||||||
|
FunctionPrefixes.push_back(FunctionPrefixWorklist.back());
|
||||||
|
} else {
|
||||||
|
if (Constant *C = dyn_cast<Constant>(ValueList[ValID]))
|
||||||
|
FunctionPrefixWorklist.back().first->setPrefixData(C);
|
||||||
|
else
|
||||||
|
return Error("Function prefix is not a constant!");
|
||||||
|
}
|
||||||
|
FunctionPrefixWorklist.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1881,6 +1897,8 @@ bool BitcodeReader::ParseModule(bool Resume) {
|
|||||||
if (Record.size() > 9)
|
if (Record.size() > 9)
|
||||||
UnnamedAddr = Record[9];
|
UnnamedAddr = Record[9];
|
||||||
Func->setUnnamedAddr(UnnamedAddr);
|
Func->setUnnamedAddr(UnnamedAddr);
|
||||||
|
if (Record.size() > 10 && Record[10] != 0)
|
||||||
|
FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1));
|
||||||
ValueList.push_back(Func);
|
ValueList.push_back(Func);
|
||||||
|
|
||||||
// If this is a function with a body, remember the prototype we are
|
// If this is a function with a body, remember the prototype we are
|
||||||
|
@ -142,6 +142,7 @@ class BitcodeReader : public GVMaterializer {
|
|||||||
|
|
||||||
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
|
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
|
||||||
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
|
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
|
||||||
|
std::vector<std::pair<Function*, unsigned> > FunctionPrefixes;
|
||||||
|
|
||||||
/// MAttributes - The set of attributes by index. Index zero in the
|
/// MAttributes - The set of attributes by index. Index zero in the
|
||||||
/// file is for null, and is thus not represented here. As such all indices
|
/// file is for null, and is thus not represented here. As such all indices
|
||||||
|
@ -632,7 +632,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
|
|||||||
// Emit the function proto information.
|
// Emit the function proto information.
|
||||||
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
|
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
|
||||||
// FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
|
// FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
|
||||||
// section, visibility, gc, unnamed_addr]
|
// section, visibility, gc, unnamed_addr, prefix]
|
||||||
Vals.push_back(VE.getTypeID(F->getType()));
|
Vals.push_back(VE.getTypeID(F->getType()));
|
||||||
Vals.push_back(F->getCallingConv());
|
Vals.push_back(F->getCallingConv());
|
||||||
Vals.push_back(F->isDeclaration());
|
Vals.push_back(F->isDeclaration());
|
||||||
@ -643,6 +643,8 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
|
|||||||
Vals.push_back(getEncodedVisibility(F));
|
Vals.push_back(getEncodedVisibility(F));
|
||||||
Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0);
|
Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0);
|
||||||
Vals.push_back(F->hasUnnamedAddr());
|
Vals.push_back(F->hasUnnamedAddr());
|
||||||
|
Vals.push_back(F->hasPrefixData() ? (VE.getValueID(F->getPrefixData()) + 1)
|
||||||
|
: 0);
|
||||||
|
|
||||||
unsigned AbbrevToUse = 0;
|
unsigned AbbrevToUse = 0;
|
||||||
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
|
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
|
||||||
@ -1863,6 +1865,8 @@ static void WriteModuleUseLists(const Module *M, ValueEnumerator &VE,
|
|||||||
WriteUseList(FI, VE, Stream);
|
WriteUseList(FI, VE, Stream);
|
||||||
if (!FI->isDeclaration())
|
if (!FI->isDeclaration())
|
||||||
WriteFunctionUseList(FI, VE, Stream);
|
WriteFunctionUseList(FI, VE, Stream);
|
||||||
|
if (FI->hasPrefixData())
|
||||||
|
WriteUseList(FI->getPrefixData(), VE, Stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the aliases.
|
// Write the aliases.
|
||||||
|
@ -60,6 +60,11 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
|
|||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
EnumerateValue(I->getAliasee());
|
EnumerateValue(I->getAliasee());
|
||||||
|
|
||||||
|
// Enumerate the prefix data constants.
|
||||||
|
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
|
||||||
|
if (I->hasPrefixData())
|
||||||
|
EnumerateValue(I->getPrefixData());
|
||||||
|
|
||||||
// Insert constants and metadata that are named at module level into the slot
|
// Insert constants and metadata that are named at module level into the slot
|
||||||
// pool so that the module symbol table can refer to them...
|
// pool so that the module symbol table can refer to them...
|
||||||
EnumerateValueSymbolTable(M->getValueSymbolTable());
|
EnumerateValueSymbolTable(M->getValueSymbolTable());
|
||||||
|
@ -459,6 +459,10 @@ void AsmPrinter::EmitFunctionHeader() {
|
|||||||
OutStreamer.EmitLabel(DeadBlockSyms[i]);
|
OutStreamer.EmitLabel(DeadBlockSyms[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit the prefix data.
|
||||||
|
if (F->hasPrefixData())
|
||||||
|
EmitGlobalConstant(F->getPrefixData());
|
||||||
|
|
||||||
// Emit pre-function debug and/or EH information.
|
// Emit pre-function debug and/or EH information.
|
||||||
if (DE) {
|
if (DE) {
|
||||||
NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
|
NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
|
||||||
|
@ -1647,6 +1647,10 @@ void AssemblyWriter::printFunction(const Function *F) {
|
|||||||
Out << " align " << F->getAlignment();
|
Out << " align " << F->getAlignment();
|
||||||
if (F->hasGC())
|
if (F->hasGC())
|
||||||
Out << " gc \"" << F->getGC() << '"';
|
Out << " gc \"" << F->getGC() << '"';
|
||||||
|
if (F->hasPrefixData()) {
|
||||||
|
Out << " prefix ";
|
||||||
|
writeOperand(F->getPrefixData(), true);
|
||||||
|
}
|
||||||
if (F->isDeclaration()) {
|
if (F->isDeclaration()) {
|
||||||
Out << '\n';
|
Out << '\n';
|
||||||
} else {
|
} else {
|
||||||
|
@ -276,6 +276,9 @@ void Function::dropAllReferences() {
|
|||||||
// blockaddresses, but BasicBlock's destructor takes care of those.
|
// blockaddresses, but BasicBlock's destructor takes care of those.
|
||||||
while (!BasicBlocks.empty())
|
while (!BasicBlocks.empty())
|
||||||
BasicBlocks.begin()->eraseFromParent();
|
BasicBlocks.begin()->eraseFromParent();
|
||||||
|
|
||||||
|
// Prefix data is stored in a side table.
|
||||||
|
setPrefixData(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Function::addAttribute(unsigned i, Attribute::AttrKind attr) {
|
void Function::addAttribute(unsigned i, Attribute::AttrKind attr) {
|
||||||
@ -351,6 +354,10 @@ void Function::copyAttributesFrom(const GlobalValue *Src) {
|
|||||||
setGC(SrcF->getGC());
|
setGC(SrcF->getGC());
|
||||||
else
|
else
|
||||||
clearGC();
|
clearGC();
|
||||||
|
if (SrcF->hasPrefixData())
|
||||||
|
setPrefixData(SrcF->getPrefixData());
|
||||||
|
else
|
||||||
|
setPrefixData(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getIntrinsicID - This method returns the ID number of the specified
|
/// getIntrinsicID - This method returns the ID number of the specified
|
||||||
@ -720,3 +727,32 @@ bool Function::callsFunctionThatReturnsTwice() const {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Constant *Function::getPrefixData() const {
|
||||||
|
assert(hasPrefixData());
|
||||||
|
const LLVMContextImpl::PrefixDataMapTy &PDMap =
|
||||||
|
getContext().pImpl->PrefixDataMap;
|
||||||
|
assert(PDMap.find(this) != PDMap.end());
|
||||||
|
return cast<Constant>(PDMap.find(this)->second->getReturnValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Function::setPrefixData(Constant *PrefixData) {
|
||||||
|
if (!PrefixData && !hasPrefixData())
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned SCData = getSubclassDataFromValue();
|
||||||
|
LLVMContextImpl::PrefixDataMapTy &PDMap = getContext().pImpl->PrefixDataMap;
|
||||||
|
ReturnInst *&PDHolder = PDMap[this];
|
||||||
|
if (PrefixData) {
|
||||||
|
if (PDHolder)
|
||||||
|
PDHolder->setOperand(0, PrefixData);
|
||||||
|
else
|
||||||
|
PDHolder = ReturnInst::Create(getContext(), PrefixData);
|
||||||
|
SCData |= 2;
|
||||||
|
} else {
|
||||||
|
delete PDHolder;
|
||||||
|
PDMap.erase(this);
|
||||||
|
SCData &= ~2;
|
||||||
|
}
|
||||||
|
setValueSubclassData(SCData);
|
||||||
|
}
|
||||||
|
@ -355,6 +355,11 @@ public:
|
|||||||
typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy;
|
typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy;
|
||||||
IntrinsicIDCacheTy IntrinsicIDCache;
|
IntrinsicIDCacheTy IntrinsicIDCache;
|
||||||
|
|
||||||
|
/// \brief Mapping from a function to its prefix data, which is stored as the
|
||||||
|
/// operand of an unparented ReturnInst so that the prefix data has a Use.
|
||||||
|
typedef DenseMap<const Function *, ReturnInst *> PrefixDataMapTy;
|
||||||
|
PrefixDataMapTy PrefixDataMap;
|
||||||
|
|
||||||
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
|
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
|
||||||
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
|
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
|
||||||
|
|
||||||
|
@ -44,6 +44,9 @@ void TypeFinder::run(const Module &M, bool onlyNamed) {
|
|||||||
for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
|
for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
|
||||||
incorporateType(FI->getType());
|
incorporateType(FI->getType());
|
||||||
|
|
||||||
|
if (FI->hasPrefixData())
|
||||||
|
incorporateValue(FI->getPrefixData());
|
||||||
|
|
||||||
// First incorporate the arguments.
|
// First incorporate the arguments.
|
||||||
for (Function::const_arg_iterator AI = FI->arg_begin(),
|
for (Function::const_arg_iterator AI = FI->arg_begin(),
|
||||||
AE = FI->arg_end(); AI != AE; ++AI)
|
AE = FI->arg_end(); AI != AE; ++AI)
|
||||||
|
@ -1260,6 +1260,13 @@ bool ModuleLinker::run() {
|
|||||||
// Skip if not linking from source.
|
// Skip if not linking from source.
|
||||||
if (DoNotLinkFromSource.count(SF)) continue;
|
if (DoNotLinkFromSource.count(SF)) continue;
|
||||||
|
|
||||||
|
Function *DF = cast<Function>(ValueMap[SF]);
|
||||||
|
if (SF->hasPrefixData()) {
|
||||||
|
// Link in the prefix data.
|
||||||
|
DF->setPrefixData(MapValue(
|
||||||
|
SF->getPrefixData(), ValueMap, RF_None, &TypeMap, &ValMaterializer));
|
||||||
|
}
|
||||||
|
|
||||||
// Skip if no body (function is external) or materialize.
|
// Skip if no body (function is external) or materialize.
|
||||||
if (SF->isDeclaration()) {
|
if (SF->isDeclaration()) {
|
||||||
if (!SF->isMaterializable())
|
if (!SF->isMaterializable())
|
||||||
@ -1268,7 +1275,7 @@ bool ModuleLinker::run() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
linkFunctionBody(cast<Function>(ValueMap[SF]), SF);
|
linkFunctionBody(DF, SF);
|
||||||
SF->Dematerialize();
|
SF->Dematerialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1296,6 +1303,14 @@ bool ModuleLinker::run() {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Function *DF = cast<Function>(ValueMap[SF]);
|
Function *DF = cast<Function>(ValueMap[SF]);
|
||||||
|
if (SF->hasPrefixData()) {
|
||||||
|
// Link in the prefix data.
|
||||||
|
DF->setPrefixData(MapValue(SF->getPrefixData(),
|
||||||
|
ValueMap,
|
||||||
|
RF_None,
|
||||||
|
&TypeMap,
|
||||||
|
&ValMaterializer));
|
||||||
|
}
|
||||||
|
|
||||||
// Materialize if necessary.
|
// Materialize if necessary.
|
||||||
if (SF->isDeclaration()) {
|
if (SF->isDeclaration()) {
|
||||||
|
@ -179,6 +179,9 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
|
|||||||
// any globals used will be marked as needed.
|
// any globals used will be marked as needed.
|
||||||
Function *F = cast<Function>(G);
|
Function *F = cast<Function>(G);
|
||||||
|
|
||||||
|
if (F->hasPrefixData())
|
||||||
|
MarkUsedGlobalsAsNeeded(F->getPrefixData());
|
||||||
|
|
||||||
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
||||||
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
|
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
|
||||||
for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)
|
for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)
|
||||||
|
15
test/CodeGen/X86/prefixdata.ll
Normal file
15
test/CodeGen/X86/prefixdata.ll
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
|
||||||
|
|
||||||
|
@i = linkonce_odr global i32 1
|
||||||
|
|
||||||
|
; CHECK: f:
|
||||||
|
; CHECK-NEXT: .long 1
|
||||||
|
define void @f() prefix i32 1 {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: g:
|
||||||
|
; CHECK-NEXT: .quad i
|
||||||
|
define void @g() prefix i32* @i {
|
||||||
|
ret void
|
||||||
|
}
|
18
test/Feature/prefixdata.ll
Normal file
18
test/Feature/prefixdata.ll
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
; RUN: llvm-as < %s | llvm-dis > %t1.ll
|
||||||
|
; RUN: FileCheck %s < %t1.ll
|
||||||
|
; RUN: llvm-as < %t1.ll | llvm-dis > %t2.ll
|
||||||
|
; RUN: diff %t1.ll %t2.ll
|
||||||
|
; RUN: opt -O3 -S < %t1.ll | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK: @i
|
||||||
|
@i = linkonce_odr global i32 1
|
||||||
|
|
||||||
|
; CHECK: f(){{.*}}prefix i32 1
|
||||||
|
define void @f() prefix i32 1 {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: g(){{.*}}prefix i32* @i
|
||||||
|
define void @g() prefix i32* @i {
|
||||||
|
ret void
|
||||||
|
}
|
9
test/Linker/prefixdata.ll
Normal file
9
test/Linker/prefixdata.ll
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
; RUN: echo > %t.ll
|
||||||
|
; RUN: llvm-link %t.ll %s -S -o - | FileCheck %s
|
||||||
|
|
||||||
|
@i = linkonce_odr global i32 1
|
||||||
|
|
||||||
|
; CHECK: define void @f() prefix i32* @i
|
||||||
|
define void @f() prefix i32* @i {
|
||||||
|
ret void
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user