Index: llvm/trunk/docs/BitCodeFormat.rst =================================================================== --- llvm/trunk/docs/BitCodeFormat.rst +++ llvm/trunk/docs/BitCodeFormat.rst @@ -741,7 +741,7 @@ MODULE_CODE_FUNCTION Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix, dllstorageclass]`` +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata]`` The ``FUNCTION`` record (code 8) marks the declaration or definition of a function. The operand fields are: @@ -784,12 +784,18 @@ * *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, +* *prologuedata*: If non-zero, the value index of the prologue data for this function, plus 1. * *dllstorageclass*: An encoding of the :ref:`dllstorageclass` of this function +* *comdat*: An encoding of the COMDAT of this function + +* *prefixdata*: If non-zero, the value index of the prefix data for this function, + plus 1. + + MODULE_CODE_ALIAS Record ^^^^^^^^^^^^^^^^^^^^^^^^ Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -633,7 +633,8 @@ attributes `), optional :ref:`function attributes `, an optional section, an optional alignment, an optional :ref:`comdat `, -an optional :ref:`garbage collector name `, an optional :ref:`prefix `, an opening +an optional :ref:`garbage collector name `, an optional :ref:`prefix `, +an optional :ref:`prologue `, an opening curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations consist of the "``declare``" keyword, an @@ -643,7 +644,8 @@ an optional ``unnamed_addr`` attribute, a return type, an optional :ref:`parameter attribute ` for the return type, a function name, a possibly empty list of arguments, an optional alignment, an optional -:ref:`garbage collector name ` and an optional :ref:`prefix `. +:ref:`garbage collector name `, an optional :ref:`prefix `, +and an optional :ref:`prologue `. A function definition contains a list of basic blocks, forming the CFG (Control Flow Graph) for the function. Each basic block may optionally start with a label @@ -680,7 +682,7 @@ [cconv] [ret attrs] @ ([argument list]) [unnamed_addr] [fn Attrs] [section "name"] [comdat $] - [align N] [gc] [prefix Constant] { ... } + [align N] [gc] [prefix Constant] [prologue Constant] { ... } The argument list is a comma seperated sequence of arguments where each argument is of the following form @@ -1021,47 +1023,79 @@ 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. +Prefix data is data associated with a function which the code +generator will emit immediately before the function's entrypoint. +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 maintain the semantics of ordinary function calls, the prefix data must +To access the data for a given function, a program may bitcast the +function pointer to a pointer to the constant's type and dereference +index -1. This implies that the IR symbol points just past the end of +the prefix data. For instance, take the example of a function annotated +with a single ``i32``, + +.. code-block:: llvm + + define void @f() prefix i32 123 { ... } + +The prefix data can be referenced as, + +.. code-block:: llvm + + %0 = bitcast *void () @f to *i32 + %a = getelementptr inbounds *i32 %0, i32 -1 + %b = load i32* %a + +Prefix data is laid out as if it were an initializer for a global variable +of the prefix data's type. The function will be placed such that the +beginning of the prefix data is aligned. This means that if the size +of the prefix data is not a multiple of the alignment size, the +function's entrypoint will not be aligned. If alignment of the +function's entrypoint is desired, padding must be added to the prefix +data. + +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. + +.. _prologuedata: + +Prologue Data +------------- + +The ``prologue`` attribute allows arbitrary code (encoded as bytes) to +be inserted prior to the function body. This can be used for enabling +function hot-patching and instrumentation. + +To maintain the semantics of ordinary function calls, the prologue 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 prologue 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. +definition without needing to reason about the prologue data. Obviously this +makes the format of the prologue data highly target dependent. -Prefix data is laid out as if it were an initializer for a global variable -of the prefix data's type. No padding is automatically placed between the -prefix data and the function body. If padding is required, it must be part -of the prefix data. - -A trivial example of valid prefix data for the x86 architecture is ``i8 144``, +A trivial example of valid prologue data for the x86 architecture is ``i8 144``, which encodes the ``nop`` instruction: .. code-block:: llvm - define void @f() prefix i8 144 { ... } + define void @f() prologue 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 +Generally prologue data can be formed by encoding a relative branch instruction +which skips the metadata, as in this example of valid prologue 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}> { ... } + define void @f() prologue %0 <{ i8 235, i8 8, i8* @md}> { ... } -A function may have prefix data but no body. This has similar semantics +A function may have prologue 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. Index: llvm/trunk/docs/ReleaseNotes.rst =================================================================== --- llvm/trunk/docs/ReleaseNotes.rst +++ llvm/trunk/docs/ReleaseNotes.rst @@ -58,6 +58,50 @@ Makes programs 10x faster by doing Special New Thing. +Prefix data rework +------------------ + +The semantics of the ``prefix`` attribute have been changed. Users +that want the previous ``prefix`` semantics should instead use +``prologue``. To motivate this change, let's examine the primary +usecases that these attributes aim to serve, + + 1. Code sanitization metadata (e.g. Clang's undefined behavior + sanitizer) + + 2. Function hot-patching: Enable the user to insert ``nop`` operations + at the beginning of the function which can later be safely replaced + with a call to some instrumentation facility. + + 3. Language runtime metadata: Allow a compiler to insert data for + use by the runtime during execution. GHC is one example of a + compiler that needs this functionality for its + tables-next-to-code functionality. + +Previously ``prefix`` served cases (1) and (2) quite well by allowing the user +to introduce arbitrary data at the entrypoint but before the function +body. Case (3), however, was poorly handled by this approach as it +required that prefix data was valid executable code. + +In this release the concept of prefix data has been redefined to be +data which occurs immediately before the function entrypoint (i.e. the +symbol address). Since prefix data now occurs before the function +entrypoint, there is no need for the data to be valid code. + +The previous notion of prefix data now goes under the name "prologue +data" to emphasize its duality with the function epilogue. + +The intention here is to handle cases (1) and (2) with prologue data and +case (3) with prefix data. See the language reference for further details +on the semantics of these attributes. + +This refactoring arose out of discussions_ with Reid Kleckner in +response to a proposal to introduce the notion of symbol offsets to +enable handling of case (3). + +.. _discussions: http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-May/073235.html + + Changes to the ARM Backend -------------------------- Index: llvm/trunk/include/llvm/IR/Function.h =================================================================== --- llvm/trunk/include/llvm/IR/Function.h +++ llvm/trunk/include/llvm/IR/Function.h @@ -87,11 +87,14 @@ ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes - // HasLazyArguments is stored in Value::SubclassData. - /*bool HasLazyArguments;*/ - - // The Calling Convention is stored in Value::SubclassData. - /*CallingConv::ID CallingConvention;*/ + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3-6: CallingConvention + */ friend class SymbolTableListTraits; @@ -102,7 +105,7 @@ /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. bool hasLazyArguments() const { - return getSubclassDataFromValue() & 1; + return getSubclassDataFromValue() & (1<<0); } void CheckLazyArguments() const { if (hasLazyArguments()) @@ -162,11 +165,11 @@ /// 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(getSubclassDataFromValue() >> 2); + return static_cast(getSubclassDataFromValue() >> 3); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 3) | - (static_cast(CC) << 2)); + setValueSubclassData((getSubclassDataFromValue() & 7) | + (static_cast(CC) << 3)); } /// @brief Return the attribute list for this Function. @@ -448,12 +451,19 @@ bool arg_empty() const; bool hasPrefixData() const { - return getSubclassDataFromValue() & 2; + return getSubclassDataFromValue() & (1<<1); } Constant *getPrefixData() const; void setPrefixData(Constant *PrefixData); + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + /// 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 Index: llvm/trunk/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLLexer.cpp +++ llvm/trunk/lib/AsmParser/LLLexer.cpp @@ -573,6 +573,7 @@ KEYWORD(inteldialect); KEYWORD(gc); KEYWORD(prefix); + KEYWORD(prologue); KEYWORD(ccc); KEYWORD(fastcc); Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -3122,7 +3122,7 @@ /// FunctionHeader /// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs /// OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection -/// OptionalAlign OptGC OptionalPrefix +/// OptionalAlign OptGC OptionalPrefix OptionalPrologue bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { // Parse the linkage. LocTy LinkageLoc = Lex.getLoc(); @@ -3203,6 +3203,7 @@ bool UnnamedAddr; LocTy UnnamedAddrLoc; Constant *Prefix = nullptr; + Constant *Prologue = nullptr; Comdat *C; if (ParseArgumentList(ArgList, isVarArg) || @@ -3217,7 +3218,9 @@ (EatIfPresent(lltok::kw_gc) && ParseStringConstant(GC)) || (EatIfPresent(lltok::kw_prefix) && - ParseGlobalTypeAndValue(Prefix))) + ParseGlobalTypeAndValue(Prefix)) || + (EatIfPresent(lltok::kw_prologue) && + ParseGlobalTypeAndValue(Prologue))) return true; if (FuncAttrs.contains(Attribute::Builtin)) @@ -3318,6 +3321,7 @@ Fn->setComdat(C); if (!GC.empty()) Fn->setGC(GC.c_str()); Fn->setPrefixData(Prefix); + Fn->setPrologueData(Prologue); ForwardRefAttrGroups[Fn] = FwdRefAttrGrps; // Add all of the arguments we parsed to the function. Index: llvm/trunk/lib/AsmParser/LLToken.h =================================================================== --- llvm/trunk/lib/AsmParser/LLToken.h +++ llvm/trunk/lib/AsmParser/LLToken.h @@ -83,6 +83,7 @@ kw_inteldialect, kw_gc, kw_prefix, + kw_prologue, kw_c, kw_cc, kw_ccc, kw_fastcc, kw_coldcc, Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h @@ -143,6 +143,7 @@ std::vector > GlobalInits; std::vector > AliasInits; std::vector > FunctionPrefixes; + std::vector > FunctionPrologues; SmallVector InstsWithTBAATag; Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1152,10 +1152,12 @@ std::vector > GlobalInitWorklist; std::vector > AliasInitWorklist; std::vector > FunctionPrefixWorklist; + std::vector > FunctionPrologueWorklist; GlobalInitWorklist.swap(GlobalInits); AliasInitWorklist.swap(AliasInits); FunctionPrefixWorklist.swap(FunctionPrefixes); + FunctionPrologueWorklist.swap(FunctionPrologues); while (!GlobalInitWorklist.empty()) { unsigned ValID = GlobalInitWorklist.back().second; @@ -1197,6 +1199,19 @@ FunctionPrefixWorklist.pop_back(); } + while (!FunctionPrologueWorklist.empty()) { + unsigned ValID = FunctionPrologueWorklist.back().second; + if (ValID >= ValueList.size()) { + FunctionPrologues.push_back(FunctionPrologueWorklist.back()); + } else { + if (Constant *C = dyn_cast_or_null(ValueList[ValID])) + FunctionPrologueWorklist.back().first->setPrologueData(C); + else + return Error(BitcodeError::ExpectedConstant); + } + FunctionPrologueWorklist.pop_back(); + } + return std::error_code(); } @@ -2011,7 +2026,7 @@ } // FUNCTION: [type, callingconv, isproto, linkage, paramattr, // alignment, section, visibility, gc, unnamed_addr, - // dllstorageclass] + // prologuedata, dllstorageclass, comdat, prefixdata] case bitc::MODULE_CODE_FUNCTION: { if (Record.size() < 8) return Error(BitcodeError::InvalidRecord); @@ -2053,7 +2068,7 @@ UnnamedAddr = Record[9]; Func->setUnnamedAddr(UnnamedAddr); if (Record.size() > 10 && Record[10] != 0) - FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1)); + FunctionPrologues.push_back(std::make_pair(Func, Record[10]-1)); if (Record.size() > 11) Func->setDLLStorageClass(GetDecodedDLLStorageClass(Record[11])); @@ -2066,6 +2081,9 @@ Func->setComdat(ComdatList[ComdatID - 1]); } + if (Record.size() > 13 && Record[13] != 0) + FunctionPrefixes.push_back(std::make_pair(Func, Record[13]-1)); + ValueList.push_back(Func); // If this is a function with a body, remember the prototype we are Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -670,7 +670,8 @@ // Emit the function proto information. for (const Function &F : *M) { // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment, - // section, visibility, gc, unnamed_addr, prefix] + // section, visibility, gc, unnamed_addr, prologuedata, + // dllstorageclass, comdat, prefixdata] Vals.push_back(VE.getTypeID(F.getType())); Vals.push_back(F.getCallingConv()); Vals.push_back(F.isDeclaration()); @@ -681,10 +682,12 @@ 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); + Vals.push_back(F.hasPrologueData() ? (VE.getValueID(F.getPrologueData()) + 1) + : 0); Vals.push_back(getEncodedDLLStorageClass(F)); Vals.push_back(F.hasComdat() ? VE.getComdatID(F.getComdat()) : 0); + Vals.push_back(F.hasPrefixData() ? (VE.getValueID(F.getPrefixData()) + 1) + : 0); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); Index: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp +++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -85,10 +85,14 @@ for (const GlobalAlias &A : M.aliases()) if (!isa(A.getAliasee())) orderValue(A.getAliasee(), OM); - for (const Function &F : M) + for (const Function &F : M) { if (F.hasPrefixData()) if (!isa(F.getPrefixData())) orderValue(F.getPrefixData(), OM); + if (F.hasPrologueData()) + if (!isa(F.getPrologueData())) + orderValue(F.getPrologueData(), OM); + } OM.LastGlobalConstantID = OM.size(); // Initializers of GlobalValues are processed in @@ -264,9 +268,12 @@ predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack); for (const GlobalAlias &A : M.aliases()) predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack); - for (const Function &F : M) + for (const Function &F : M) { if (F.hasPrefixData()) predictValueUseListOrder(F.getPrefixData(), nullptr, OM, Stack); + if (F.hasPrologueData()) + predictValueUseListOrder(F.getPrologueData(), nullptr, OM, Stack); + } return Stack; } @@ -314,6 +321,11 @@ if (I->hasPrefixData()) EnumerateValue(I->getPrefixData()); + // Enumerate the prologue data constants. + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->hasPrologueData()) + EnumerateValue(I->getPrologueData()); + // 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()); Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -508,6 +508,10 @@ OutStreamer.GetCommentOS() << '\n'; } + // Emit the prefix data. + if (F->hasPrefixData()) + EmitGlobalConstant(F->getPrefixData()); + // Emit the CurrentFnSym. This is a virtual function to allow targets to // do their wild and crazy things as required. EmitFunctionEntryLabel(); @@ -528,9 +532,9 @@ HI.Handler->beginFunction(MF); } - // Emit the prefix data. - if (F->hasPrefixData()) - EmitGlobalConstant(F->getPrefixData()); + // Emit the prologue data. + if (F->hasPrologueData()) + EmitGlobalConstant(F->getPrologueData()); } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the Index: llvm/trunk/lib/IR/AsmWriter.cpp =================================================================== --- llvm/trunk/lib/IR/AsmWriter.cpp +++ llvm/trunk/lib/IR/AsmWriter.cpp @@ -101,6 +101,11 @@ if (F.hasPrefixData()) if (!isa(F.getPrefixData())) orderValue(F.getPrefixData(), OM); + + if (F.hasPrologueData()) + if (!isa(F.getPrologueData())) + orderValue(F.getPrologueData(), OM); + orderValue(&F, OM); if (F.isDeclaration()) @@ -1902,6 +1907,11 @@ Out << " prefix "; writeOperand(F->getPrefixData(), true); } + if (F->hasPrologueData()) { + Out << " prologue "; + writeOperand(F->getPrologueData(), true); + } + if (F->isDeclaration()) { Out << '\n'; } else { Index: llvm/trunk/lib/IR/Function.cpp =================================================================== --- llvm/trunk/lib/IR/Function.cpp +++ llvm/trunk/lib/IR/Function.cpp @@ -298,7 +298,7 @@ // Clear the lazy arguments bit. unsigned SDC = getSubclassDataFromValue(); - const_cast(this)->setValueSubclassData(SDC &= ~1); + const_cast(this)->setValueSubclassData(SDC &= ~(1<<0)); } size_t Function::arg_size() const { @@ -335,8 +335,9 @@ while (!BasicBlocks.empty()) BasicBlocks.begin()->eraseFromParent(); - // Prefix data is stored in a side table. + // Prefix and prologue data are stored in a side table. setPrefixData(nullptr); + setPrologueData(nullptr); } void Function::addAttribute(unsigned i, Attribute::AttrKind attr) { @@ -416,6 +417,10 @@ setPrefixData(SrcF->getPrefixData()); else setPrefixData(nullptr); + if (SrcF->hasPrologueData()) + setPrologueData(SrcF->getPrologueData()); + else + setPrologueData(nullptr); } /// getIntrinsicID - This method returns the ID number of the specified @@ -880,11 +885,40 @@ PDHolder->setOperand(0, PrefixData); else PDHolder = ReturnInst::Create(getContext(), PrefixData); - SCData |= 2; + SCData |= (1<<1); } else { delete PDHolder; PDMap.erase(this); - SCData &= ~2; + SCData &= ~(1<<1); } setValueSubclassData(SCData); } + +Constant *Function::getPrologueData() const { + assert(hasPrologueData()); + const LLVMContextImpl::PrologueDataMapTy &SOMap = + getContext().pImpl->PrologueDataMap; + assert(SOMap.find(this) != SOMap.end()); + return cast(SOMap.find(this)->second->getReturnValue()); +} + +void Function::setPrologueData(Constant *PrologueData) { + if (!PrologueData && !hasPrologueData()) + return; + + unsigned PDData = getSubclassDataFromValue(); + LLVMContextImpl::PrologueDataMapTy &PDMap = getContext().pImpl->PrologueDataMap; + ReturnInst *&PDHolder = PDMap[this]; + if (PrologueData) { + if (PDHolder) + PDHolder->setOperand(0, PrologueData); + else + PDHolder = ReturnInst::Create(getContext(), PrologueData); + PDData |= (1<<2); + } else { + delete PDHolder; + PDMap.erase(this); + PDData &= ~(1<<2); + } + setValueSubclassData(PDData); +} Index: llvm/trunk/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/trunk/lib/IR/LLVMContextImpl.h +++ llvm/trunk/lib/IR/LLVMContextImpl.h @@ -401,6 +401,12 @@ typedef DenseMap PrefixDataMapTy; PrefixDataMapTy PrefixDataMap; + /// \brief Mapping from a function to its prologue data, which is stored as + /// the operand of an unparented ReturnInst so that the prologue data has a + /// Use. + typedef DenseMap PrologueDataMapTy; + PrologueDataMapTy PrologueDataMap; + int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx); int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx); Index: llvm/trunk/lib/IR/TypeFinder.cpp =================================================================== --- llvm/trunk/lib/IR/TypeFinder.cpp +++ llvm/trunk/lib/IR/TypeFinder.cpp @@ -47,6 +47,9 @@ if (FI->hasPrefixData()) incorporateValue(FI->getPrefixData()); + if (FI->hasPrologueData()) + incorporateValue(FI->getPrologueData()); + // First incorporate the arguments. for (Function::const_arg_iterator AI = FI->arg_begin(), AE = FI->arg_end(); AI != AE; ++AI) Index: llvm/trunk/lib/Linker/LinkModules.cpp =================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp +++ llvm/trunk/lib/Linker/LinkModules.cpp @@ -1505,11 +1505,16 @@ if (DoNotLinkFromSource.count(SF)) continue; Function *DF = cast(ValueMap[SF]); - if (SF->hasPrefixData()) { - // Link in the prefix data. + + // Link in the prefix data. + if (SF->hasPrefixData()) DF->setPrefixData(MapValue( SF->getPrefixData(), ValueMap, RF_None, &TypeMap, &ValMaterializer)); - } + + // Link in the prologue data. + if (SF->hasPrologueData()) + DF->setPrologueData(MapValue( + SF->getPrologueData(), ValueMap, RF_None, &TypeMap, &ValMaterializer)); // Materialize if needed. if (std::error_code EC = SF->materialize()) Index: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp +++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp @@ -219,6 +219,9 @@ if (F->hasPrefixData()) MarkUsedGlobalsAsNeeded(F->getPrefixData()); + if (F->hasPrologueData()) + MarkUsedGlobalsAsNeeded(F->getPrologueData()); + 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) Index: llvm/trunk/test/CodeGen/X86/prefixdata.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/prefixdata.ll +++ llvm/trunk/test/CodeGen/X86/prefixdata.ll @@ -2,16 +2,17 @@ @i = linkonce_odr global i32 1 -; CHECK: f: -; CHECK-NEXT: .cfi_startproc +; CHECK: .type f,@function ; CHECK-NEXT: .long 1 +; CHECK-NEXT: # 0x1 +; CHECK-NEXT: f: define void @f() prefix i32 1 { ret void } -; CHECK: g: -; CHECK-NEXT: .cfi_startproc +; CHECK: .type g,@function ; CHECK-NEXT: .quad i +; CHECK-NEXT: g: define void @g() prefix i32* @i { ret void } Index: llvm/trunk/test/CodeGen/X86/prologuedata.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/prologuedata.ll +++ llvm/trunk/test/CodeGen/X86/prologuedata.ll @@ -0,0 +1,17 @@ +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s + +@i = linkonce_odr global i32 1 + +; CHECK: f: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .long 1 +define void @f() prologue i32 1 { + ret void +} + +; CHECK: g: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .quad i +define void @g() prologue i32* @i { + ret void +} Index: llvm/trunk/test/Feature/prologuedata.ll =================================================================== --- llvm/trunk/test/Feature/prologuedata.ll +++ llvm/trunk/test/Feature/prologuedata.ll @@ -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(){{.*}}prologue i32 1 +define void @f() prologue i32 1 { + ret void +} + +; CHECK: g(){{.*}}prologue i32* @i +define void @g() prologue i32* @i { + ret void +} Index: llvm/trunk/test/Linker/prefixdata.ll =================================================================== --- llvm/trunk/test/Linker/prefixdata.ll +++ llvm/trunk/test/Linker/prefixdata.ll @@ -1,9 +0,0 @@ -; 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 -} Index: llvm/trunk/test/Linker/prologuedata.ll =================================================================== --- llvm/trunk/test/Linker/prologuedata.ll +++ llvm/trunk/test/Linker/prologuedata.ll @@ -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() prologue i32* @i +define void @f() prologue i32* @i { + ret void +} Index: llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp =================================================================== --- llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp +++ llvm/trunk/tools/verify-uselistorder/verify-uselistorder.cpp @@ -197,9 +197,12 @@ map(G.getInitializer()); for (const GlobalAlias &A : M.aliases()) map(A.getAliasee()); - for (const Function &F : M) + for (const Function &F : M) { if (F.hasPrefixData()) map(F.getPrefixData()); + if (F.hasPrologueData()) + map(F.getPrologueData()); + } // Function bodies. for (const Function &F : M) { @@ -463,9 +466,12 @@ changeValueUseList(G.getInitializer()); for (GlobalAlias &A : M.aliases()) changeValueUseList(A.getAliasee()); - for (Function &F : M) + for (Function &F : M) { if (F.hasPrefixData()) changeValueUseList(F.getPrefixData()); + if (F.hasPrologueData()) + changeValueUseList(F.getPrologueData()); + } // Function bodies. for (Function &F : M) {