//===--- SILValue.cpp - Implementation for SILValue -----------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "swift/SIL/SILValue.h" #include "ValueOwnershipKindClassifier.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuiltinVisitor.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILVisitor.h" #include "llvm/ADT/StringSwitch.h" using namespace swift; //===----------------------------------------------------------------------===// // Check SILNode Type Properties //===----------------------------------------------------------------------===// /// These are just for performance and verification. If one needs to make /// changes that cause the asserts the fire, please update them. The purpose is /// to prevent these predicates from changing values by mistake. //===----------------------------------------------------------------------===// // Check SILValue Type Properties //===----------------------------------------------------------------------===// /// These are just for performance and verification. If one needs to make /// changes that cause the asserts the fire, please update them. The purpose is /// to prevent these predicates from changing values by mistake. static_assert(std::is_standard_layout::value, "Expected SILValue to be standard layout"); static_assert(sizeof(SILValue) == sizeof(uintptr_t), "SILValue should be pointer sized"); //===----------------------------------------------------------------------===// // Utility Methods //===----------------------------------------------------------------------===// void ValueBase::replaceAllUsesWith(ValueBase *RHS) { assert(this != RHS && "Cannot RAUW a value with itself"); while (!use_empty()) { Operand *Op = *use_begin(); Op->set(RHS); } } void ValueBase::replaceAllUsesWithUndef() { SILModule *Mod = getModule(); if (!Mod) { llvm_unreachable("replaceAllUsesWithUndef can only be used on ValueBase " "that have access to the parent module."); } while (!use_empty()) { Operand *Op = *use_begin(); Op->set(SILUndef::get(Op->get()->getType(), Mod)); } } SILInstruction *ValueBase::getDefiningInstruction() { if (auto *inst = dyn_cast(this)) return inst; if (auto *result = dyn_cast(this)) return result->getParent(); return nullptr; } Optional ValueBase::getDefiningInstructionResult() { if (auto *inst = dyn_cast(this)) return DefiningInstructionResult{inst, 0}; if (auto *result = dyn_cast(this)) return DefiningInstructionResult{result->getParent(), result->getIndex()}; return None; } SILBasicBlock *SILNode::getParentBlock() const { auto *CanonicalNode = const_cast(this)->getRepresentativeSILNodeInObject(); if (auto *Inst = dyn_cast(CanonicalNode)) return Inst->getParent(); if (auto *Arg = dyn_cast(CanonicalNode)) return Arg->getParent(); return nullptr; } SILFunction *SILNode::getFunction() const { auto *CanonicalNode = const_cast(this)->getRepresentativeSILNodeInObject(); if (auto *Inst = dyn_cast(CanonicalNode)) return Inst->getFunction(); if (auto *Arg = dyn_cast(CanonicalNode)) return Arg->getFunction(); return nullptr; } SILModule *SILNode::getModule() const { auto *CanonicalNode = const_cast(this)->getRepresentativeSILNodeInObject(); if (auto *Inst = dyn_cast(CanonicalNode)) return &Inst->getModule(); if (auto *Arg = dyn_cast(CanonicalNode)) return &Arg->getModule(); return nullptr; } const SILNode *SILNode::getRepresentativeSILNodeSlowPath() const { assert(getStorageLoc() != SILNodeStorageLocation::Instruction); if (isa(this)) { assert(hasMultipleSILNodeBases(getKind())); return &static_cast( static_cast( static_cast(*this))); } if (auto *MVR = dyn_cast(this)) { return MVR->getParent(); } llvm_unreachable("Invalid value for slow path"); } /// Get a location for this value. SILLocation SILValue::getLoc() const { if (auto *instr = Value->getDefiningInstruction()) return instr->getLoc(); if (auto *arg = dyn_cast(*this)) { if (arg->getDecl()) return RegularLocation(const_cast(arg->getDecl())); } // TODO: bbargs should probably use one of their operand locations. return Value->getFunction()->getLocation(); } //===----------------------------------------------------------------------===// // ValueOwnershipKind //===----------------------------------------------------------------------===// ValueOwnershipKind::ValueOwnershipKind(SILModule &M, SILType Type, SILArgumentConvention Convention) : Value() { // Trivial types can be passed using a variety of conventions. They always // have trivial ownership. if (Type.isTrivial(M)) { Value = ValueOwnershipKind::Trivial; return; } switch (Convention) { case SILArgumentConvention::Indirect_In: case SILArgumentConvention::Indirect_In_Constant: Value = SILModuleConventions(M).useLoweredAddresses() ? ValueOwnershipKind::Trivial : ValueOwnershipKind::Owned; break; case SILArgumentConvention::Indirect_In_Guaranteed: Value = SILModuleConventions(M).useLoweredAddresses() ? ValueOwnershipKind::Trivial : ValueOwnershipKind::Guaranteed; break; case SILArgumentConvention::Indirect_Inout: case SILArgumentConvention::Indirect_InoutAliasable: case SILArgumentConvention::Indirect_Out: Value = ValueOwnershipKind::Trivial; return; case SILArgumentConvention::Direct_Owned: Value = ValueOwnershipKind::Owned; return; case SILArgumentConvention::Direct_Unowned: Value = ValueOwnershipKind::Unowned; return; case SILArgumentConvention::Direct_Guaranteed: Value = ValueOwnershipKind::Guaranteed; return; case SILArgumentConvention::Direct_Deallocating: llvm_unreachable("Not handled"); } } llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os, ValueOwnershipKind Kind) { switch (Kind) { case ValueOwnershipKind::Trivial: return os << "trivial"; case ValueOwnershipKind::Unowned: return os << "unowned"; case ValueOwnershipKind::Owned: return os << "owned"; case ValueOwnershipKind::Guaranteed: return os << "guaranteed"; case ValueOwnershipKind::Any: return os << "any"; } llvm_unreachable("Unhandled ValueOwnershipKind in switch."); } Optional ValueOwnershipKind::merge(ValueOwnershipKind RHS) const { auto LHSVal = Value; auto RHSVal = RHS.Value; // Any merges with anything. if (LHSVal == ValueOwnershipKind::Any) { return ValueOwnershipKind(RHSVal); } // Any merges with anything. if (RHSVal == ValueOwnershipKind::Any) { return ValueOwnershipKind(LHSVal); } return (LHSVal == RHSVal) ? Optional(*this) : None; } ValueOwnershipKind::ValueOwnershipKind(StringRef S) { auto Result = llvm::StringSwitch>(S) .Case("trivial", ValueOwnershipKind::Trivial) .Case("unowned", ValueOwnershipKind::Unowned) .Case("owned", ValueOwnershipKind::Owned) .Case("guaranteed", ValueOwnershipKind::Guaranteed) .Case("any", ValueOwnershipKind::Any) .Default(None); if (!Result.hasValue()) llvm_unreachable("Invalid string representation of ValueOwnershipKind"); Value = Result.getValue(); } ValueOwnershipKind ValueOwnershipKind::getProjectedOwnershipKind(SILModule &M, SILType Proj) const { if (Proj.isTrivial(M)) return ValueOwnershipKind::Trivial; return *this; } ValueOwnershipKind SILValue::getOwnershipKind() const { // Once we have multiple return values, this must be changed. sil::ValueOwnershipKindClassifier Classifier; return Classifier.visit(const_cast(Value)); } #if 0 /// Map a SILValue mnemonic name to its ValueKind. ValueKind swift::getSILValueKind(StringRef Name) { #define SINGLE_VALUE_INST(Id, TextualName, Parent, MemoryBehavior, ReleasingBehavior) \ if (Name == #TextualName) \ return ValueKind::Id; #define VALUE(Id, Parent) \ if (Name == #Id) \ return ValueKind::Id; #include "swift/SIL/SILNodes.def" #ifdef NDEBUG llvm::errs() << "Unknown SILValue name\n"; abort(); #endif llvm_unreachable("Unknown SILValue name"); } /// Map ValueKind to a corresponding mnemonic name. StringRef swift::getSILValueName(ValueKind Kind) { switch (Kind) { #define SINGLE_VALUE_INST(Id, TextualName, Parent, MemoryBehavior, ReleasingBehavior) \ case ValueKind::Id: \ return #TextualName; #define VALUE(Id, Parent) \ case ValueKind::Id: \ return #Id; #include "swift/SIL/SILNodes.def" } } #endif