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:
Peter Collingbourne 2013-09-16 01:08:15 +00:00
parent 3ee2bf6a62
commit 3fa50f9b05
20 changed files with 213 additions and 13 deletions

View File

@ -718,7 +718,7 @@ global variable. The operand fields are:
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
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``
* *prefix*: If non-zero, the value index of the prefix data for this function,
plus 1.
MODULE_CODE_ALIAS Record
^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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
attributes <paramattrs>`), optional :ref:`function attributes <fnattrs>`,
an optional section, an optional alignment, an optional :ref:`garbage
collector name <gc>`, an opening curly brace, a list of basic blocks,
and a closing curly brace.
collector name <gc>`, an optional :ref:`prefix <prefixdata>`, an opening
curly brace, a list of basic blocks, and a closing curly brace.
LLVM function declarations consist of the "``declare``" keyword, an
optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
style <visibility>`, an optional :ref:`calling convention <callingconv>`,
an optional ``unnamed_addr`` attribute, a return type, an optional
:ref:`parameter attribute <paramattrs>` for the return type, a function
name, a possibly empty list of arguments, an optional alignment, and an
optional :ref:`garbage collector name <gc>`.
name, a possibly empty list of arguments, an optional alignment, an optional
:ref:`garbage collector name <gc>` and an optional :ref:`prefix <prefixdata>`.
A function definition contains a list of basic blocks, forming the CFG
(Control Flow Graph) for the function. Each basic block may optionally
@ -598,7 +598,7 @@ Syntax::
[cconv] [ret attrs]
<ResultType> @<FunctionName> ([argument list])
[fn Attrs] [section "name"] [align N]
[gc] { ... }
[gc] [prefix Constant] { ... }
.. _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
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:
Attribute Groups

View File

@ -159,11 +159,11 @@ public:
/// calling convention of this function. The enum values for the known
/// calling conventions are defined in CallingConv.h.
CallingConv::ID getCallingConv() const {
return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 1);
return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2);
}
void setCallingConv(CallingConv::ID CC) {
setValueSubclassData((getSubclassDataFromValue() & 1) |
(static_cast<unsigned>(CC) << 1));
setValueSubclassData((getSubclassDataFromValue() & 3) |
(static_cast<unsigned>(CC) << 2));
}
/// @brief Return the attribute list for this Function.
@ -427,6 +427,13 @@ public:
size_t arg_size() 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
/// 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

View File

@ -540,6 +540,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(alignstack);
KEYWORD(inteldialect);
KEYWORD(gc);
KEYWORD(prefix);
KEYWORD(ccc);
KEYWORD(fastcc);

View File

@ -2922,7 +2922,7 @@ bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
/// FunctionHeader
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
/// OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
/// OptionalAlign OptGC
/// OptionalAlign OptGC OptionalPrefix
bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
// Parse the linkage.
LocTy LinkageLoc = Lex.getLoc();
@ -3001,6 +3001,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
std::string GC;
bool UnnamedAddr;
LocTy UnnamedAddrLoc;
Constant *Prefix = 0;
if (ParseArgumentList(ArgList, isVarArg) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
@ -3011,7 +3012,9 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
ParseStringConstant(Section)) ||
ParseOptionalAlignment(Alignment) ||
(EatIfPresent(lltok::kw_gc) &&
ParseStringConstant(GC)))
ParseStringConstant(GC)) ||
(EatIfPresent(lltok::kw_prefix) &&
ParseGlobalTypeAndValue(Prefix)))
return true;
if (FuncAttrs.contains(Attribute::Builtin))
@ -3109,6 +3112,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
Fn->setAlignment(Alignment);
Fn->setSection(Section);
if (!GC.empty()) Fn->setGC(GC.c_str());
Fn->setPrefixData(Prefix);
ForwardRefAttrGroups[Fn] = FwdRefAttrGrps;
// Add all of the arguments we parsed to the function.

View File

@ -81,6 +81,7 @@ namespace lltok {
kw_alignstack,
kw_inteldialect,
kw_gc,
kw_prefix,
kw_c,
kw_cc, kw_ccc, kw_fastcc, kw_coldcc,

View File

@ -1106,9 +1106,11 @@ uint64_t BitcodeReader::decodeSignRotatedValue(uint64_t V) {
bool BitcodeReader::ResolveGlobalAndAliasInits() {
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
std::vector<std::pair<Function*, unsigned> > FunctionPrefixWorklist;
GlobalInitWorklist.swap(GlobalInits);
AliasInitWorklist.swap(AliasInits);
FunctionPrefixWorklist.swap(FunctionPrefixes);
while (!GlobalInitWorklist.empty()) {
unsigned ValID = GlobalInitWorklist.back().second;
@ -1136,6 +1138,20 @@ bool BitcodeReader::ResolveGlobalAndAliasInits() {
}
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;
}
@ -1881,6 +1897,8 @@ bool BitcodeReader::ParseModule(bool Resume) {
if (Record.size() > 9)
UnnamedAddr = Record[9];
Func->setUnnamedAddr(UnnamedAddr);
if (Record.size() > 10 && Record[10] != 0)
FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1));
ValueList.push_back(Func);
// If this is a function with a body, remember the prototype we are

View File

@ -142,6 +142,7 @@ class BitcodeReader : public GVMaterializer {
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
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
/// file is for null, and is thus not represented here. As such all indices

View File

@ -632,7 +632,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
// Emit the function proto information.
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
// 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(F->getCallingConv());
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(F->hasGC() ? GCMap[F->getGC()] : 0);
Vals.push_back(F->hasUnnamedAddr());
Vals.push_back(F->hasPrefixData() ? (VE.getValueID(F->getPrefixData()) + 1)
: 0);
unsigned AbbrevToUse = 0;
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
@ -1863,6 +1865,8 @@ static void WriteModuleUseLists(const Module *M, ValueEnumerator &VE,
WriteUseList(FI, VE, Stream);
if (!FI->isDeclaration())
WriteFunctionUseList(FI, VE, Stream);
if (FI->hasPrefixData())
WriteUseList(FI->getPrefixData(), VE, Stream);
}
// Write the aliases.

View File

@ -60,6 +60,11 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
I != E; ++I)
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
// pool so that the module symbol table can refer to them...
EnumerateValueSymbolTable(M->getValueSymbolTable());

View File

@ -459,6 +459,10 @@ void AsmPrinter::EmitFunctionHeader() {
OutStreamer.EmitLabel(DeadBlockSyms[i]);
}
// Emit the prefix data.
if (F->hasPrefixData())
EmitGlobalConstant(F->getPrefixData());
// Emit pre-function debug and/or EH information.
if (DE) {
NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);

View File

@ -1647,6 +1647,10 @@ void AssemblyWriter::printFunction(const Function *F) {
Out << " align " << F->getAlignment();
if (F->hasGC())
Out << " gc \"" << F->getGC() << '"';
if (F->hasPrefixData()) {
Out << " prefix ";
writeOperand(F->getPrefixData(), true);
}
if (F->isDeclaration()) {
Out << '\n';
} else {

View File

@ -276,6 +276,9 @@ void Function::dropAllReferences() {
// blockaddresses, but BasicBlock's destructor takes care of those.
while (!BasicBlocks.empty())
BasicBlocks.begin()->eraseFromParent();
// Prefix data is stored in a side table.
setPrefixData(0);
}
void Function::addAttribute(unsigned i, Attribute::AttrKind attr) {
@ -351,6 +354,10 @@ void Function::copyAttributesFrom(const GlobalValue *Src) {
setGC(SrcF->getGC());
else
clearGC();
if (SrcF->hasPrefixData())
setPrefixData(SrcF->getPrefixData());
else
setPrefixData(0);
}
/// getIntrinsicID - This method returns the ID number of the specified
@ -720,3 +727,32 @@ bool Function::callsFunctionThatReturnsTwice() const {
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);
}

View File

@ -355,6 +355,11 @@ public:
typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy;
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 getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);

View File

@ -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) {
incorporateType(FI->getType());
if (FI->hasPrefixData())
incorporateValue(FI->getPrefixData());
// First incorporate the arguments.
for (Function::const_arg_iterator AI = FI->arg_begin(),
AE = FI->arg_end(); AI != AE; ++AI)

View File

@ -1260,6 +1260,13 @@ bool ModuleLinker::run() {
// Skip if not linking from source.
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.
if (SF->isDeclaration()) {
if (!SF->isMaterializable())
@ -1268,7 +1275,7 @@ bool ModuleLinker::run() {
return true;
}
linkFunctionBody(cast<Function>(ValueMap[SF]), SF);
linkFunctionBody(DF, SF);
SF->Dematerialize();
}
@ -1296,6 +1303,14 @@ bool ModuleLinker::run() {
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));
}
// Materialize if necessary.
if (SF->isDeclaration()) {

View File

@ -179,6 +179,9 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
// any globals used will be marked as needed.
Function *F = cast<Function>(G);
if (F->hasPrefixData())
MarkUsedGlobalsAsNeeded(F->getPrefixData());
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 (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)

View 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
}

View 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
}

View 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
}