diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 2855fdcc2b1..0b881dc6889 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -549,7 +549,47 @@ public: } }; +/// BlockAddress - The address of a basic block. +/// +class BlockAddress : public Constant { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t s) { return User::operator new(s, 2); } + BlockAddress(Function *F, BasicBlock *BB); +public: + /// get - Return a BlockAddress for the specified function and basic block. + static BlockAddress *get(Function *F, BasicBlock *BB); + + /// get - Return a BlockAddress for the specified basic block. The basic + /// block must be embedded into a function. + static BlockAddress *get(BasicBlock *BB); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + Function *getFunction() const { return (Function*)Op<0>().get(); } + BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BlockAddress *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == BlockAddressVal; + } +}; +template <> +struct OperandTraits : public FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Constant) + +//===----------------------------------------------------------------------===// /// ConstantExpr - a constant value that is initialized with an expression using /// other constant values. /// diff --git a/include/llvm/Value.h b/include/llvm/Value.h index c09fdfb8a87..b485524b05b 100644 --- a/include/llvm/Value.h +++ b/include/llvm/Value.h @@ -210,6 +210,7 @@ public: GlobalAliasVal, // This is an instance of GlobalAlias GlobalVariableVal, // This is an instance of GlobalVariable UndefValueVal, // This is an instance of UndefValue + BlockAddressVal, // This is an instance of BlockAddress ConstantExprVal, // This is an instance of ConstantExpr ConstantAggregateZeroVal, // This is an instance of ConstantAggregateNull ConstantIntVal, // This is an instance of ConstantInt diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 02c33528ecf..c2402da257b 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -987,7 +987,7 @@ Constant *ConstantVector::getSplatValue() { return Elt; } -//---- ConstantPointerNull::get() implementation... +//---- ConstantPointerNull::get() implementation. // ConstantPointerNull *ConstantPointerNull::get(const PointerType *Ty) { @@ -1004,23 +1004,90 @@ void ConstantPointerNull::destroyConstant() { } -//---- UndefValue::get() implementation... +//---- UndefValue::get() implementation. // UndefValue *UndefValue::get(const Type *Ty) { - // Implicitly locked. return Ty->getContext().pImpl->UndefValueConstants.getOrCreate(Ty, 0); } // destroyConstant - Remove the constant from the constant table. // void UndefValue::destroyConstant() { - // Implicitly locked. getType()->getContext().pImpl->UndefValueConstants.remove(this); destroyConstantImpl(); } -//---- ConstantExpr::get() implementations... +//---- BlockAddress::get() implementation. +// + +BlockAddress *BlockAddress::get(BasicBlock *BB) { + assert(BB->getParent() != 0 && "Block must have a parent"); + return get(BB->getParent(), BB); +} + +BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) { + BlockAddress *&BA = + F->getContext().pImpl->BlockAddresses[std::make_pair(F, BB)]; + if (BA == 0) + BA = new BlockAddress(F, BB); + + assert(BA->getFunction() == F && "Basic block moved between functions"); + return BA; +} + +BlockAddress::BlockAddress(Function *F, BasicBlock *BB) +: Constant(Type::getInt8PtrTy(F->getContext()), Value::BlockAddressVal, + &Op<0>(), 2) { + Op<0>() = F; + Op<1>() = BB; +} + + +// destroyConstant - Remove the constant from the constant table. +// +void BlockAddress::destroyConstant() { + getFunction()->getType()->getContext().pImpl + ->BlockAddresses.erase(std::make_pair(getFunction(), getBasicBlock())); + destroyConstantImpl(); +} + +void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { + // This could be replacing either the Basic Block or the Function. In either + // case, we have to remove the map entry. + Function *NewF = getFunction(); + BasicBlock *NewBB = getBasicBlock(); + + if (U == &Op<0>()) + NewF = cast(To); + else + NewBB = cast(To); + + // See if the 'new' entry already exists, if not, just update this in place + // and return early. + BlockAddress *&NewBA = + getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)]; + if (NewBA == 0) { + // Remove the old entry, this can't cause the map to rehash (just a + // tombstone will get added). + getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), + getBasicBlock())); + NewBA = this; + Op<0>() = NewF; + Op<1>() = NewBB; + return; + } + + // Otherwise, I do need to replace this with an existing value. + assert(NewBA != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement. + uncheckedReplaceAllUsesWith(NewBA); + + destroyConstant(); +} + +//---- ConstantExpr::get() implementations. // /// This is a utility function to handle folding of casts and lookup of the @@ -1838,7 +1905,7 @@ const char *ConstantExpr::getOpcodeName() const { /// single invocation handles all 1000 uses. Handling them one at a time would /// work, but would be really slow because it would have to unique each updated /// array instance. - +/// void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index 68bd01f1ef4..fd39b0c71b6 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -126,6 +126,7 @@ public: ConstantUniqueMap UndefValueConstants; + DenseMap , BlockAddress*> BlockAddresses; ConstantUniqueMap ExprConstants; ConstantInt *TheTrueVal;