| //===--- SILNode.h - Node base class for SIL --------------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the SILNode class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SIL_SILNODE_H |
| #define SWIFT_SIL_SILNODE_H |
| |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/ADT/DenseMapInfo.h" |
| #include "llvm/Support/PointerLikeTypeTraits.h" |
| #include "swift/Basic/InlineBitfield.h" |
| #include "swift/Basic/LLVM.h" |
| #include <type_traits> |
| |
| namespace swift { |
| |
| class SILBasicBlock; |
| class SILFunction; |
| class SILInstruction; |
| class SILModule; |
| class SingleValueInstruction; |
| class ValueBase; |
| |
| /// An enumeration which contains values for all the nodes in SILNodes.def. |
| /// Other enumerators, like ValueKind and SILInstructionKind, ultimately |
| /// take their values from this enumerator. |
| enum class SILNodeKind { |
| #define NODE(ID, PARENT) \ |
| ID, |
| #define NODE_RANGE(ID, FIRST, LAST) \ |
| First_##ID = FIRST, \ |
| Last_##ID = LAST, |
| #include "swift/SIL/SILNodes.def" |
| }; |
| |
| enum { NumSILNodeKindBits = |
| countBitsUsed(static_cast<unsigned>(SILNodeKind::Last_SILNode)) }; |
| |
| enum class SILInstructionKind : std::underlying_type<SILNodeKind>::type; |
| |
| /// A SILNode is a node in the use-def graph of a SILFunction. It is |
| /// either an instruction or a defined value which can be used by an |
| /// instruction. A defined value may be an instruction result, a basic |
| /// block argument, or the special 'undef' value. |
| /// |
| /// The 'node' intuition is slightly imprecise because a single instruction |
| /// may be composed of multiple SILNodes: one for the instruction itself |
| /// and one for each value it produces. When an instruction kind always |
| /// produces exactly one value, the cast machinery (isa, cast, and dyn_cast) |
| /// works to make both nodes appear to be the same object: there is a value |
| /// kind exactly equal to the instruction kind and the value node can be |
| /// directly cast to the instruction's class. When an instruction kind |
| /// never produces values, it has no corresponding value kind, and it is |
| /// a compile-time error to attempt to cast a value node to the instruction |
| /// class. When an instruction kind can have multiple values (not yet |
| /// implemented), its value nodes have a different kind from the |
| /// instruction kind and it is a static error to attempt to cast a value |
| /// node to the instruction kind. |
| /// |
| /// Another way of interpreting SILNode is that there is a SILNode for |
| /// everything that can be numbered in SIL assembly (plus 'undef', which |
| /// is not conventionally numbered). Instructions without results are |
| /// still numbered in SIL in order to describe the users lists of an |
| /// instruction or argument. Instructions with multiple results are |
| /// numbered using their first result. |
| /// |
| /// SILNode is a base class of both SILInstruction and ValueBase. |
| /// Because there can be multiple SILNodes within a single instruction |
| /// object, some care must be taken when working with SILNode pointers. |
| /// These precautions only apply to SILNode* and not its subclasses. |
| /// |
| /// - There may have multiple SILNode* values that refer to the same |
| /// instruction. Data structures and algorithms that rely on uniqueness of a |
| /// SILNode* should generally make sure that they're working with the |
| /// representative SILNode*; see getRepresentativeSILNodeInObject(). |
| /// |
| /// - Do not use builtin C++ casts to downcast a SILNode*. A static_cast |
| /// from SILNode* to SILInstruction* only works if the referenced |
| /// SILNode is the base subobject of the object's SILInstruction |
| /// subobject. If the SILNode is actually the base subobject of a |
| /// ValueBase subobject, the cast will yield a corrupted value. |
| /// Always use the LLVM casts (cast<>, dyn_cast<>, etc.) instead. |
| class alignas(8) SILNode { |
| public: |
| enum { NumVOKindBits = 3 }; |
| enum { NumStoreOwnershipQualifierBits = 2 }; |
| enum { NumLoadOwnershipQualifierBits = 2 }; |
| enum { NumAssignOwnershipQualifierBits = 2 }; |
| enum { NumSILAccessKindBits = 2 }; |
| enum { NumSILAccessEnforcementBits = 2 }; |
| |
| protected: |
| union { uint64_t OpaqueBits; |
| |
| SWIFT_INLINE_BITFIELD_BASE(SILNode, bitmax(NumSILNodeKindBits,8)+1+1, |
| Kind : bitmax(NumSILNodeKindBits,8), |
| StorageLoc : 1, |
| IsRepresentativeNode : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(ValueBase, SILNode); |
| |
| SWIFT_INLINE_BITFIELD(SILArgument, ValueBase, NumVOKindBits, |
| VOKind : NumVOKindBits |
| ); |
| |
| // No MultipleValueInstructionResult subclass needs inline bits right now, |
| // therefore let's naturally align and size the Index for speed. |
| SWIFT_INLINE_BITFIELD_FULL(MultipleValueInstructionResult, ValueBase, |
| NumVOKindBits+32, |
| VOKind : NumVOKindBits, |
| : NumPadBits, |
| Index : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(SILInstruction, SILNode); |
| |
| // Special handling for UnaryInstructionWithTypeDependentOperandsBase |
| SWIFT_INLINE_BITFIELD(IBWTO, SILNode, 64-NumSILNodeBits, |
| // DO NOT allocate bits at the front! |
| // IBWTO is a template, and templates must allocate bits from back to front |
| // so that "normal" subclassing can allocate bits from front to back. |
| // If you update this, then you must update the IBWTO_BITFIELD macros. |
| |
| /*pad*/ : 32-NumSILNodeBits, |
| |
| // Total number of operands of this instruction. |
| // It is number of type dependent operands + 1. |
| NumOperands : 32; |
| template<SILInstructionKind Kind, typename, typename, typename...> |
| friend class InstructionBaseWithTrailingOperands |
| ); |
| |
| #define IBWTO_BITFIELD(T, U, C, ...) \ |
| SWIFT_INLINE_BITFIELD_TEMPLATE(T, U, (C), 32, __VA_ARGS__) |
| #define IBWTO_BITFIELD_EMPTY(T, U) \ |
| SWIFT_INLINE_BITFIELD_EMPTY(T, U) |
| |
| #define UIWTDOB_BITFIELD(T, U, C, ...) \ |
| IBWTO_BITFIELD(T, U, (C), __VA_ARGS__) |
| #define UIWTDOB_BITFIELD_EMPTY(T, U) \ |
| IBWTO_BITFIELD_EMPTY(T, U) |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(SingleValueInstruction, SILInstruction); |
| SWIFT_INLINE_BITFIELD_EMPTY(DeallocationInst, SILInstruction); |
| SWIFT_INLINE_BITFIELD_EMPTY(LiteralInst, SingleValueInstruction); |
| SWIFT_INLINE_BITFIELD_EMPTY(AllocationInst, SingleValueInstruction); |
| |
| // Ensure that StructInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(StructInst, SingleValueInstruction); |
| |
| // Ensure that TupleInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(TupleInst, SingleValueInstruction); |
| |
| IBWTO_BITFIELD(ObjectInst, SingleValueInstruction, |
| 32-NumSingleValueInstructionBits, |
| NumBaseElements : 32-NumSingleValueInstructionBits |
| ); |
| |
| IBWTO_BITFIELD(SelectEnumInstBase, SingleValueInstruction, 1, |
| HasDefault : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(IntegerLiteralInst, LiteralInst, 32, |
| : NumPadBits, |
| numBits : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(FloatLiteralInst, LiteralInst, 32, |
| : NumPadBits, |
| numBits : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(StringLiteralInst, LiteralInst, 2+32, |
| TheEncoding : 2, |
| : NumPadBits, |
| Length : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(DeallocRefInst, DeallocationInst, 1, |
| OnStack : 1 |
| ); |
| |
| // Ensure that AllocBoxInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(AllocBoxInst, AllocationInst); |
| // Ensure that AllocExistentialBoxInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(AllocExistentialBoxInst, AllocationInst); |
| SWIFT_INLINE_BITFIELD_FULL(AllocStackInst, AllocationInst, |
| 64-NumAllocationInstBits, |
| NumOperands : 32-NumAllocationInstBits, |
| VarInfo : 32 |
| ); |
| IBWTO_BITFIELD(AllocRefInstBase, AllocationInst, 32-NumAllocationInstBits, |
| ObjC : 1, |
| OnStack : 1, |
| NumTailTypes : 32-1-1-NumAllocationInstBits |
| ); |
| static_assert(32-1-1-NumAllocationInstBits >= 16, "Reconsider bitfield use?"); |
| |
| UIWTDOB_BITFIELD_EMPTY(AllocValueBufferInst, AllocationInst); |
| |
| // TODO: Sort the following in SILNodes.def order |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(NonValueInstruction, SILInstruction); |
| SWIFT_INLINE_BITFIELD(RefCountingInst, NonValueInstruction, 1, |
| atomicity : 1 |
| ); |
| |
| // Ensure that BindMemoryInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(BindMemoryInst, NonValueInstruction); |
| |
| // Ensure that MarkFunctionEscapeInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(MarkFunctionEscapeInst, NonValueInstruction); |
| |
| // Ensure that MetatypeInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(MetatypeInst, SingleValueInstruction); |
| |
| SWIFT_INLINE_BITFIELD(CopyAddrInst, NonValueInstruction, 1+1, |
| /// IsTakeOfSrc - True if ownership will be taken from the value at the |
| /// source memory location. |
| IsTakeOfSrc : 1, |
| |
| /// IsInitializationOfDest - True if this is the initialization of the |
| /// uninitialized destination memory location. |
| IsInitializationOfDest : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(LoadReferenceInstBaseT, NonValueInstruction, 1, |
| IsTake : 1; |
| template<SILInstructionKind K> |
| friend class LoadReferenceInstBase |
| ); |
| |
| SWIFT_INLINE_BITFIELD(StoreReferenceInstBaseT, NonValueInstruction, 1, |
| IsInitializationOfDest : 1; |
| template<SILInstructionKind K> |
| friend class StoreReferenceInstBase |
| ); |
| |
| SWIFT_INLINE_BITFIELD(BeginAccessInst, SingleValueInstruction, |
| NumSILAccessKindBits+NumSILAccessEnforcementBits |
| + 1 + 1, |
| AccessKind : NumSILAccessKindBits, |
| Enforcement : NumSILAccessEnforcementBits, |
| NoNestedConflict : 1, |
| FromBuiltin : 1 |
| ); |
| SWIFT_INLINE_BITFIELD(BeginUnpairedAccessInst, NonValueInstruction, |
| NumSILAccessKindBits + NumSILAccessEnforcementBits |
| + 1 + 1, |
| AccessKind : NumSILAccessKindBits, |
| Enforcement : NumSILAccessEnforcementBits, |
| NoNestedConflict : 1, |
| FromBuiltin : 1); |
| |
| SWIFT_INLINE_BITFIELD(EndAccessInst, NonValueInstruction, 1, |
| Aborting : 1 |
| ); |
| SWIFT_INLINE_BITFIELD(EndUnpairedAccessInst, NonValueInstruction, |
| NumSILAccessEnforcementBits + 1 + 1, |
| Enforcement : NumSILAccessEnforcementBits, |
| Aborting : 1, |
| FromBuiltin : 1); |
| |
| SWIFT_INLINE_BITFIELD(StoreInst, NonValueInstruction, |
| NumStoreOwnershipQualifierBits, |
| OwnershipQualifier : NumStoreOwnershipQualifierBits |
| ); |
| SWIFT_INLINE_BITFIELD(LoadInst, SingleValueInstruction, |
| NumLoadOwnershipQualifierBits, |
| OwnershipQualifier : NumLoadOwnershipQualifierBits |
| ); |
| SWIFT_INLINE_BITFIELD(AssignInst, NonValueInstruction, |
| NumAssignOwnershipQualifierBits, |
| OwnershipQualifier : NumAssignOwnershipQualifierBits |
| ); |
| SWIFT_INLINE_BITFIELD(AssignByWrapperInst, NonValueInstruction, |
| NumAssignOwnershipQualifierBits, |
| OwnershipQualifier : NumAssignOwnershipQualifierBits |
| ); |
| |
| SWIFT_INLINE_BITFIELD(UncheckedOwnershipConversionInst,SingleValueInstruction, |
| NumVOKindBits, |
| Kind : NumVOKindBits |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(TupleExtractInst, SingleValueInstruction, 32, |
| : NumPadBits, |
| FieldNo : 32 |
| ); |
| SWIFT_INLINE_BITFIELD_FULL(TupleElementAddrInst, SingleValueInstruction, 32, |
| : NumPadBits, |
| FieldNo : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(RefElementAddrInst, SingleValueInstruction, 1, |
| Immutable : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(RefTailAddrInst, SingleValueInstruction, 1, |
| Immutable : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(EndCOWMutationInst, NonValueInstruction, 1, |
| KeepUnique : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL_TEMPLATE(FieldIndexCacheBase, |
| SingleValueInstruction, 32, |
| : NumPadBits, |
| FieldIndex : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(MethodInst, SingleValueInstruction); |
| // Ensure that WitnessMethodInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(WitnessMethodInst, MethodInst); |
| UIWTDOB_BITFIELD_EMPTY(ObjCMethodInst, MethodInst); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(ConversionInst, SingleValueInstruction); |
| SWIFT_INLINE_BITFIELD(PointerToAddressInst, ConversionInst, 1+1, |
| IsStrict : 1, |
| IsInvariant : 1 |
| ); |
| |
| UIWTDOB_BITFIELD(ConvertFunctionInst, ConversionInst, 1, |
| WithoutActuallyEscaping : 1); |
| UIWTDOB_BITFIELD_EMPTY(PointerToThinFunctionInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(UnconditionalCheckedCastInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(UpcastInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(UncheckedRefCastInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(UncheckedAddrCastInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(UncheckedTrivialBitCastInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(UncheckedBitwiseCastInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(ThinToThickFunctionInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(UnconditionalCheckedCastValueInst, ConversionInst); |
| UIWTDOB_BITFIELD_EMPTY(InitExistentialAddrInst, SingleValueInstruction); |
| UIWTDOB_BITFIELD_EMPTY(InitExistentialValueInst, SingleValueInstruction); |
| UIWTDOB_BITFIELD_EMPTY(InitExistentialRefInst, SingleValueInstruction); |
| UIWTDOB_BITFIELD_EMPTY(InitExistentialMetatypeInst, SingleValueInstruction); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(TermInst, SILInstruction); |
| UIWTDOB_BITFIELD_EMPTY(CheckedCastBranchInst, SingleValueInstruction); |
| UIWTDOB_BITFIELD_EMPTY(CheckedCastValueBranchInst, SingleValueInstruction); |
| |
| // Ensure that BranchInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(BranchInst, TermInst); |
| // Ensure that YieldInst bitfield does not overflow. |
| IBWTO_BITFIELD_EMPTY(YieldInst, TermInst); |
| IBWTO_BITFIELD(CondBranchInst, TermInst, 32-NumTermInstBits, |
| NumTrueArgs : 32-NumTermInstBits |
| ); |
| IBWTO_BITFIELD(SwitchValueInst, TermInst, 1, |
| HasDefault : 1 |
| ); |
| |
| // Special handling for SwitchEnumInstBase. |
| // |
| // We assume all subsequent SwitchEnumBit uses do not use any further bits. |
| SWIFT_INLINE_BITFIELD(SEIBase, TermInst, 32-NumTermInstBits, |
| // Does this switch enum inst have a default block. |
| HasDefault : 1, |
| // Number of cases |
| NumCases : 31 - NumTermInstBits; |
| template <typename BaseTy> |
| friend class SwitchEnumInstBase |
| ); |
| |
| #define SEIB_BITFIELD_EMPTY(T, U) \ |
| IBWTO_BITFIELD_EMPTY(T, U) |
| |
| SEIB_BITFIELD_EMPTY(SwitchEnumInst, SEIBase); |
| SEIB_BITFIELD_EMPTY(SwitchEnumAddrInst, SEIBase); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(MultipleValueInstruction, SILInstruction); |
| |
| SWIFT_INLINE_BITFIELD(BeginCOWMutationInst, MultipleValueInstruction, 1, |
| Native : 1 |
| ); |
| |
| } Bits; |
| |
| enum class SILNodeStorageLocation : uint8_t { Value, Instruction }; |
| |
| enum class IsRepresentative : bool { |
| No = false, |
| Yes = true, |
| }; |
| |
| private: |
| |
| SILNodeStorageLocation getStorageLoc() const { |
| return SILNodeStorageLocation(Bits.SILNode.StorageLoc); |
| } |
| |
| const SILNode *getRepresentativeSILNodeSlowPath() const; |
| |
| protected: |
| SILNode(SILNodeKind kind, SILNodeStorageLocation storageLoc, |
| IsRepresentative isRepresentative) { |
| Bits.OpaqueBits = 0; |
| Bits.SILNode.Kind = unsigned(kind); |
| Bits.SILNode.StorageLoc = unsigned(storageLoc); |
| Bits.SILNode.IsRepresentativeNode = unsigned(isRepresentative); |
| } |
| |
| public: |
| /// Does the given kind of node inherit from multiple multiple SILNode base |
| /// classes? |
| /// |
| /// This enables one to know if their is a diamond in the inheritence |
| /// hierarchy for this SILNode. |
| static bool hasMultipleSILNodeBases(SILNodeKind kind) { |
| // Currently only SingleValueInstructions. Note that multi-result |
| // instructions shouldn't return true for this. |
| return kind >= SILNodeKind::First_SingleValueInstruction && |
| kind <= SILNodeKind::Last_SingleValueInstruction; |
| } |
| |
| /// Is this SILNode the representative SILNode subobject in this object? |
| bool isRepresentativeSILNodeInObject() const { |
| return Bits.SILNode.IsRepresentativeNode; |
| } |
| |
| /// Return a pointer to the representative SILNode subobject in this object. |
| SILNode *getRepresentativeSILNodeInObject() { |
| if (isRepresentativeSILNodeInObject()) |
| return this; |
| return const_cast<SILNode *>(getRepresentativeSILNodeSlowPath()); |
| } |
| |
| const SILNode *getRepresentativeSILNodeInObject() const { |
| if (isRepresentativeSILNodeInObject()) |
| return this; |
| return getRepresentativeSILNodeSlowPath(); |
| } |
| |
| LLVM_ATTRIBUTE_ALWAYS_INLINE |
| SILNodeKind getKind() const { |
| return SILNodeKind(Bits.SILNode.Kind); |
| } |
| |
| /// Return the SILNodeKind of this node's representative SILNode. |
| SILNodeKind getKindOfRepresentativeSILNodeInObject() const { |
| return getRepresentativeSILNodeInObject()->getKind(); |
| } |
| |
| /// If this is a SILArgument or a SILInstruction get its parent basic block, |
| /// otherwise return null. |
| SILBasicBlock *getParentBlock() const; |
| |
| /// If this is a SILArgument or a SILInstruction get its parent function, |
| /// otherwise return null. |
| SILFunction *getFunction() const; |
| |
| /// If this is a SILArgument or a SILInstruction get its parent module, |
| /// otherwise return null. |
| SILModule *getModule() const; |
| |
| /// Pretty-print the node. If the node is an instruction, the output |
| /// will be valid SIL assembly; otherwise, it will be an arbitrary |
| /// format suitable for debugging. |
| void print(raw_ostream &OS) const; |
| void dump() const; |
| |
| /// Pretty-print the node in context, preceded by its operands (if the |
| /// value represents the result of an instruction) and followed by its |
| /// users. |
| void printInContext(raw_ostream &OS) const; |
| void dumpInContext() const; |
| |
| // Cast to SingleValueInstruction. This is an implementation detail |
| // of the cast machinery. At a high level, all you need to know is to |
| // never use static_cast to downcast a SILNode. |
| SingleValueInstruction *castToSingleValueInstruction(); |
| const SingleValueInstruction *castToSingleValueInstruction() const { |
| return const_cast<SILNode*>(this)->castToSingleValueInstruction(); |
| } |
| |
| static bool classof(const SILNode *node) { |
| return true; |
| } |
| }; |
| |
| inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, |
| const SILNode &node) { |
| node.print(OS); |
| return OS; |
| } |
| |
| template <class To> struct cast_sil_node_is_unambiguous { |
| // The only ambiguity right now is between the value and instruction |
| // nodes on a SingleValueInstruction. |
| static constexpr bool value = |
| // If the destination type isn't a subclass of ValueBase or |
| // SILInstruction, there's no ambiguity. |
| (!std::is_base_of<SILInstruction, To>::value && |
| !std::is_base_of<ValueBase, To>::value) |
| |
| // If the destination type is a proper subclass of ValueBase |
| // that isn't a subclass of SILInstruction, there's no ambiguity. |
| || (std::is_base_of<ValueBase, To>::value && |
| !std::is_same<ValueBase, To>::value && |
| !std::is_base_of<SILInstruction, To>::value) |
| |
| // If the destination type is a proper subclass of SILInstruction |
| // that isn't a subclass of ValueBase, there's no ambiguity. |
| || (std::is_base_of<SILInstruction, To>::value && |
| !std::is_same<SILInstruction, To>::value && |
| !std::is_base_of<ValueBase, To>::value); |
| }; |
| |
| template <class To, |
| bool IsSingleValueInstruction = |
| std::is_base_of<SingleValueInstruction, To>::value, |
| bool IsKnownUnambiguous = |
| cast_sil_node_is_unambiguous<To>::value> |
| struct cast_sil_node; |
| |
| // If all complete objects of the destination type are known to only |
| // contain a single node, we can just use a static_cast. |
| template <class To> |
| struct cast_sil_node<To, /*single value*/ false, /*unambiguous*/ true> { |
| static To *doit(SILNode *node) { |
| return &static_cast<To&>(*node); |
| } |
| }; |
| |
| // If we're casting to a subclass of SingleValueInstruction, we don't |
| // need to dynamically check whether the node is an SVI. In fact, |
| // we can't, because the static_cast will be ambiguous. |
| template <class To> |
| struct cast_sil_node<To, /*single value*/ true, /*unambiguous*/ false> { |
| static To *doit(SILNode *node) { |
| auto svi = node->castToSingleValueInstruction(); |
| return &static_cast<To&>(*svi); |
| } |
| }; |
| |
| // Otherwise, we need to dynamically check which case we're in. |
| template <class To> |
| struct cast_sil_node<To, /*single value*/ false, /*unambiguous*/ false> { |
| static To *doit(SILNode *node) { |
| // If the node isn't dynamically a SingleValueInstruction, then this |
| // is indeed the SILNode subobject that's statically observable in To. |
| if (!SILNode::hasMultipleSILNodeBases(node->getKind())) { |
| return &static_cast<To&>(*node); |
| } |
| |
| auto svi = node->castToSingleValueInstruction(); |
| return &static_cast<To&>(*svi); |
| } |
| }; |
| |
| } // end namespace swift |
| |
| namespace llvm { |
| |
| /// Completely take over cast<>'ing from SILNode*. A static_cast to |
| /// ValueBase* or SILInstruction* can be quite wrong. |
| template <class To> |
| struct cast_convert_val<To, swift::SILNode*, swift::SILNode*> { |
| using ret_type = typename cast_retty<To, swift::SILNode*>::ret_type; |
| static ret_type doit(swift::SILNode *node) { |
| return swift::cast_sil_node<To>::doit(node); |
| } |
| }; |
| template <class To> |
| struct cast_convert_val<To, const swift::SILNode *, const swift::SILNode *> { |
| using ret_type = typename cast_retty<To, const swift::SILNode*>::ret_type; |
| static ret_type doit(const swift::SILNode *node) { |
| return swift::cast_sil_node<To>::doit(const_cast<swift::SILNode*>(node)); |
| } |
| }; |
| |
| // We don't support casting from SILNode references yet. |
| template <class To, class From> |
| struct cast_convert_val<To, swift::SILNode, From>; |
| template <class To, class From> |
| struct cast_convert_val<To, const swift::SILNode, From>; |
| |
| /// ValueBase * is always at least eight-byte aligned; make the three tag bits |
| /// available through PointerLikeTypeTraits. |
| template<> |
| struct PointerLikeTypeTraits<swift::SILNode *> { |
| public: |
| static inline void *getAsVoidPointer(swift::SILNode *I) { |
| return (void*)I; |
| } |
| static inline swift::SILNode *getFromVoidPointer(void *P) { |
| return (swift::SILNode *)P; |
| } |
| enum { NumLowBitsAvailable = 3 }; |
| }; |
| |
| } // end namespace llvm |
| |
| #endif |