From 837e04a8bf13712a4a8ae279daab65a048b21f7d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 28 Oct 2009 05:24:40 +0000 Subject: [PATCH] bitcode writer support for blockaddress. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85376 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/LLVMBitCodes.h | 3 +- lib/Bitcode/Writer/BitcodeWriter.cpp | 7 ++++ lib/Bitcode/Writer/ValueEnumerator.cpp | 44 +++++++++++++++++++++----- lib/Bitcode/Writer/ValueEnumerator.h | 9 ++++++ 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index abe9966aa0a..c037399b96d 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -138,7 +138,8 @@ namespace bitc { CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred] CST_CODE_INLINEASM = 18, // INLINEASM: [sideeffect,asmstr,conststr] CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval] - CST_CODE_CE_INBOUNDS_GEP = 20 // INBOUNDS_GEP: [n x operands] + CST_CODE_CE_INBOUNDS_GEP = 20,// INBOUNDS_GEP: [n x operands] + CST_CODE_BLOCKADDRESS = 21 // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#] }; /// CastOpcodes - These are values used in the bitcode files to encode which diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 98f782ff5ba..af0b8acd44c 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -853,6 +853,13 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(CE->getPredicate()); break; } + } else if (const BlockAddress *BA = dyn_cast(C)) { + assert(BA->getFunction() == BA->getBasicBlock()->getParent() && + "Malformed blockaddress"); + Code = bitc::CST_CODE_BLOCKADDRESS; + Record.push_back(VE.getTypeID(BA->getFunction()->getType())); + Record.push_back(VE.getValueID(BA->getFunction())); + Record.push_back(VE.getGlobalBasicBlockID(BA->getBasicBlock())); } else { llvm_unreachable("Unknown constant!"); } diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index 95746eee03b..d840d4ae9fe 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -223,7 +223,9 @@ void ValueEnumerator::EnumerateMetadata(const MetadataBase *MD) { EnumerateType(Type::getVoidTy(MD->getContext())); } return; - } else if (const NamedMDNode *N = dyn_cast(MD)) { + } + + if (const NamedMDNode *N = dyn_cast(MD)) { for(NamedMDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end(); I != E; ++I) { MetadataBase *M = *I; @@ -274,7 +276,8 @@ void ValueEnumerator::EnumerateValue(const Value *V) { // graph that don't go through a global variable. for (User::const_op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I) - EnumerateValue(*I); + if (!isa(*I)) // Don't enumerate BB operand to BlockAddress. + EnumerateValue(*I); // Finally, add the value. Doing this could make the ValueID reference be // dangling, don't reuse it. @@ -320,15 +323,20 @@ void ValueEnumerator::EnumerateOperandType(const Value *V) { // This constant may have operands, make sure to enumerate the types in // them. - for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) - EnumerateOperandType(C->getOperand(i)); + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { + const User *Op = C->getOperand(i); + + // Don't enumerate basic blocks here, this happens as operands to + // blockaddress. + if (isa(Op)) continue; + + EnumerateOperandType(cast(Op)); + } if (const MDNode *N = dyn_cast(V)) { - for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { - Value *Elem = N->getElement(i); - if (Elem) + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) + if (Value *Elem = N->getElement(i)) EnumerateOperandType(Elem); - } } } else if (isa(V) || isa(V)) EnumerateValue(V); @@ -397,3 +405,23 @@ void ValueEnumerator::purgeFunction() { Values.resize(NumModuleValues); BasicBlocks.clear(); } + +static void IncorporateFunctionInfoGlobalBBIDs(const Function *F, + DenseMap &IDMap) { + unsigned Counter = 0; + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + IDMap[BB] = ++Counter; +} + +/// getGlobalBasicBlockID - This returns the function-specific ID for the +/// specified basic block. This is relatively expensive information, so it +/// should only be used by rare constructs such as address-of-label. +unsigned ValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { + unsigned &Idx = GlobalBasicBlockIDs[BB]; + if (Idx != 0) + return Idx-1; + + IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); + return getGlobalBasicBlockID(BB); +} + diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h index da63dde2a27..3c83e356956 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.h +++ b/lib/Bitcode/Writer/ValueEnumerator.h @@ -53,6 +53,10 @@ private: AttributeMapType AttributeMap; std::vector Attributes; + /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by + /// the "getGlobalBasicBlockID" method. + mutable DenseMap GlobalBasicBlockIDs; + typedef DenseMap InstructionMapType; InstructionMapType InstructionMap; unsigned InstructionCount; @@ -106,6 +110,11 @@ public: const std::vector &getAttributes() const { return Attributes; } + + /// getGlobalBasicBlockID - This returns the function-specific ID for the + /// specified basic block. This is relatively expensive information, so it + /// should only be used by rare constructs such as address-of-label. + unsigned getGlobalBasicBlockID(const BasicBlock *BB) const; /// incorporateFunction/purgeFunction - If you'd like to deal with a function, /// use these two methods to get its data into the ValueEnumerator!