| //===--- DeserializeSIL.cpp - Read SIL ------------------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "deserialize" |
| #include "DeserializeSIL.h" |
| |
| #include "BCReadingExtras.h" |
| #include "DeserializationErrors.h" |
| #include "ModuleFile.h" |
| #include "SILFormat.h" |
| |
| #include "SILSerializationFunctionBuilder.h" |
| #include "swift/AST/GenericSignature.h" |
| #include "swift/AST/PrettyStackTrace.h" |
| #include "swift/AST/ProtocolConformance.h" |
| #include "swift/Basic/Defer.h" |
| #include "swift/Basic/PrettyStackTrace.h" |
| #include "swift/SIL/SILArgument.h" |
| #include "swift/SIL/SILBuilder.h" |
| #include "swift/SIL/SILDebugScope.h" |
| #include "swift/SIL/SILModule.h" |
| #include "swift/SIL/SILUndef.h" |
| |
| #include "llvm/ADT/Statistic.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/DJB.h" |
| #include "llvm/Support/OnDiskHashTable.h" |
| |
| #include <type_traits> |
| |
| using namespace swift; |
| using namespace swift::serialization; |
| using namespace swift::serialization::sil_block; |
| using namespace llvm::support; |
| |
| const char SILEntityError::ID = '\0'; |
| void SILEntityError::anchor() {} |
| |
| STATISTIC(NumDeserializedFunc, "Number of deserialized SIL functions"); |
| |
| static Optional<StringLiteralInst::Encoding> |
| fromStableStringEncoding(unsigned value) { |
| switch (value) { |
| case SIL_BYTES: return StringLiteralInst::Encoding::Bytes; |
| case SIL_UTF8: return StringLiteralInst::Encoding::UTF8; |
| case SIL_OBJC_SELECTOR: return StringLiteralInst::Encoding::ObjCSelector; |
| default: return None; |
| } |
| } |
| |
| static Optional<SILLinkage> |
| fromStableSILLinkage(unsigned value) { |
| switch (value) { |
| case SIL_LINKAGE_PUBLIC: return SILLinkage::Public; |
| case SIL_LINKAGE_PUBLIC_NON_ABI: return SILLinkage::PublicNonABI; |
| case SIL_LINKAGE_HIDDEN: return SILLinkage::Hidden; |
| case SIL_LINKAGE_SHARED: return SILLinkage::Shared; |
| case SIL_LINKAGE_PRIVATE: return SILLinkage::Private; |
| case SIL_LINKAGE_PUBLIC_EXTERNAL: return SILLinkage::PublicExternal; |
| case SIL_LINKAGE_HIDDEN_EXTERNAL: return SILLinkage::HiddenExternal; |
| case SIL_LINKAGE_SHARED_EXTERNAL: return SILLinkage::SharedExternal; |
| case SIL_LINKAGE_PRIVATE_EXTERNAL: return SILLinkage::PrivateExternal; |
| default: return None; |
| } |
| } |
| |
| static Optional<SILVTable::Entry::Kind> |
| fromStableVTableEntryKind(unsigned value) { |
| switch (value) { |
| case SIL_VTABLE_ENTRY_NORMAL: return SILVTable::Entry::Kind::Normal; |
| case SIL_VTABLE_ENTRY_INHERITED: return SILVTable::Entry::Kind::Inherited; |
| case SIL_VTABLE_ENTRY_OVERRIDE: return SILVTable::Entry::Kind::Override; |
| default: return None; |
| } |
| } |
| |
| /// Used to deserialize entries in the on-disk func hash table. |
| class SILDeserializer::FuncTableInfo { |
| ModuleFile &MF; |
| |
| public: |
| using internal_key_type = StringRef; |
| using external_key_type = StringRef; |
| using data_type = DeclID; |
| using hash_value_type = uint32_t; |
| using offset_type = unsigned; |
| |
| explicit FuncTableInfo(ModuleFile &MF) : MF(MF) {} |
| |
| internal_key_type GetInternalKey(external_key_type ID) { return ID; } |
| |
| external_key_type GetExternalKey(internal_key_type ID) { return ID; } |
| |
| hash_value_type ComputeHash(internal_key_type key) { |
| return llvm::djbHash(key, SWIFTMODULE_HASH_SEED); |
| } |
| |
| static bool EqualKey(internal_key_type lhs, internal_key_type rhs) { |
| return lhs == rhs; |
| } |
| |
| static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&data) { |
| return { sizeof(uint32_t), sizeof(uint32_t) }; |
| } |
| |
| internal_key_type ReadKey(const uint8_t *data, unsigned length) { |
| assert(length == sizeof(uint32_t) && "Expect a single IdentifierID."); |
| IdentifierID keyID = endian::readNext<uint32_t, little, unaligned>(data); |
| return MF.getIdentifierText(keyID); |
| } |
| |
| static data_type ReadData(internal_key_type key, const uint8_t *data, |
| unsigned length) { |
| assert(length == sizeof(uint32_t) && "Expect a single DeclID."); |
| data_type result = endian::readNext<uint32_t, little, unaligned>(data); |
| return result; |
| } |
| }; |
| |
| SILDeserializer::SILDeserializer( |
| ModuleFile *MF, SILModule &M, |
| DeserializationNotificationHandlerSet *callback) |
| : MF(MF), SILMod(M), Callback(callback) { |
| |
| SILCursor = MF->getSILCursor(); |
| SILIndexCursor = MF->getSILIndexCursor(); |
| // Early return if either sil block or sil index block does not exist. |
| if (SILCursor.AtEndOfStream() || SILIndexCursor.AtEndOfStream()) |
| return; |
| |
| // Load any abbrev records at the start of the block. |
| MF->fatalIfUnexpected(SILCursor.advance()); |
| |
| llvm::BitstreamCursor cursor = SILIndexCursor; |
| // We expect SIL_FUNC_NAMES first, then SIL_VTABLE_NAMES, then |
| // SIL_GLOBALVAR_NAMES, then SIL_WITNESS_TABLE_NAMES, and finally |
| // SIL_DEFAULT_WITNESS_TABLE_NAMES. But each one can be |
| // omitted if no entries exist in the module file. |
| unsigned kind = 0; |
| while (kind != sil_index_block::SIL_PROPERTY_OFFSETS) { |
| llvm::BitstreamEntry next = MF->fatalIfUnexpected(cursor.advance()); |
| if (next.Kind == llvm::BitstreamEntry::EndBlock) |
| return; |
| |
| SmallVector<uint64_t, 4> scratch; |
| StringRef blobData; |
| unsigned prevKind = kind; |
| kind = |
| MF->fatalIfUnexpected(cursor.readRecord(next.ID, scratch, &blobData)); |
| assert((next.Kind == llvm::BitstreamEntry::Record && |
| kind > prevKind && |
| (kind == sil_index_block::SIL_FUNC_NAMES || |
| kind == sil_index_block::SIL_VTABLE_NAMES || |
| kind == sil_index_block::SIL_GLOBALVAR_NAMES || |
| kind == sil_index_block::SIL_WITNESS_TABLE_NAMES || |
| kind == sil_index_block::SIL_DEFAULT_WITNESS_TABLE_NAMES || |
| kind == sil_index_block::SIL_PROPERTY_OFFSETS || |
| kind == sil_index_block::SIL_DIFFERENTIABILITY_WITNESS_NAMES)) && |
| "Expect SIL_FUNC_NAMES, SIL_VTABLE_NAMES, SIL_GLOBALVAR_NAMES, \ |
| SIL_WITNESS_TABLE_NAMES, SIL_DEFAULT_WITNESS_TABLE_NAMES, \ |
| SIL_PROPERTY_OFFSETS, or SIL_DIFFERENTIABILITY_WITNESS_NAMES."); |
| (void)prevKind; |
| |
| if (kind == sil_index_block::SIL_FUNC_NAMES) |
| FuncTable = readFuncTable(scratch, blobData); |
| else if (kind == sil_index_block::SIL_VTABLE_NAMES) |
| VTableList = readFuncTable(scratch, blobData); |
| else if (kind == sil_index_block::SIL_GLOBALVAR_NAMES) |
| GlobalVarList = readFuncTable(scratch, blobData); |
| else if (kind == sil_index_block::SIL_WITNESS_TABLE_NAMES) |
| WitnessTableList = readFuncTable(scratch, blobData); |
| else if (kind == sil_index_block::SIL_DEFAULT_WITNESS_TABLE_NAMES) |
| DefaultWitnessTableList = readFuncTable(scratch, blobData); |
| else if (kind == sil_index_block::SIL_DIFFERENTIABILITY_WITNESS_NAMES) |
| DifferentiabilityWitnessList = readFuncTable(scratch, blobData); |
| else if (kind == sil_index_block::SIL_PROPERTY_OFFSETS) { |
| // No matching 'names' block for property descriptors needed yet. |
| MF->allocateBuffer(Properties, scratch); |
| return; |
| } |
| |
| // Read SIL_FUNC|VTABLE|GLOBALVAR_OFFSETS record. |
| next = MF->fatalIfUnexpected(cursor.advance()); |
| scratch.clear(); |
| unsigned offKind = |
| MF->fatalIfUnexpected(cursor.readRecord(next.ID, scratch, &blobData)); |
| (void)offKind; |
| if (kind == sil_index_block::SIL_FUNC_NAMES) { |
| assert((next.Kind == llvm::BitstreamEntry::Record && |
| offKind == sil_index_block::SIL_FUNC_OFFSETS) && |
| "Expect a SIL_FUNC_OFFSETS record."); |
| MF->allocateBuffer(Funcs, scratch); |
| } else if (kind == sil_index_block::SIL_VTABLE_NAMES) { |
| assert((next.Kind == llvm::BitstreamEntry::Record && |
| offKind == sil_index_block::SIL_VTABLE_OFFSETS) && |
| "Expect a SIL_VTABLE_OFFSETS record."); |
| MF->allocateBuffer(VTables, scratch); |
| } else if (kind == sil_index_block::SIL_GLOBALVAR_NAMES) { |
| assert((next.Kind == llvm::BitstreamEntry::Record && |
| offKind == sil_index_block::SIL_GLOBALVAR_OFFSETS) && |
| "Expect a SIL_GLOBALVAR_OFFSETS record."); |
| MF->allocateBuffer(GlobalVars, scratch); |
| } else if (kind == sil_index_block::SIL_WITNESS_TABLE_NAMES) { |
| assert((next.Kind == llvm::BitstreamEntry::Record && |
| offKind == sil_index_block::SIL_WITNESS_TABLE_OFFSETS) && |
| "Expect a SIL_WITNESS_TABLE_OFFSETS record."); |
| MF->allocateBuffer(WitnessTables, scratch); |
| } else if (kind == sil_index_block::SIL_DEFAULT_WITNESS_TABLE_NAMES) { |
| assert((next.Kind == llvm::BitstreamEntry::Record && |
| offKind == sil_index_block::SIL_DEFAULT_WITNESS_TABLE_OFFSETS) && |
| "Expect a SIL_DEFAULT_WITNESS_TABLE_OFFSETS record."); |
| MF->allocateBuffer(DefaultWitnessTables, scratch); |
| } else if (kind == sil_index_block::SIL_DIFFERENTIABILITY_WITNESS_NAMES) { |
| assert((next.Kind == llvm::BitstreamEntry::Record && |
| offKind == |
| sil_index_block::SIL_DIFFERENTIABILITY_WITNESS_OFFSETS) && |
| "Expect a SIL_DIFFERENTIABILITY_WITNESS_OFFSETS record."); |
| MF->allocateBuffer(DifferentiabilityWitnesses, scratch); |
| } |
| } |
| } |
| |
| std::unique_ptr<SILDeserializer::SerializedFuncTable> |
| SILDeserializer::readFuncTable(ArrayRef<uint64_t> fields, StringRef blobData) { |
| uint32_t tableOffset; |
| sil_index_block::ListLayout::readRecord(fields, tableOffset); |
| auto base = reinterpret_cast<const uint8_t *>(blobData.data()); |
| |
| using OwnedTable = std::unique_ptr<SerializedFuncTable>; |
| return OwnedTable(SerializedFuncTable::Create(base + tableOffset, |
| base + sizeof(uint32_t), base, |
| FuncTableInfo(*MF))); |
| } |
| |
| /// A high-level overview of how forward references work in serializer and |
| /// deserializer: |
| /// In serializer, we pre-assign a value ID in order, to each basic block |
| /// argument and each SILInstruction that has a value. |
| /// In deserializer, we use LocalValues to store the definitions and |
| /// ForwardLocalValues for forward-referenced values (values that are |
| /// used but not yet defined). LocalValues are updated in setLocalValue where |
| /// the ID passed in assumes the same ordering as in serializer: in-order |
| /// for each basic block argument and each SILInstruction that has a value. |
| /// We update ForwardLocalValues in getLocalValue and when a value is defined |
| /// in setLocalValue, the corresponding entry in ForwardLocalValues will be |
| /// erased. |
| void SILDeserializer::setLocalValue(ValueBase *Value, ValueID Id) { |
| ValueBase *&Entry = LocalValues[Id]; |
| assert(!Entry && "We should not redefine the same value."); |
| |
| auto It = ForwardLocalValues.find(Id); |
| if (It != ForwardLocalValues.end()) { |
| // Take the information about the forward ref out of the map. |
| ValueBase *Placeholder = It->second; |
| |
| // Remove the entries from the map. |
| ForwardLocalValues.erase(It); |
| |
| Placeholder->replaceAllUsesWith(Value); |
| } |
| |
| // Store it in our map. |
| Entry = Value; |
| } |
| |
| SILValue SILDeserializer::getLocalValue(ValueID Id, |
| SILType Type) { |
| // The first two IDs are special undefined values. |
| if (Id == 0) |
| return SILUndef::get(Type, SILMod); |
| assert(Id != 1 && "This used to be for SILUndef with OwnershipKind::Owned... " |
| "but we don't support that anymore. Make sure no one " |
| "changes that without updating this code if needed"); |
| |
| // Check to see if this is already defined. |
| ValueBase *Entry = LocalValues.lookup(Id); |
| if (Entry) { |
| // If this value was already defined, check it to make sure types match. |
| assert(Entry->getType() == Type && "Value Type mismatch?"); |
| return Entry; |
| } |
| |
| // Otherwise, this is a forward reference. Create a dummy node to represent |
| // it until we see a real definition. |
| ValueBase *&Placeholder = ForwardLocalValues[Id]; |
| if (!Placeholder) |
| Placeholder = new (SILMod) GlobalAddrInst(SILDebugLocation(), Type); |
| return Placeholder; |
| } |
| |
| /// Return the SILBasicBlock of a given ID. |
| SILBasicBlock *SILDeserializer::getBBForDefinition(SILFunction *Fn, |
| SILBasicBlock *Prev, |
| unsigned ID) { |
| SILBasicBlock *&BB = BlocksByID[ID]; |
| // If the block has never been named yet, just create it. |
| if (BB == nullptr) { |
| if (Prev) { |
| BB = Fn->createBasicBlockAfter(Prev); |
| } else { |
| BB = Fn->createBasicBlock(); |
| } |
| return BB; |
| } |
| |
| // If it already exists, it was either a forward reference or a redefinition. |
| // The latter should never happen. |
| bool wasForwardReferenced = UndefinedBlocks.erase(BB); |
| assert(wasForwardReferenced); |
| (void)wasForwardReferenced; |
| |
| if (Prev) |
| BB->moveAfter(Prev); |
| return BB; |
| } |
| |
| /// Return the SILBasicBlock of a given ID. |
| SILBasicBlock *SILDeserializer::getBBForReference(SILFunction *Fn, |
| unsigned ID) { |
| SILBasicBlock *&BB = BlocksByID[ID]; |
| if (BB != nullptr) |
| return BB; |
| |
| // Otherwise, create it and remember that this is a forward reference |
| BB = Fn->createBasicBlock(); |
| UndefinedBlocks[BB] = ID; |
| return BB; |
| } |
| |
| /// Helper function to convert from Type to SILType. |
| SILType SILDeserializer::getSILType(Type Ty, SILValueCategory Category, |
| SILFunction *inContext) { |
| auto TyLoc = TypeLoc::withoutLoc(Ty); |
| if (!inContext) { |
| return SILType::getPrimitiveType(TyLoc.getType()->getCanonicalType(), |
| Category); |
| } |
| return inContext->getLoweredType(TyLoc.getType()->getCanonicalType()) |
| .getCategoryType(Category); |
| } |
| |
| /// Helper function to find a SILDifferentiabilityWitness, given its mangled |
| /// key. |
| SILDifferentiabilityWitness * |
| SILDeserializer::getSILDifferentiabilityWitnessForReference( |
| StringRef mangledKey) { |
| // Check to see if we have a witness under this key already. |
| auto *witness = SILMod.lookUpDifferentiabilityWitness(mangledKey); |
| if (witness) |
| return witness; |
| // Otherwise, look for a witness under this key in the module. |
| if (!DifferentiabilityWitnessList) |
| return nullptr; |
| auto iter = DifferentiabilityWitnessList->find(mangledKey); |
| if (iter == DifferentiabilityWitnessList->end()) |
| return nullptr; |
| return readDifferentiabilityWitness(*iter); |
| } |
| |
| /// Helper function to find a SILFunction, given its name and type. |
| SILFunction *SILDeserializer::getFuncForReference(StringRef name, |
| SILType type) { |
| // Check to see if we have a function by this name already. |
| SILFunction *fn = SILMod.lookUpFunction(name); |
| if (!fn) { |
| // Otherwise, look for a function with this name in the module. |
| auto iter = FuncTable->find(name); |
| if (iter != FuncTable->end()) { |
| auto maybeFn = readSILFunctionChecked(*iter, nullptr, name, |
| /*declarationOnly*/ true); |
| if (maybeFn) { |
| fn = maybeFn.get(); |
| } else { |
| // Ignore the failure; we'll synthesize a bogus function instead. |
| llvm::consumeError(maybeFn.takeError()); |
| } |
| } |
| } |
| |
| // FIXME: check for matching types. |
| |
| // At this point, if fn is set, we know that we have a good function to use. |
| if (fn) |
| return fn; |
| |
| // Otherwise, create a function declaration with the right type and a bogus |
| // source location. This ensures that we can at least parse the rest of the |
| // SIL. |
| SourceLoc sourceLoc; |
| SILSerializationFunctionBuilder builder(SILMod); |
| return builder.createDeclaration(name, type, RegularLocation(sourceLoc)); |
| } |
| |
| /// Helper function to find a SILFunction, given its name and type. |
| SILFunction *SILDeserializer::getFuncForReference(StringRef name) { |
| // Check to see if we have a function by this name already. |
| SILFunction *fn = SILMod.lookUpFunction(name); |
| if (fn) |
| return fn; |
| |
| // Otherwise, look for a function with this name in the module. |
| auto iter = FuncTable->find(name); |
| if (iter == FuncTable->end()) |
| return nullptr; |
| |
| auto maybeFn = readSILFunctionChecked(*iter, nullptr, name, |
| /*declarationOnly*/ true); |
| if (!maybeFn) { |
| // Ignore the failure and just pretend the function doesn't exist |
| llvm::consumeError(maybeFn.takeError()); |
| return nullptr; |
| } |
| |
| return maybeFn.get(); |
| } |
| |
| /// Helper function to find a SILGlobalVariable given its name. It first checks |
| /// in the module. If we cannot find it in the module, we attempt to |
| /// deserialize it. |
| SILGlobalVariable *SILDeserializer::getGlobalForReference(StringRef name) { |
| // Check to see if we have a global by this name already. |
| if (SILGlobalVariable *g = SILMod.lookUpGlobalVariable(name)) |
| return g; |
| |
| // Otherwise, look for a global with this name in the module. |
| return readGlobalVar(name); |
| } |
| |
| /// Deserialize a SILFunction if it is not already deserialized. The input |
| /// SILFunction can either be an empty declaration or null. If it is an empty |
| /// declaration, we fill in the contents. If the input SILFunction is |
| /// null, we create a SILFunction. |
| SILFunction *SILDeserializer::readSILFunction(DeclID FID, |
| SILFunction *existingFn, |
| StringRef name, |
| bool declarationOnly, |
| bool errorIfEmptyBody) { |
| llvm::Expected<SILFunction *> deserialized = |
| readSILFunctionChecked(FID, existingFn, name, declarationOnly, |
| errorIfEmptyBody); |
| if (!deserialized) { |
| MF->fatal(deserialized.takeError()); |
| } |
| return deserialized.get(); |
| } |
| |
| llvm::Expected<SILFunction *> |
| SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, |
| StringRef name, bool declarationOnly, |
| bool errorIfEmptyBody) { |
| // We can't deserialize function bodies after IRGen lowering passes have |
| // happened since other definitions in the module will no longer be in |
| // canonical SIL form. |
| switch (SILMod.getStage()) { |
| case SILStage::Raw: |
| case SILStage::Canonical: |
| break; |
| |
| case SILStage::Lowered: |
| llvm_unreachable("cannot deserialize into a module that has entered " |
| "Lowered stage"); |
| } |
| |
| if (FID == 0) |
| return nullptr; |
| assert(FID <= Funcs.size() && "invalid SILFunction ID"); |
| |
| PrettyStackTraceStringAction trace("deserializing SIL function", name); |
| |
| auto &cacheEntry = Funcs[FID-1]; |
| if (cacheEntry.isFullyDeserialized() || |
| (cacheEntry.isDeserialized() && declarationOnly)) |
| return cacheEntry.get(); |
| |
| BCOffsetRAII restoreOffset(SILCursor); |
| if (llvm::Error Err = SILCursor.JumpToBit(cacheEntry.getOffset())) |
| return std::move(Err); |
| |
| llvm::Expected<llvm::BitstreamEntry> maybeEntry = |
| SILCursor.advance(AF_DontPopBlockAtEnd); |
| if (!maybeEntry) |
| return maybeEntry.takeError(); |
| llvm::BitstreamEntry entry = maybeEntry.get(); |
| if (entry.Kind == llvm::BitstreamEntry::Error) { |
| LLVM_DEBUG(llvm::dbgs() << "Cursor advance error in readSILFunction.\n"); |
| MF->fatal(); |
| } |
| |
| SmallVector<uint64_t, 64> scratch; |
| StringRef blobData; |
| llvm::Expected<unsigned> maybeKind = |
| SILCursor.readRecord(entry.ID, scratch, &blobData); |
| if (!maybeKind) |
| MF->fatal(maybeKind.takeError()); |
| unsigned kind = maybeKind.get(); |
| assert(kind == SIL_FUNCTION && "expect a sil function"); |
| (void)kind; |
| |
| DeclID clangNodeOwnerID; |
| TypeID funcTyID; |
| IdentifierID replacedFunctionID; |
| GenericSignatureID genericSigID; |
| unsigned rawLinkage, isTransparent, isSerialized, isThunk, |
| isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy, |
| optimizationMode, subclassScope, hasCReferences, effect, numSpecAttrs, |
| hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), |
| isDynamic, isExactSelfClass; |
| ArrayRef<uint64_t> SemanticsIDs; |
| SILFunctionLayout::readRecord( |
| scratch, rawLinkage, isTransparent, isSerialized, isThunk, |
| isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy, |
| optimizationMode, subclassScope, hasCReferences, effect, numSpecAttrs, |
| hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), |
| isDynamic, isExactSelfClass, funcTyID, replacedFunctionID, genericSigID, |
| clangNodeOwnerID, SemanticsIDs); |
| |
| if (funcTyID == 0) { |
| LLVM_DEBUG(llvm::dbgs() << "SILFunction typeID is 0.\n"); |
| MF->fatal(); |
| } |
| auto astType = MF->getTypeChecked(funcTyID); |
| if (!astType) { |
| if (!existingFn || errorIfEmptyBody) { |
| return llvm::make_error<SILEntityError>( |
| name, takeErrorInfo(astType.takeError())); |
| } |
| consumeError(astType.takeError()); |
| return existingFn; |
| } |
| auto ty = getSILType(astType.get(), SILValueCategory::Object, nullptr); |
| if (!ty.is<SILFunctionType>()) { |
| LLVM_DEBUG(llvm::dbgs() << "not a function type for SILFunction\n"); |
| MF->fatal(); |
| } |
| |
| SILFunction *replacedFunction = nullptr; |
| Identifier replacedObjectiveCFunc; |
| if (replacedFunctionID && |
| ty.getAs<SILFunctionType>()->getExtInfo().getRepresentation() != |
| SILFunctionTypeRepresentation::ObjCMethod) { |
| replacedFunction = |
| getFuncForReference(MF->getIdentifier(replacedFunctionID).str()); |
| } else if (replacedFunctionID) { |
| replacedObjectiveCFunc = MF->getIdentifier(replacedFunctionID); |
| } |
| |
| auto linkageOpt = fromStableSILLinkage(rawLinkage); |
| if (!linkageOpt) { |
| LLVM_DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage |
| << " for SILFunction\n"); |
| MF->fatal(); |
| } |
| SILLinkage linkage = linkageOpt.getValue(); |
| |
| ValueDecl *clangNodeOwner = nullptr; |
| if (clangNodeOwnerID != 0) { |
| clangNodeOwner = dyn_cast_or_null<ValueDecl>(MF->getDecl(clangNodeOwnerID)); |
| if (!clangNodeOwner) { |
| LLVM_DEBUG(llvm::dbgs() << "invalid clang node owner for SILFunction\n"); |
| MF->fatal(); |
| } |
| } |
| |
| // If we weren't handed a function, check for an existing |
| // declaration in the output module. |
| if (!existingFn) existingFn = SILMod.lookUpFunction(name); |
| auto fn = existingFn; |
| |
| // TODO: use the correct SILLocation from module. |
| SILLocation loc = RegularLocation::getAutoGeneratedLocation(); |
| |
| // If we've already serialized the module, don't mark the function |
| // as serialized, since we no longer need to enforce resilience |
| // boundaries. |
| if (SILMod.isSerialized()) |
| isSerialized = IsNotSerialized; |
| |
| SILSerializationFunctionBuilder builder(SILMod); |
| |
| // If we have an existing function, verify that the types match up. |
| if (fn) { |
| if (fn->getLoweredType() != ty) { |
| LLVM_DEBUG(llvm::dbgs() << "SILFunction type mismatch.\n"); |
| MF->fatal(); |
| } |
| |
| fn->setSerialized(IsSerialized_t(isSerialized)); |
| |
| // If the serialized function comes from the same module, we're merging |
| // modules, and can update the the linkage directly. This is needed to |
| // correctly update the linkage for forward declarations to entities defined |
| // in another file of the same module – we want to ensure the linkage |
| // reflects the fact that the entity isn't really external and shouldn't be |
| // dropped from the resulting merged module. |
| if (getFile()->getParentModule() == SILMod.getSwiftModule()) |
| fn->setLinkage(linkage); |
| |
| // Don't override the transparency or linkage of a function with |
| // an existing declaration, except if we deserialized a |
| // PublicNonABI function, which has HiddenExternal when |
| // referenced as a declaration, and SharedExternal when it has |
| // a deserialized body. |
| if (isAvailableExternally(fn->getLinkage())) { |
| if (linkage == SILLinkage::PublicNonABI) { |
| fn->setLinkage(SILLinkage::SharedExternal); |
| } else if (hasPublicVisibility(linkage)) { |
| // Cross-module-optimization can change the linkage to public. In this |
| // case we need to update the linkage of the function (which is |
| // originally just derived from the AST). |
| fn->setLinkage(SILLinkage::PublicExternal); |
| } |
| } |
| |
| if (fn->isDynamicallyReplaceable() != isDynamic) { |
| LLVM_DEBUG(llvm::dbgs() << "SILFunction type mismatch.\n"); |
| MF->fatal(); |
| } |
| |
| } else { |
| // Otherwise, create a new function. |
| fn = builder.createDeclaration(name, ty, loc); |
| fn->setLinkage(linkage); |
| fn->setTransparent(IsTransparent_t(isTransparent == 1)); |
| fn->setSerialized(IsSerialized_t(isSerialized)); |
| fn->setThunk(IsThunk_t(isThunk)); |
| fn->setWithoutActuallyEscapingThunk(bool(isWithoutactuallyEscapingThunk)); |
| fn->setInlineStrategy(Inline_t(inlineStrategy)); |
| fn->setSpecialPurpose(SILFunction::Purpose(specialPurpose)); |
| fn->setEffectsKind(EffectsKind(effect)); |
| fn->setOptimizationMode(OptimizationMode(optimizationMode)); |
| fn->setAlwaysWeakImported(isWeakImported); |
| fn->setClassSubclassScope(SubclassScope(subclassScope)); |
| fn->setHasCReferences(bool(hasCReferences)); |
| |
| llvm::VersionTuple available; |
| DECODE_VER_TUPLE(available); |
| fn->setAvailabilityForLinkage( |
| available.empty() |
| ? AvailabilityContext::alwaysAvailable() |
| : AvailabilityContext(VersionRange::allGTE(available))); |
| |
| fn->setIsDynamic(IsDynamicallyReplaceable_t(isDynamic)); |
| fn->setIsExactSelfClass(IsExactSelfClass_t(isExactSelfClass)); |
| if (replacedFunction) |
| fn->setDynamicallyReplacedFunction(replacedFunction); |
| if (!replacedObjectiveCFunc.empty()) |
| fn->setObjCReplacement(replacedObjectiveCFunc); |
| if (clangNodeOwner) |
| fn->setClangNodeOwner(clangNodeOwner); |
| for (auto ID : SemanticsIDs) { |
| fn->addSemanticsAttr(MF->getIdentifierText(ID)); |
| } |
| if (Callback) Callback->didDeserialize(MF->getAssociatedModule(), fn); |
| } |
| |
| // First before we do /anything/ validate that our function is truly empty. |
| assert(fn->empty() && "SILFunction to be deserialized starts being empty."); |
| |
| // Given that our original function was empty, just match the deserialized |
| // function. Ownership doesn't really have a meaning without a body. |
| builder.setHasOwnership(fn, hasQualifiedOwnership); |
| |
| // Mark this function as deserialized. This avoids rerunning diagnostic |
| // passes. Certain passes in the madatory pipeline may not work as expected |
| // after arbitrary optimization and lowering. |
| if (!MF->isSIB()) |
| fn->setWasDeserializedCanonical(); |
| |
| fn->setBare(IsBare); |
| const SILDebugScope *DS = fn->getDebugScope(); |
| if (!DS) { |
| DS = new (SILMod) SILDebugScope(loc, fn); |
| fn->setDebugScope(DS); |
| } |
| |
| // Read and instantiate the specialize attributes. |
| bool shouldAddAtttributes = fn->getSpecializeAttrs().empty(); |
| while (numSpecAttrs--) { |
| llvm::Expected<llvm::BitstreamEntry> maybeNext = |
| SILCursor.advance(AF_DontPopBlockAtEnd); |
| if (!maybeNext) |
| return maybeNext.takeError(); |
| llvm::BitstreamEntry next = maybeNext.get(); |
| assert(next.Kind == llvm::BitstreamEntry::Record); |
| |
| scratch.clear(); |
| llvm::Expected<unsigned> maybeKind = SILCursor.readRecord(next.ID, scratch); |
| if (!maybeKind) |
| return maybeKind.takeError(); |
| unsigned kind = maybeKind.get(); |
| assert(kind == SIL_SPECIALIZE_ATTR && "Missing specialization attribute"); |
| |
| unsigned exported; |
| unsigned specializationKindVal; |
| GenericSignatureID specializedSigID; |
| IdentifierID targetFunctionID; |
| IdentifierID spiGroupID; |
| ModuleID spiModuleID; |
| SILSpecializeAttrLayout::readRecord( |
| scratch, exported, specializationKindVal, specializedSigID, |
| targetFunctionID, spiGroupID, spiModuleID); |
| |
| SILFunction *target = nullptr; |
| if (targetFunctionID) { |
| target = getFuncForReference(MF->getIdentifier(targetFunctionID).str()); |
| } |
| |
| Identifier spiGroup; |
| const ModuleDecl *spiModule = nullptr; |
| if (spiGroupID) { |
| spiGroup = MF->getIdentifier(spiGroupID); |
| spiModule = MF->getModule(spiModuleID); |
| } |
| |
| SILSpecializeAttr::SpecializationKind specializationKind = |
| specializationKindVal ? SILSpecializeAttr::SpecializationKind::Partial |
| : SILSpecializeAttr::SpecializationKind::Full; |
| |
| auto specializedSig = MF->getGenericSignature(specializedSigID); |
| // Only add the specialize attributes once. |
| if (shouldAddAtttributes) { |
| // Read the substitution list and construct a SILSpecializeAttr. |
| fn->addSpecializeAttr(SILSpecializeAttr::create( |
| SILMod, specializedSig, exported != 0, specializationKind, target, |
| spiGroup, spiModule)); |
| } |
| } |
| |
| GenericEnvironment *genericEnv = nullptr; |
| if (!declarationOnly) |
| if (auto genericSig = MF->getGenericSignature(genericSigID)) |
| genericEnv = genericSig->getGenericEnvironment(); |
| |
| // If the next entry is the end of the block, then this function has |
| // no contents. |
| maybeEntry = SILCursor.advance(AF_DontPopBlockAtEnd); |
| if (!maybeEntry) |
| return maybeEntry.takeError(); |
| entry = maybeEntry.get(); |
| bool isEmptyFunction = (entry.Kind == llvm::BitstreamEntry::EndBlock); |
| assert((!isEmptyFunction || !genericEnv) && |
| "generic environment without body?!"); |
| |
| // Remember this in our cache in case it's a recursive function. |
| // Increase the reference count to keep it alive. |
| bool isFullyDeserialized = (isEmptyFunction || !declarationOnly); |
| if (cacheEntry.isDeserialized()) { |
| assert(fn == cacheEntry.get() && "changing SIL function during deserialization!"); |
| } else { |
| fn->incrementRefCount(); |
| } |
| cacheEntry.set(fn, isFullyDeserialized); |
| |
| // Stop here if we have nothing else to do. |
| if (isEmptyFunction || declarationOnly) { |
| return fn; |
| } |
| |
| ++NumDeserializedFunc; |
| |
| assert(!(fn->getGenericEnvironment() && !fn->empty()) |
| && "function already has context generic params?!"); |
| if (genericEnv) |
| fn->setGenericEnvironment(genericEnv); |
| |
| scratch.clear(); |
| maybeKind = SILCursor.readRecord(entry.ID, scratch); |
| if (!maybeKind) |
| return maybeKind.takeError(); |
| kind = maybeKind.get(); |
| |
| SILBasicBlock *CurrentBB = nullptr; |
| |
| // Clear up at the beginning of each SILFunction. |
| BasicBlockID = 0; |
| BlocksByID.clear(); |
| UndefinedBlocks.clear(); |
| |
| // The first two IDs are reserved for SILUndef. |
| LastValueID = 1; |
| LocalValues.clear(); |
| ForwardLocalValues.clear(); |
| |
| SILOpenedArchetypesTracker OpenedArchetypesTracker(fn); |
| SILBuilder Builder(*fn); |
| // Track the archetypes just like SILGen. This |
| // is required for adding typedef operands to instructions. |
| Builder.setOpenedArchetypesTracker(&OpenedArchetypesTracker); |
| |
| // Define a callback to be invoked on the deserialized types. |
| auto OldDeserializedTypeCallback = MF->DeserializedTypeCallback; |
| SWIFT_DEFER { |
| MF->DeserializedTypeCallback = OldDeserializedTypeCallback; |
| }; |
| |
| MF->DeserializedTypeCallback = [&OpenedArchetypesTracker] (Type ty) { |
| // We can't call getCanonicalType() immediately on everything we |
| // deserialize, but fortunately we only need to register opened |
| // existentials. |
| if (ty->isOpenedExistential()) |
| OpenedArchetypesTracker.registerUsedOpenedArchetypes(CanType(ty)); |
| }; |
| |
| // Another SIL_FUNCTION record means the end of this SILFunction. |
| // SIL_VTABLE or SIL_GLOBALVAR or SIL_WITNESS_TABLE record also means the end |
| // of this SILFunction. |
| while (kind != SIL_FUNCTION && kind != SIL_VTABLE && kind != SIL_GLOBALVAR && |
| kind != SIL_WITNESS_TABLE && kind != SIL_DIFFERENTIABILITY_WITNESS) { |
| if (kind == SIL_BASIC_BLOCK) |
| // Handle a SILBasicBlock record. |
| CurrentBB = readSILBasicBlock(fn, CurrentBB, scratch); |
| else { |
| // If CurrentBB is empty, just return fn. The code in readSILInstruction |
| // assumes that such a situation means that fn is a declaration. Thus it |
| // is using return false to mean two different things, error a failure |
| // occurred and this is a declaration. Work around that for now. |
| if (!CurrentBB) |
| return fn; |
| Builder.setInsertionPoint(CurrentBB); |
| |
| // Handle a SILInstruction record. |
| if (readSILInstruction(fn, Builder, kind, scratch)) { |
| LLVM_DEBUG(llvm::dbgs() << "readSILInstruction returns error.\n"); |
| MF->fatal(); |
| } |
| } |
| |
| // Fetch the next record. |
| scratch.clear(); |
| llvm::Expected<llvm::BitstreamEntry> maybeEntry = |
| SILCursor.advance(AF_DontPopBlockAtEnd); |
| if (!maybeEntry) |
| return maybeEntry.takeError(); |
| llvm::BitstreamEntry entry = maybeEntry.get(); |
| |
| // EndBlock means the end of this SILFunction. |
| if (entry.Kind == llvm::BitstreamEntry::EndBlock) |
| break; |
| maybeKind = SILCursor.readRecord(entry.ID, scratch); |
| if (!maybeKind) |
| return maybeKind.takeError(); |
| kind = maybeKind.get(); |
| } |
| |
| // If fn is empty, we failed to deserialize its body. Return nullptr to signal |
| // error. |
| if (fn->empty() && errorIfEmptyBody) |
| return nullptr; |
| |
| // Check that there are no unresolved forward definitions of opened |
| // archetypes. |
| if (OpenedArchetypesTracker.hasUnresolvedOpenedArchetypeDefinitions()) |
| llvm_unreachable( |
| "All forward definitions of opened archetypes should be resolved"); |
| |
| if (Callback) |
| Callback->didDeserializeFunctionBody(MF->getAssociatedModule(), fn); |
| |
| return fn; |
| } |
| |
| // We put these static asserts here to formalize our assumption that both |
| // SILValueCategory and ValueOwnershipKind have uint8_t as their underlying |
| // pointer values. |
| static_assert( |
| std::is_same<std::underlying_type<SILValueCategory>::type, uint8_t>::value, |
| "Expected an underlying uint8_t type"); |
| // We put these static asserts here to formalize our assumption that both |
| // SILValueCategory and ValueOwnershipKind have uint8_t as their underlying |
| // pointer values. |
| static_assert(std::is_same<std::underlying_type<OwnershipKind::innerty>::type, |
| uint8_t>::value, |
| "Expected an underlying uint8_t type"); |
| SILBasicBlock *SILDeserializer::readSILBasicBlock(SILFunction *Fn, |
| SILBasicBlock *Prev, |
| SmallVectorImpl<uint64_t> &scratch) { |
| ArrayRef<uint64_t> Args; |
| SILBasicBlockLayout::readRecord(scratch, Args); |
| |
| // Args should be a list of triples of the following form: |
| // |
| // 1. A TypeID. |
| // 2. A flag of metadata. This currently includes the SILValueCategory and |
| // ValueOwnershipKind. We enforce size constraints of these types above. |
| // 3. A ValueID. |
| SILBasicBlock *CurrentBB = getBBForDefinition(Fn, Prev, BasicBlockID++); |
| bool IsEntry = CurrentBB->isEntry(); |
| for (unsigned I = 0, E = Args.size(); I < E; I += 3) { |
| TypeID TyID = Args[I]; |
| if (!TyID) return nullptr; |
| ValueID ValId = Args[I+2]; |
| if (!ValId) return nullptr; |
| |
| auto ArgTy = MF->getType(TyID); |
| SILArgument *Arg; |
| auto ValueCategory = SILValueCategory(Args[I + 1] & 0xF); |
| SILType SILArgTy = getSILType(ArgTy, ValueCategory, Fn); |
| if (IsEntry) { |
| Arg = CurrentBB->createFunctionArgument(SILArgTy); |
| } else { |
| auto OwnershipKind = ValueOwnershipKind((Args[I + 1] >> 8) & 0xF); |
| Arg = CurrentBB->createPhiArgument(SILArgTy, OwnershipKind); |
| } |
| LastValueID = LastValueID + 1; |
| setLocalValue(Arg, LastValueID); |
| } |
| return CurrentBB; |
| } |
| |
| static CastConsumptionKind getCastConsumptionKind(unsigned attr) { |
| switch (attr) { |
| case SIL_CAST_CONSUMPTION_TAKE_ALWAYS: |
| return CastConsumptionKind::TakeAlways; |
| case SIL_CAST_CONSUMPTION_TAKE_ON_SUCCESS: |
| return CastConsumptionKind::TakeOnSuccess; |
| case SIL_CAST_CONSUMPTION_COPY_ON_SUCCESS: |
| return CastConsumptionKind::CopyOnSuccess; |
| case SIL_CAST_CONSUMPTION_BORROW_ALWAYS: |
| return CastConsumptionKind::BorrowAlways; |
| default: |
| llvm_unreachable("not a valid CastConsumptionKind for SIL"); |
| } |
| } |
| |
| /// Construct a SILDeclRef from ListOfValues. |
| static SILDeclRef getSILDeclRef(ModuleFile *MF, |
| ArrayRef<uint64_t> ListOfValues, |
| unsigned &NextIdx) { |
| assert(ListOfValues.size() >= NextIdx+3 && |
| "Expect 3 numbers for SILDeclRef"); |
| SILDeclRef DRef(cast<ValueDecl>(MF->getDecl(ListOfValues[NextIdx])), |
| (SILDeclRef::Kind)ListOfValues[NextIdx+1], |
| /*isForeign=*/ListOfValues[NextIdx+2] > 0); |
| NextIdx += 3; |
| return DRef; |
| } |
| |
| Optional<KeyPathPatternComponent> |
| SILDeserializer::readKeyPathComponent(ArrayRef<uint64_t> ListOfValues, |
| unsigned &nextValue) { |
| auto kind = |
| (KeyPathComponentKindEncoding)ListOfValues[nextValue++]; |
| |
| if (kind == KeyPathComponentKindEncoding::Trivial) |
| return None; |
| |
| auto type = MF->getType(ListOfValues[nextValue++]) |
| ->getCanonicalType(); |
| |
| auto handleComputedId = |
| [&]() -> KeyPathPatternComponent::ComputedPropertyId { |
| auto kind = |
| (KeyPathComputedComponentIdKindEncoding)ListOfValues[nextValue++]; |
| switch (kind) { |
| case KeyPathComputedComponentIdKindEncoding::Property: |
| return cast<VarDecl>(MF->getDecl(ListOfValues[nextValue++])); |
| case KeyPathComputedComponentIdKindEncoding::Function: { |
| auto name = MF->getIdentifierText(ListOfValues[nextValue++]); |
| return getFuncForReference(name); |
| } |
| case KeyPathComputedComponentIdKindEncoding::DeclRef: { |
| // read SILDeclRef |
| return getSILDeclRef(MF, ListOfValues, nextValue); |
| } |
| } |
| llvm_unreachable("unhandled kind"); |
| }; |
| |
| ArrayRef<KeyPathPatternComponent::Index> indices; |
| SILFunction *indicesEquals = nullptr; |
| SILFunction *indicesHash = nullptr; |
| AbstractStorageDecl *externalDecl = nullptr; |
| SubstitutionMap externalSubs; |
| |
| auto handleComputedExternalReferenceAndIndices = [&] { |
| auto externalDeclID = ListOfValues[nextValue++]; |
| externalDecl = |
| cast_or_null<AbstractStorageDecl>(MF->getDecl(externalDeclID)); |
| externalSubs = MF->getSubstitutionMap(ListOfValues[nextValue++]); |
| |
| SmallVector<KeyPathPatternComponent::Index, 4> indicesBuf; |
| auto numIndexes = ListOfValues[nextValue++]; |
| indicesBuf.reserve(numIndexes); |
| while (numIndexes-- > 0) { |
| unsigned operand = ListOfValues[nextValue++]; |
| auto formalType = MF->getType(ListOfValues[nextValue++]); |
| auto loweredType = MF->getType(ListOfValues[nextValue++]); |
| auto loweredCategory = (SILValueCategory)ListOfValues[nextValue++]; |
| auto conformance = MF->readConformance(SILCursor); |
| indicesBuf.push_back({ |
| operand, formalType->getCanonicalType(), |
| SILType::getPrimitiveType(loweredType->getCanonicalType(), |
| loweredCategory), |
| conformance}); |
| } |
| |
| indices = MF->getContext().AllocateCopy(indicesBuf); |
| if (!indices.empty()) { |
| auto indicesEqualsName = MF->getIdentifierText(ListOfValues[nextValue++]); |
| auto indicesHashName = MF->getIdentifierText(ListOfValues[nextValue++]); |
| indicesEquals = getFuncForReference(indicesEqualsName); |
| indicesHash = getFuncForReference(indicesHashName); |
| } |
| }; |
| |
| switch (kind) { |
| case KeyPathComponentKindEncoding::StoredProperty: { |
| auto decl = cast<VarDecl>(MF->getDecl(ListOfValues[nextValue++])); |
| return KeyPathPatternComponent::forStoredProperty(decl, type); |
| } |
| case KeyPathComponentKindEncoding::GettableProperty: { |
| auto id = handleComputedId(); |
| auto getterName = MF->getIdentifierText(ListOfValues[nextValue++]); |
| auto getter = getFuncForReference(getterName); |
| handleComputedExternalReferenceAndIndices(); |
| return KeyPathPatternComponent::forComputedGettableProperty( |
| id, getter, indices, indicesEquals, indicesHash, |
| externalDecl, externalSubs, type); |
| } |
| case KeyPathComponentKindEncoding::SettableProperty: { |
| auto id = handleComputedId(); |
| auto getterName = MF->getIdentifierText(ListOfValues[nextValue++]); |
| auto getter = getFuncForReference(getterName); |
| auto setterName = MF->getIdentifierText(ListOfValues[nextValue++]); |
| auto setter = getFuncForReference(setterName); |
| handleComputedExternalReferenceAndIndices(); |
| return KeyPathPatternComponent::forComputedSettableProperty( |
| id, getter, setter, indices, indicesEquals, indicesHash, |
| externalDecl, externalSubs, type); |
| break; |
| } |
| case KeyPathComponentKindEncoding::OptionalChain: |
| return KeyPathPatternComponent::forOptional( |
| KeyPathPatternComponent::Kind::OptionalChain, type); |
| case KeyPathComponentKindEncoding::OptionalForce: |
| return KeyPathPatternComponent::forOptional( |
| KeyPathPatternComponent::Kind::OptionalForce, type); |
| case KeyPathComponentKindEncoding::OptionalWrap: |
| return KeyPathPatternComponent::forOptional( |
| KeyPathPatternComponent::Kind::OptionalWrap, type); |
| case KeyPathComponentKindEncoding::TupleElement: |
| return KeyPathPatternComponent::forTupleElement( |
| ListOfValues[nextValue++], type); |
| case KeyPathComponentKindEncoding::Trivial: |
| llvm_unreachable("handled above"); |
| } |
| |
| llvm_unreachable("invalid key path component kind encoding"); |
| } |
| |
| bool SILDeserializer::readSILInstruction(SILFunction *Fn, |
| SILBuilder &Builder, |
| unsigned RecordKind, |
| SmallVectorImpl<uint64_t> &scratch) { |
| if (Fn) |
| Builder.setCurrentDebugScope(Fn->getDebugScope()); |
| unsigned RawOpCode = 0, TyCategory = 0, TyCategory2 = 0, TyCategory3 = 0, |
| Attr = 0, Attr2 = 0, Attr3 = 0, Attr4 = 0, NumSubs = 0, |
| NumConformances = 0, IsNonThrowingApply = 0; |
| ValueID ValID, ValID2, ValID3; |
| TypeID TyID, TyID2, TyID3; |
| TypeID ConcreteTyID; |
| SourceLoc SLoc; |
| ArrayRef<uint64_t> ListOfValues; |
| SILLocation Loc = RegularLocation(SLoc); |
| |
| switch (RecordKind) { |
| default: |
| llvm_unreachable("Record kind for a SIL instruction is not supported."); |
| case SIL_ONE_VALUE_ONE_OPERAND: |
| SILOneValueOneOperandLayout::readRecord(scratch, RawOpCode, Attr, |
| ValID, TyID, TyCategory, |
| ValID2); |
| break; |
| case SIL_ONE_TYPE: |
| SILOneTypeLayout::readRecord(scratch, RawOpCode, Attr, TyID, TyCategory); |
| break; |
| case SIL_ONE_OPERAND: |
| SILOneOperandLayout::readRecord(scratch, RawOpCode, Attr, |
| TyID, TyCategory, ValID); |
| break; |
| case SIL_ONE_OPERAND_EXTRA_ATTR: |
| SILOneOperandExtraAttributeLayout::readRecord(scratch, RawOpCode, Attr, |
| TyID, TyCategory, ValID); |
| break; |
| case SIL_ONE_TYPE_ONE_OPERAND: |
| SILOneTypeOneOperandLayout::readRecord(scratch, RawOpCode, Attr, |
| TyID, TyCategory, |
| TyID2, TyCategory2, |
| ValID); |
| break; |
| case SIL_INIT_EXISTENTIAL: |
| SILInitExistentialLayout::readRecord(scratch, RawOpCode, |
| TyID, TyCategory, |
| TyID2, TyCategory2, |
| ValID, |
| ConcreteTyID, |
| NumConformances); |
| break; |
| case SIL_ONE_TYPE_VALUES: |
| SILOneTypeValuesLayout::readRecord(scratch, RawOpCode, TyID, TyCategory, |
| ListOfValues); |
| break; |
| case SIL_TWO_OPERANDS: |
| SILTwoOperandsLayout::readRecord(scratch, RawOpCode, Attr, |
| TyID, TyCategory, ValID, |
| TyID2, TyCategory2, ValID2); |
| break; |
| case SIL_TWO_OPERANDS_EXTRA_ATTR: |
| SILTwoOperandsExtraAttributeLayout::readRecord(scratch, RawOpCode, Attr, |
| TyID, TyCategory, ValID, |
| TyID2, TyCategory2, ValID2); |
| break; |
| case SIL_TAIL_ADDR: |
| SILTailAddrLayout::readRecord(scratch, RawOpCode, |
| TyID, ValID, |
| TyID2, ValID2, |
| TyID3); |
| break; |
| case SIL_INST_APPLY: { |
| unsigned IsPartial; |
| SILInstApplyLayout::readRecord(scratch, IsPartial, NumSubs, TyID, TyID2, |
| ValID, ListOfValues); |
| switch (IsPartial) { |
| case SIL_APPLY: |
| RawOpCode = (unsigned)SILInstructionKind::ApplyInst; |
| break; |
| case SIL_PARTIAL_APPLY: |
| RawOpCode = (unsigned)SILInstructionKind::PartialApplyInst; |
| break; |
| case SIL_BUILTIN: |
| RawOpCode = (unsigned)SILInstructionKind::BuiltinInst; |
| break; |
| case SIL_TRY_APPLY: |
| RawOpCode = (unsigned)SILInstructionKind::TryApplyInst; |
| break; |
| case SIL_NON_THROWING_APPLY: |
| RawOpCode = (unsigned)SILInstructionKind::ApplyInst; |
| IsNonThrowingApply = true; |
| break; |
| case SIL_BEGIN_APPLY: |
| RawOpCode = (unsigned)SILInstructionKind::BeginApplyInst; |
| break; |
| case SIL_NON_THROWING_BEGIN_APPLY: |
| RawOpCode = (unsigned)SILInstructionKind::BeginApplyInst; |
| IsNonThrowingApply = true; |
| break; |
| |
| default: |
| llvm_unreachable("unexpected apply inst kind"); |
| } |
| break; |
| } |
| case SIL_INST_NO_OPERAND: |
| SILInstNoOperandLayout::readRecord(scratch, RawOpCode); |
| break; |
| case SIL_INST_WITNESS_METHOD: |
| SILInstWitnessMethodLayout::readRecord( |
| scratch, TyID, TyCategory, Attr, TyID2, TyCategory2, TyID3, |
| TyCategory3, ValID3, ListOfValues); |
| RawOpCode = (unsigned)SILInstructionKind::WitnessMethodInst; |
| break; |
| case SIL_INST_DIFFERENTIABLE_FUNCTION: |
| SILInstDifferentiableFunctionLayout::readRecord( |
| scratch, /*numParams*/ Attr, /*numResults*/ Attr2, |
| /*numDiffParams*/ Attr3, |
| /*hasDerivativeFunctions*/ Attr4, ListOfValues); |
| RawOpCode = (unsigned)SILInstructionKind::DifferentiableFunctionInst; |
| break; |
| case SIL_INST_LINEAR_FUNCTION: |
| SILInstLinearFunctionLayout::readRecord(scratch, /*numDiffParams*/ Attr, |
| /*hasTransposeFunction*/ Attr2, |
| ListOfValues); |
| RawOpCode = (unsigned)SILInstructionKind::LinearFunctionInst; |
| break; |
| case SIL_INST_DIFFERENTIABLE_FUNCTION_EXTRACT: |
| SILInstDifferentiableFunctionExtractLayout::readRecord( |
| scratch, TyID, TyCategory, ValID, /*extractee*/ Attr, |
| /*hasExplicitExtracteeType*/ Attr2, /*explicitExtracteeType*/ TyID2); |
| RawOpCode = (unsigned)SILInstructionKind::DifferentiableFunctionExtractInst; |
| break; |
| case SIL_INST_LINEAR_FUNCTION_EXTRACT: |
| SILInstLinearFunctionExtractLayout::readRecord( |
| scratch, TyID, TyCategory, ValID, /*extractee*/ Attr); |
| RawOpCode = (unsigned)SILInstructionKind::LinearFunctionExtractInst; |
| break; |
| } |
| |
| // FIXME: validate |
| SILInstructionKind OpCode = (SILInstructionKind) RawOpCode; |
| |
| SILInstruction *ResultInst; |
| switch (OpCode) { |
| case SILInstructionKind::DebugValueInst: |
| case SILInstructionKind::DebugValueAddrInst: |
| llvm_unreachable("not supported"); |
| |
| case SILInstructionKind::AllocBoxInst: |
| assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); |
| ResultInst = Builder.createAllocBox( |
| Loc, cast<SILBoxType>(MF->getType(TyID)->getCanonicalType()), None, |
| /*bool hasDynamicLifetime*/ Attr != 0); |
| break; |
| case SILInstructionKind::AllocStackInst: |
| assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); |
| ResultInst = Builder.createAllocStack( |
| Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), |
| None, /*bool hasDynamicLifetime*/ Attr != 0); |
| break; |
| case SILInstructionKind::MetatypeInst: |
| assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); |
| ResultInst = Builder.createMetatype( |
| Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| break; |
| |
| case SILInstructionKind::GetAsyncContinuationInst: |
| assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); |
| ResultInst = Builder.createGetAsyncContinuation( |
| Loc, MF->getType(TyID)->getCanonicalType(), |
| /*throws*/ Attr != 0); |
| break; |
| |
| case SILInstructionKind::GetAsyncContinuationAddrInst: |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND |
| && "Layout should be OneTypeOneOperand."); |
| ResultInst = Builder.createGetAsyncContinuationAddr(Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)), |
| MF->getType(TyID)->getCanonicalType(), |
| /*throws*/ Attr != 0); |
| break; |
| |
| #define ONETYPE_ONEOPERAND_INST(ID) \ |
| case SILInstructionKind::ID##Inst: \ |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \ |
| "Layout should be OneTypeOneOperand."); \ |
| ResultInst = Builder.create##ID( \ |
| Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), \ |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), \ |
| (SILValueCategory)TyCategory2, Fn))); \ |
| break; |
| ONETYPE_ONEOPERAND_INST(ValueMetatype) |
| ONETYPE_ONEOPERAND_INST(ExistentialMetatype) |
| ONETYPE_ONEOPERAND_INST(AllocValueBuffer) |
| ONETYPE_ONEOPERAND_INST(ProjectValueBuffer) |
| ONETYPE_ONEOPERAND_INST(ProjectExistentialBox) |
| ONETYPE_ONEOPERAND_INST(DeallocValueBuffer) |
| #undef ONETYPE_ONEOPERAND_INST |
| case SILInstructionKind::DeallocBoxInst: |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && |
| "Layout should be OneTypeOneOperand."); |
| ResultInst = Builder.createDeallocBox( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn))); |
| break; |
| case SILInstructionKind::OpenExistentialAddrInst: |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && |
| "Layout should be OneTypeOneOperand."); |
| ResultInst = Builder.createOpenExistentialAddr( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)), |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), |
| Attr == 0 ? OpenedExistentialAccess::Immutable |
| : OpenedExistentialAccess::Mutable); |
| break; |
| |
| #define ONEOPERAND_ONETYPE_INST(ID) \ |
| case SILInstructionKind::ID##Inst: \ |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \ |
| "Layout should be OneTypeOneOperand."); \ |
| ResultInst = Builder.create##ID( \ |
| Loc, \ |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), \ |
| (SILValueCategory)TyCategory2, Fn)), \ |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); \ |
| break; |
| ONEOPERAND_ONETYPE_INST(OpenExistentialRef) |
| ONEOPERAND_ONETYPE_INST(OpenExistentialMetatype) |
| ONEOPERAND_ONETYPE_INST(OpenExistentialBox) |
| ONEOPERAND_ONETYPE_INST(OpenExistentialValue) |
| ONEOPERAND_ONETYPE_INST(OpenExistentialBoxValue) |
| // Conversion instructions. |
| #define LOADABLE_REF_STORAGE(Name, ...) \ |
| ONEOPERAND_ONETYPE_INST(RefTo##Name) \ |
| ONEOPERAND_ONETYPE_INST(Name##ToRef) |
| #include "swift/AST/ReferenceStorage.def" |
| ONEOPERAND_ONETYPE_INST(UncheckedRefCast) |
| ONEOPERAND_ONETYPE_INST(UncheckedAddrCast) |
| ONEOPERAND_ONETYPE_INST(UncheckedTrivialBitCast) |
| ONEOPERAND_ONETYPE_INST(UncheckedBitwiseCast) |
| ONEOPERAND_ONETYPE_INST(UncheckedValueCast) |
| ONEOPERAND_ONETYPE_INST(BridgeObjectToRef) |
| ONEOPERAND_ONETYPE_INST(BridgeObjectToWord) |
| ONEOPERAND_ONETYPE_INST(Upcast) |
| ONEOPERAND_ONETYPE_INST(AddressToPointer) |
| ONEOPERAND_ONETYPE_INST(RefToRawPointer) |
| ONEOPERAND_ONETYPE_INST(RawPointerToRef) |
| ONEOPERAND_ONETYPE_INST(ThinToThickFunction) |
| ONEOPERAND_ONETYPE_INST(ThickToObjCMetatype) |
| ONEOPERAND_ONETYPE_INST(ObjCToThickMetatype) |
| ONEOPERAND_ONETYPE_INST(ObjCMetatypeToObject) |
| ONEOPERAND_ONETYPE_INST(ObjCExistentialMetatypeToObject) |
| ONEOPERAND_ONETYPE_INST(ThinFunctionToPointer) |
| ONEOPERAND_ONETYPE_INST(PointerToThinFunction) |
| ONEOPERAND_ONETYPE_INST(ProjectBlockStorage) |
| #undef ONEOPERAND_ONETYPE_INST |
| |
| case SILInstructionKind::ProjectBoxInst: { |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && |
| "Layout should be OneTypeOneOperand."); |
| ResultInst = Builder.createProjectBox( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)), |
| TyID); |
| break; |
| } |
| case SILInstructionKind::ConvertEscapeToNoEscapeInst: { |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && |
| "Layout should be OneTypeOneOperand."); |
| bool isLifetimeGuaranteed = Attr & 0x01; |
| ResultInst = Builder.createConvertEscapeToNoEscape( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)), |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), |
| isLifetimeGuaranteed); |
| break; |
| } |
| case SILInstructionKind::ConvertFunctionInst: { |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND |
| && "Layout should be OneTypeOneOperand."); |
| bool withoutActuallyEscaping = Attr & 0x01; |
| ResultInst = Builder.createConvertFunction( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)), |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), |
| withoutActuallyEscaping); |
| break; |
| } |
| case SILInstructionKind::PointerToAddressInst: { |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && |
| "Layout should be OneTypeOneOperand."); |
| bool isStrict = Attr & 0x01; |
| bool isInvariant = Attr & 0x02; |
| ResultInst = Builder.createPointerToAddress( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)), |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), |
| isStrict, isInvariant); |
| break; |
| } |
| case SILInstructionKind::DeallocExistentialBoxInst: { |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && |
| "Layout should be OneTypeOneOperand."); |
| ResultInst = Builder.createDeallocExistentialBox( |
| Loc, MF->getType(TyID)->getCanonicalType(), |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn))); |
| break; |
| |
| } |
| |
| case SILInstructionKind::RefToBridgeObjectInst: { |
| auto RefTy = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| auto Ref = getLocalValue(ValID, RefTy); |
| auto BitsTy = |
| getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2, Fn); |
| auto Bits = getLocalValue(ValID2, BitsTy); |
| |
| ResultInst = Builder.createRefToBridgeObject(Loc, Ref, Bits); |
| break; |
| } |
| |
| case SILInstructionKind::ObjCProtocolInst: { |
| auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| auto Proto = MF->getDecl(ValID); |
| ResultInst = Builder.createObjCProtocol(Loc, cast<ProtocolDecl>(Proto), Ty); |
| break; |
| } |
| |
| case SILInstructionKind::InitExistentialAddrInst: |
| case SILInstructionKind::InitExistentialValueInst: |
| case SILInstructionKind::InitExistentialMetatypeInst: |
| case SILInstructionKind::InitExistentialRefInst: |
| case SILInstructionKind::AllocExistentialBoxInst: { |
| |
| auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| auto Ty2 = MF->getType(TyID2); |
| CanType ConcreteTy; |
| if (OpCode != SILInstructionKind::InitExistentialMetatypeInst) |
| ConcreteTy = MF->getType(ConcreteTyID)->getCanonicalType(); |
| SILValue operand; |
| if (OpCode != SILInstructionKind::AllocExistentialBoxInst) |
| operand = getLocalValue( |
| ValID, getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)); |
| |
| SmallVector<ProtocolConformanceRef, 2> conformances; |
| while (NumConformances--) { |
| auto conformance = MF->readConformance(SILCursor); |
| conformances.push_back(conformance); |
| } |
| |
| auto ctxConformances = MF->getContext().AllocateCopy(conformances); |
| |
| switch (OpCode) { |
| default: llvm_unreachable("Out of sync with parent switch"); |
| case SILInstructionKind::InitExistentialAddrInst: |
| ResultInst = Builder.createInitExistentialAddr(Loc, operand, ConcreteTy, |
| Ty, ctxConformances); |
| break; |
| case SILInstructionKind::InitExistentialValueInst: |
| ResultInst = Builder.createInitExistentialValue(Loc, Ty, ConcreteTy, |
| operand, ctxConformances); |
| break; |
| case SILInstructionKind::InitExistentialMetatypeInst: |
| ResultInst = Builder.createInitExistentialMetatype(Loc, operand, Ty, |
| ctxConformances); |
| break; |
| case SILInstructionKind::InitExistentialRefInst: |
| ResultInst = Builder.createInitExistentialRef(Loc, Ty, ConcreteTy, |
| operand, ctxConformances); |
| break; |
| case SILInstructionKind::AllocExistentialBoxInst: |
| ResultInst = Builder.createAllocExistentialBox(Loc, Ty, ConcreteTy, |
| ctxConformances); |
| break; |
| } |
| break; |
| } |
| case SILInstructionKind::AllocRefInst: |
| case SILInstructionKind::AllocRefDynamicInst: { |
| assert(RecordKind == SIL_ONE_TYPE_VALUES && |
| "Layout should be OneTypeValues."); |
| unsigned NumVals = ListOfValues.size(); |
| assert(NumVals >= 1 && "Not enough values"); |
| unsigned Flags = ListOfValues[0]; |
| bool isObjC = (bool)(Flags & 1); |
| bool canAllocOnStack = (bool)((Flags >> 1) & 1); |
| SILType ClassTy = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| SmallVector<SILValue, 4> Counts; |
| SmallVector<SILType, 4> TailTypes; |
| unsigned i = 1; |
| for (; i + 2 < NumVals; i += 3) { |
| SILType TailType = getSILType(MF->getType(ListOfValues[i]), |
| SILValueCategory::Object, Fn); |
| TailTypes.push_back(TailType); |
| SILType CountType = getSILType(MF->getType(ListOfValues[i + 2]), |
| SILValueCategory::Object, Fn); |
| SILValue CountVal = getLocalValue(ListOfValues[i+1], CountType); |
| Counts.push_back(CountVal); |
| } |
| if (OpCode == SILInstructionKind::AllocRefDynamicInst) { |
| assert(i + 2 == NumVals); |
| assert(!canAllocOnStack); |
| SILType MetadataType = getSILType(MF->getType(ListOfValues[i+1]), |
| SILValueCategory::Object, Fn); |
| SILValue MetadataOp = getLocalValue(ListOfValues[i], MetadataType); |
| ResultInst = Builder.createAllocRefDynamic(Loc, MetadataOp, ClassTy, |
| isObjC, TailTypes, Counts); |
| } else { |
| assert(i == NumVals); |
| ResultInst = Builder.createAllocRef(Loc, ClassTy, isObjC, canAllocOnStack, |
| TailTypes, Counts); |
| } |
| break; |
| } |
| case SILInstructionKind::ApplyInst: |
| case SILInstructionKind::BeginApplyInst: { |
| // Format: attributes such as transparent, the callee's type, a value for |
| // the callee and a list of values for the arguments. Each value in the list |
| // is represented with 2 IDs: ValueID and ValueResultNumber. |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| SILType FnTy = getSILType(Ty, SILValueCategory::Object, Fn); |
| SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object, Fn); |
| SILFunctionConventions substConventions(SubstFnTy.castTo<SILFunctionType>(), |
| Builder.getModule()); |
| assert(substConventions.getNumSILArguments() == ListOfValues.size() |
| && "Argument number mismatch in ApplyInst."); |
| SmallVector<SILValue, 4> Args; |
| for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) |
| Args.push_back(getLocalValue(ListOfValues[I], |
| substConventions.getSILArgumentType( |
| I, Builder.getTypeExpansionContext()))); |
| SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs); |
| |
| if (OpCode == SILInstructionKind::ApplyInst) { |
| ResultInst = |
| Builder.createApply(Loc, getLocalValue(ValID, FnTy), Substitutions, |
| Args, IsNonThrowingApply != 0); |
| } else { |
| ResultInst = Builder.createBeginApply(Loc, getLocalValue(ValID, FnTy), |
| Substitutions, Args, |
| IsNonThrowingApply != 0); |
| } |
| break; |
| } |
| case SILInstructionKind::TryApplyInst: { |
| // Format: attributes such as transparent, the callee's type, a value for |
| // the callee and a list of values for the arguments. Each value in the list |
| // is represented with 2 IDs: ValueID and ValueResultNumber. The final |
| // two values in the list are the basic block identifiers. |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| SILType FnTy = getSILType(Ty, SILValueCategory::Object, Fn); |
| SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object, Fn); |
| |
| SILBasicBlock *errorBB = getBBForReference(Fn, ListOfValues.back()); |
| ListOfValues = ListOfValues.drop_back(); |
| SILBasicBlock *normalBB = getBBForReference(Fn, ListOfValues.back()); |
| ListOfValues = ListOfValues.drop_back(); |
| |
| SILFunctionConventions substConventions(SubstFnTy.castTo<SILFunctionType>(), |
| Builder.getModule()); |
| assert(substConventions.getNumSILArguments() == ListOfValues.size() |
| && "Argument number mismatch in ApplyInst."); |
| SmallVector<SILValue, 4> Args; |
| for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) |
| Args.push_back(getLocalValue(ListOfValues[I], |
| substConventions.getSILArgumentType( |
| I, Builder.getTypeExpansionContext()))); |
| SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs); |
| |
| ResultInst = Builder.createTryApply(Loc, getLocalValue(ValID, FnTy), |
| Substitutions, Args, normalBB, errorBB); |
| break; |
| } |
| case SILInstructionKind::PartialApplyInst: { |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| SILType FnTy = getSILType(Ty, SILValueCategory::Object, Fn); |
| SILType closureTy = getSILType(Ty2, SILValueCategory::Object, Fn); |
| |
| SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs); |
| |
| auto SubstFnTy = SILType::getPrimitiveObjectType( |
| FnTy.castTo<SILFunctionType>()->substGenericArgs( |
| Builder.getModule(), Substitutions, |
| Builder.getTypeExpansionContext())); |
| SILFunctionConventions fnConv(SubstFnTy.castTo<SILFunctionType>(), |
| Builder.getModule()); |
| |
| unsigned numArgs = fnConv.getNumSILArguments(); |
| assert(numArgs >= ListOfValues.size() |
| && "Argument number mismatch in PartialApplyInst."); |
| |
| SILValue FnVal = getLocalValue(ValID, FnTy); |
| SmallVector<SILValue, 4> Args; |
| unsigned unappliedArgs = numArgs - ListOfValues.size(); |
| for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) |
| Args.push_back(getLocalValue( |
| ListOfValues[I], |
| fnConv.getSILArgumentType(I + unappliedArgs, |
| Builder.getTypeExpansionContext()))); |
| auto onStack = closureTy.castTo<SILFunctionType>()->isNoEscape() |
| ? PartialApplyInst::OnStackKind::OnStack |
| : PartialApplyInst::OnStackKind::NotOnStack; |
| // FIXME: Why the arbitrary order difference in IRBuilder type argument? |
| ResultInst = Builder.createPartialApply( |
| Loc, FnVal, Substitutions, Args, |
| closureTy.castTo<SILFunctionType>()->getCalleeConvention(), onStack); |
| break; |
| } |
| case SILInstructionKind::BuiltinInst: { |
| auto ASTTy = MF->getType(TyID); |
| auto ResultTy = getSILType(ASTTy, (SILValueCategory)(unsigned)TyID2, Fn); |
| SmallVector<SILValue, 4> Args; |
| for (unsigned i = 0, e = ListOfValues.size(); i < e; i += 3) { |
| auto ArgASTTy = MF->getType(ListOfValues[i+1]); |
| auto ArgTy = getSILType( |
| ArgASTTy, (SILValueCategory)(unsigned)ListOfValues[i + 2], Fn); |
| Args.push_back(getLocalValue(ListOfValues[i], ArgTy)); |
| } |
| SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs); |
| Identifier Name = MF->getIdentifier(ValID); |
| |
| ResultInst = |
| Builder.createBuiltin(Loc, Name, ResultTy, Substitutions, Args); |
| break; |
| } |
| case SILInstructionKind::AllocGlobalInst: { |
| // Format: Name and type. Use SILOneOperandLayout. |
| StringRef Name = MF->getIdentifierText(ValID); |
| |
| // Find the global variable. |
| SILGlobalVariable *g = getGlobalForReference(Name); |
| assert(g && "Can't deserialize global variable"); |
| |
| ResultInst = Builder.createAllocGlobal(Loc, g); |
| break; |
| } |
| case SILInstructionKind::GlobalAddrInst: |
| case SILInstructionKind::GlobalValueInst: { |
| // Format: Name and type. Use SILOneOperandLayout. |
| auto Ty = MF->getType(TyID); |
| StringRef Name = MF->getIdentifierText(ValID); |
| |
| // Find the global variable. |
| SILGlobalVariable *g = getGlobalForReference(Name); |
| assert(g && "Can't deserialize global variable"); |
| SILType expectedType = |
| (OpCode == SILInstructionKind::GlobalAddrInst |
| ? g->getLoweredTypeInContext(TypeExpansionContext(*Fn)) |
| .getAddressType() |
| : g->getLoweredTypeInContext(TypeExpansionContext(*Fn))); |
| assert(expectedType == getSILType(Ty, (SILValueCategory)TyCategory, Fn) && |
| "Type of a global variable does not match GlobalAddr."); |
| (void)Ty; |
| (void)expectedType; |
| if (OpCode == SILInstructionKind::GlobalAddrInst) { |
| ResultInst = Builder.createGlobalAddr(Loc, g); |
| } else { |
| ResultInst = Builder.createGlobalValue(Loc, g); |
| } |
| break; |
| } |
| case SILInstructionKind::BaseAddrForOffsetInst: |
| assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); |
| ResultInst = Builder.createBaseAddrForOffset( |
| Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| break; |
| case SILInstructionKind::DeallocStackInst: { |
| auto Ty = MF->getType(TyID); |
| ResultInst = Builder.createDeallocStack( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn))); |
| break; |
| } |
| case SILInstructionKind::DeallocRefInst: { |
| auto Ty = MF->getType(TyID); |
| bool OnStack = (bool)Attr; |
| ResultInst = Builder.createDeallocRef( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| OnStack); |
| break; |
| } |
| case SILInstructionKind::DeallocPartialRefInst: { |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| ResultInst = Builder.createDeallocPartialRef( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| getLocalValue(ValID2, |
| getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); |
| break; |
| } |
| case SILInstructionKind::FunctionRefInst: { |
| auto Ty = MF->getType(TyID); |
| StringRef FuncName = MF->getIdentifierText(ValID); |
| ResultInst = Builder.createFunctionRef( |
| Loc, |
| getFuncForReference( |
| FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr))); |
| break; |
| } |
| case SILInstructionKind::DynamicFunctionRefInst: { |
| auto Ty = MF->getType(TyID); |
| StringRef FuncName = MF->getIdentifierText(ValID); |
| ResultInst = Builder.createDynamicFunctionRef( |
| Loc, |
| getFuncForReference( |
| FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr))); |
| break; |
| } |
| case SILInstructionKind::PreviousDynamicFunctionRefInst: { |
| auto Ty = MF->getType(TyID); |
| StringRef FuncName = MF->getIdentifierText(ValID); |
| ResultInst = Builder.createPreviousDynamicFunctionRef( |
| Loc, |
| getFuncForReference( |
| FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr))); |
| break; |
| } |
| case SILInstructionKind::MarkDependenceInst: { |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| ResultInst = Builder.createMarkDependence( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| getLocalValue(ValID2, |
| getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); |
| break; |
| } |
| case SILInstructionKind::CopyBlockWithoutEscapingInst: { |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| ResultInst = Builder.createCopyBlockWithoutEscaping( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| getLocalValue(ValID2, |
| getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); |
| break; |
| } |
| case SILInstructionKind::IndexAddrInst: { |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| ResultInst = Builder.createIndexAddr( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| getLocalValue(ValID2, |
| getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); |
| break; |
| } |
| case SILInstructionKind::TailAddrInst: { |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| auto ResultTy = MF->getType(TyID3); |
| ResultInst = Builder.createTailAddr( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, SILValueCategory::Address, Fn)), |
| getLocalValue(ValID2, getSILType(Ty2, SILValueCategory::Object, Fn)), |
| getSILType(ResultTy, SILValueCategory::Address, Fn)); |
| break; |
| } |
| case SILInstructionKind::IndexRawPointerInst: { |
| auto Ty = MF->getType(TyID); |
| auto Ty2 = MF->getType(TyID2); |
| ResultInst = Builder.createIndexRawPointer( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| getLocalValue(ValID2, |
| getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); |
| break; |
| } |
| case SILInstructionKind::IntegerLiteralInst: { |
| auto Ty = MF->getType(TyID); |
| auto intTy = Ty->castTo<AnyBuiltinIntegerType>(); |
| StringRef text = MF->getIdentifierText(ValID); |
| bool negate = text[0] == '-'; |
| if (negate) text = text.drop_front(); |
| APInt value = intTy->getWidth().parse(text, 10, negate); |
| ResultInst = Builder.createIntegerLiteral( |
| Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), value); |
| break; |
| } |
| case SILInstructionKind::FloatLiteralInst: { |
| auto Ty = MF->getType(TyID); |
| auto floatTy = Ty->castTo<BuiltinFloatType>(); |
| StringRef StringVal = MF->getIdentifierText(ValID); |
| // Build APInt from string. |
| APInt bits(floatTy->getBitWidth(), StringVal, 16); |
| if (bits.getBitWidth() != floatTy->getBitWidth()) |
| bits = bits.zextOrTrunc(floatTy->getBitWidth()); |
| |
| APFloat value(floatTy->getAPFloatSemantics(), bits); |
| |
| ResultInst = Builder.createFloatLiteral( |
| Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), value); |
| break; |
| } |
| case SILInstructionKind::StringLiteralInst: { |
| StringRef StringVal = MF->getIdentifierText(ValID); |
| auto encoding = fromStableStringEncoding(Attr); |
| if (!encoding) return true; |
| ResultInst = |
| Builder.createStringLiteral(Loc, StringVal, encoding.getValue()); |
| break; |
| } |
| case SILInstructionKind::CondFailInst: { |
| SILValue Op = getLocalValue( |
| ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| StringRef StringVal = MF->getIdentifierText(ValID2); |
| ResultInst = Builder.createCondFail(Loc, Op, StringVal); |
| break; |
| } |
| case SILInstructionKind::MarkFunctionEscapeInst: { |
| // Format: a list of typed values. A typed value is expressed by 4 IDs: |
| // TypeID, TypeCategory, ValueID, ValueResultNumber. |
| SmallVector<SILValue, 4> OpList; |
| for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) { |
| auto EltTy = MF->getType(ListOfValues[I]); |
| OpList.push_back(getLocalValue( |
| ListOfValues[I + 2], |
| getSILType(EltTy, (SILValueCategory)ListOfValues[I + 1], Fn))); |
| } |
| ResultInst = Builder.createMarkFunctionEscape(Loc, OpList); |
| break; |
| } |
| // Checked Conversion instructions. |
| case SILInstructionKind::UnconditionalCheckedCastInst: { |
| SILType srcLoweredType = getSILType(MF->getType(ListOfValues[1]), |
| (SILValueCategory)ListOfValues[2], Fn); |
| SILValue src = getLocalValue(ListOfValues[0], srcLoweredType); |
| |
| SILType targetLoweredType = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| CanType targetFormalType = |
| MF->getType(ListOfValues[3])->getCanonicalType(); |
| ResultInst = Builder.createUnconditionalCheckedCast( |
| Loc, src, targetLoweredType, targetFormalType); |
| break; |
| } |
| |
| #define UNARY_INSTRUCTION(ID) \ |
| case SILInstructionKind::ID##Inst: \ |
| assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); \ |
| ResultInst = Builder.create##ID( \ |
| Loc, \ |
| getLocalValue(ValID, getSILType(MF->getType(TyID), \ |
| (SILValueCategory)TyCategory, Fn))); \ |
| break; |
| |
| #define REFCOUNTING_INSTRUCTION(ID) \ |
| case SILInstructionKind::ID##Inst: \ |
| assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); \ |
| ResultInst = Builder.create##ID( \ |
| Loc, \ |
| getLocalValue(ValID, getSILType(MF->getType(TyID), \ |
| (SILValueCategory)TyCategory, Fn)), \ |
| (Atomicity)Attr); \ |
| break; |
| |
| #define UNCHECKED_REF_STORAGE(Name, ...) \ |
| UNARY_INSTRUCTION(StrongCopy##Name##Value) |
| #define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ |
| REFCOUNTING_INSTRUCTION(Name##Retain) \ |
| REFCOUNTING_INSTRUCTION(Name##Release) \ |
| REFCOUNTING_INSTRUCTION(StrongRetain##Name) \ |
| UNARY_INSTRUCTION(StrongCopy##Name##Value) |
| #include "swift/AST/ReferenceStorage.def" |
| REFCOUNTING_INSTRUCTION(RetainValue) |
| REFCOUNTING_INSTRUCTION(RetainValueAddr) |
| REFCOUNTING_INSTRUCTION(UnmanagedRetainValue) |
| UNARY_INSTRUCTION(CopyValue) |
| UNARY_INSTRUCTION(DestroyValue) |
| REFCOUNTING_INSTRUCTION(ReleaseValue) |
| REFCOUNTING_INSTRUCTION(ReleaseValueAddr) |
| REFCOUNTING_INSTRUCTION(UnmanagedReleaseValue) |
| REFCOUNTING_INSTRUCTION(AutoreleaseValue) |
| REFCOUNTING_INSTRUCTION(UnmanagedAutoreleaseValue) |
| REFCOUNTING_INSTRUCTION(SetDeallocating) |
| UNARY_INSTRUCTION(DeinitExistentialAddr) |
| UNARY_INSTRUCTION(DeinitExistentialValue) |
| UNARY_INSTRUCTION(EndBorrow) |
| UNARY_INSTRUCTION(DestroyAddr) |
| UNARY_INSTRUCTION(Return) |
| UNARY_INSTRUCTION(Throw) |
| UNARY_INSTRUCTION(ClassifyBridgeObject) |
| UNARY_INSTRUCTION(ValueToBridgeObject) |
| UNARY_INSTRUCTION(FixLifetime) |
| UNARY_INSTRUCTION(EndLifetime) |
| UNARY_INSTRUCTION(CopyBlock) |
| UNARY_INSTRUCTION(LoadBorrow) |
| UNARY_INSTRUCTION(BeginBorrow) |
| REFCOUNTING_INSTRUCTION(StrongRetain) |
| REFCOUNTING_INSTRUCTION(StrongRelease) |
| UNARY_INSTRUCTION(IsUnique) |
| UNARY_INSTRUCTION(AbortApply) |
| UNARY_INSTRUCTION(EndApply) |
| UNARY_INSTRUCTION(HopToExecutor) |
| #undef UNARY_INSTRUCTION |
| #undef REFCOUNTING_INSTRUCTION |
| |
| case SILInstructionKind::IsEscapingClosureInst: { |
| assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); |
| unsigned verificationType = Attr; |
| ResultInst = Builder.createIsEscapingClosure( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID), |
| (SILValueCategory)TyCategory, Fn)), |
| verificationType); |
| break; |
| } |
| |
| case SILInstructionKind::BeginCOWMutationInst: { |
| assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); |
| unsigned isNative = Attr; |
| ResultInst = Builder.createBeginCOWMutation( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID), |
| (SILValueCategory)TyCategory, Fn)), |
| isNative != 0); |
| break; |
| } |
| |
| case SILInstructionKind::EndCOWMutationInst: { |
| assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); |
| unsigned keepUnique = Attr; |
| ResultInst = Builder.createEndCOWMutation( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID), |
| (SILValueCategory)TyCategory, Fn)), |
| keepUnique != 0); |
| break; |
| } |
| |
| case SILInstructionKind::DestructureTupleInst: { |
| assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); |
| SILValue Operand = getLocalValue( |
| ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| ResultInst = Builder.createDestructureTuple(Loc, Operand); |
| break; |
| } |
| case SILInstructionKind::DestructureStructInst: { |
| assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); |
| SILValue Operand = getLocalValue( |
| ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| ResultInst = Builder.createDestructureStruct(Loc, Operand); |
| break; |
| } |
| case SILInstructionKind::UncheckedOwnershipConversionInst: { |
| auto Ty = MF->getType(TyID); |
| auto ResultKind = ValueOwnershipKind(Attr); |
| ResultInst = Builder.createUncheckedOwnershipConversion( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| ResultKind); |
| break; |
| } |
| |
| case SILInstructionKind::LoadInst: { |
| auto Ty = MF->getType(TyID); |
| auto Qualifier = LoadOwnershipQualifier(Attr); |
| ResultInst = Builder.createLoad( |
| Loc, |
| getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| Qualifier); |
| break; |
| } |
| |
| #define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ |
| case SILInstructionKind::Load##Name##Inst: { \ |
| auto Ty = MF->getType(TyID); \ |
| bool isTake = (Attr > 0); \ |
| auto Val = getLocalValue( \ |
| ValID, getSILType(Ty, SILValueCategory(TyCategory), Fn)); \ |
| ResultInst = Builder.createLoad##Name(Loc, Val, IsTake_t(isTake)); \ |
| break; \ |
| } \ |
| case SILInstructionKind::Store##Name##Inst: { \ |
| auto Ty = MF->getType(TyID); \ |
| SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); \ |
| auto refType = addrType.castTo<Name##StorageType>(); \ |
| auto ValType = SILType::getPrimitiveObjectType(refType.getReferentType()); \ |
| bool isInit = (Attr > 0); \ |
| ResultInst = Builder.createStore##Name(Loc, getLocalValue(ValID, ValType), \ |
| getLocalValue(ValID2, addrType), \ |
| IsInitialization_t(isInit)); \ |
| break; \ |
| } |
| #include "swift/AST/ReferenceStorage.def" |
| case SILInstructionKind::MarkUninitializedInst: { |
| auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| auto Kind = (MarkUninitializedInst::Kind)Attr; |
| auto Val = getLocalValue(ValID, Ty); |
| ResultInst = Builder.createMarkUninitialized(Loc, Val, Kind); |
| break; |
| } |
| case SILInstructionKind::StoreInst: { |
| auto Ty = MF->getType(TyID); |
| SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); |
| SILType ValType = addrType.getObjectType(); |
| auto Qualifier = StoreOwnershipQualifier(Attr); |
| ResultInst = |
| Builder.createStore(Loc, getLocalValue(ValID, ValType), |
| getLocalValue(ValID2, addrType), Qualifier); |
| break; |
| } |
| case SILInstructionKind::StoreBorrowInst: { |
| auto Ty = MF->getType(TyID); |
| SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); |
| SILType ValType = addrType.getObjectType(); |
| ResultInst = Builder.createStoreBorrow(Loc, getLocalValue(ValID, ValType), |
| getLocalValue(ValID2, addrType)); |
| break; |
| } |
| case SILInstructionKind::BeginAccessInst: { |
| SILValue op = getLocalValue( |
| ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| auto accessKind = SILAccessKind(Attr & 0x3); |
| auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x3); |
| bool noNestedConflict = (Attr >> 4) & 0x01; |
| bool fromBuiltin = (Attr >> 5) & 0x01; |
| ResultInst = Builder.createBeginAccess(Loc, op, accessKind, enforcement, |
| noNestedConflict, fromBuiltin); |
| break; |
| } |
| case SILInstructionKind::EndAccessInst: { |
| SILValue op = getLocalValue( |
| ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| bool aborted = Attr & 0x1; |
| ResultInst = Builder.createEndAccess(Loc, op, aborted); |
| break; |
| } |
| case SILInstructionKind::BeginUnpairedAccessInst: { |
| SILValue source = getLocalValue( |
| ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| SILValue buffer = |
| getLocalValue(ValID2, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)); |
| auto accessKind = SILAccessKind(Attr & 0x3); |
| auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x03); |
| bool noNestedConflict = (Attr >> 4) & 0x01; |
| bool fromBuiltin = (Attr >> 5) & 0x01; |
| ResultInst = Builder.createBeginUnpairedAccess( |
| Loc, source, buffer, accessKind, enforcement, noNestedConflict, |
| fromBuiltin); |
| break; |
| } |
| case SILInstructionKind::EndUnpairedAccessInst: { |
| SILValue op = getLocalValue( |
| ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| bool aborted = Attr & 0x1; |
| auto enforcement = SILAccessEnforcement((Attr >> 1) & 0x03); |
| bool fromBuiltin = (Attr >> 3) & 0x01; |
| ResultInst = Builder.createEndUnpairedAccess(Loc, op, enforcement, aborted, |
| fromBuiltin); |
| break; |
| } |
| case SILInstructionKind::CopyAddrInst: { |
| auto Ty = MF->getType(TyID); |
| SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); |
| bool isInit = (Attr & 0x2) > 0; |
| bool isTake = (Attr & 0x1) > 0; |
| ResultInst = Builder.createCopyAddr( |
| Loc, getLocalValue(ValID, addrType), getLocalValue(ValID2, addrType), |
| IsTake_t(isTake), IsInitialization_t(isInit)); |
| break; |
| } |
| case SILInstructionKind::AssignInst: { |
| auto Ty = MF->getType(TyID); |
| SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); |
| SILType valType = addrType.getObjectType(); |
| auto qualifier = AssignOwnershipQualifier(Attr); |
| ResultInst = |
| Builder.createAssign(Loc, getLocalValue(ValID, valType), |
| getLocalValue(ValID2, addrType), qualifier); |
| break; |
| } |
| case SILInstructionKind::AssignByWrapperInst: |
| llvm_unreachable("not supported"); |
| case SILInstructionKind::BindMemoryInst: { |
| assert(RecordKind == SIL_ONE_TYPE_VALUES && |
| "Layout should be OneTypeValues."); |
| auto Ty = MF->getType(TyID); // BoundTy |
| ResultInst = Builder.createBindMemory( |
| Loc, |
| getLocalValue(ListOfValues[2], |
| getSILType(MF->getType(ListOfValues[0]), |
| (SILValueCategory)ListOfValues[1], Fn)), |
| getLocalValue(ListOfValues[5], |
| getSILType(MF->getType(ListOfValues[3]), |
| (SILValueCategory)ListOfValues[4], Fn)), |
| getSILType(Ty, (SILValueCategory)TyCategory, Fn)); |
| break; |
| } |
| case SILInstructionKind::StructElementAddrInst: |
| case SILInstructionKind::StructExtractInst: { |
| // Use SILOneValueOneOperandLayout. |
| VarDecl *Field = cast<VarDecl>(MF->getDecl(ValID)); |
| auto Ty = MF->getType(TyID); |
| auto Val = |
| getLocalValue(ValID2, getSILType(Ty, (SILValueCategory)TyCategory, Fn)); |
| auto ResultTy = Val->getType().getFieldType( |
| Field, SILMod, Builder.getTypeExpansionContext()); |
| if (OpCode == SILInstructionKind::StructElementAddrInst) |
| ResultInst = Builder.createStructElementAddr(Loc, Val, Field, |
| ResultTy.getAddressType()); |
| else |
| ResultInst = Builder.createStructExtract(Loc, Val, Field, |
| ResultTy.getObjectType()); |
| break; |
| } |
| case SILInstructionKind::StructInst: { |
| // Format: a type followed by a list of typed values. A typed value is |
| // expressed by 4 IDs: TypeID, TypeCategory, ValueID, ValueResultNumber. |
| auto Ty = MF->getType(TyID); |
| SmallVector<SILValue, 4> OpList; |
| for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) { |
| auto EltTy = MF->getType(ListOfValues[I]); |
| OpList.push_back(getLocalValue( |
| ListOfValues[I + 2], |
| getSILType(EltTy, (SILValueCategory)ListOfValues[I + 1], Fn))); |
| } |
| ResultInst = Builder.createStruct( |
| Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), OpList); |
| break; |
| } |
| case SILInstructionKind::TupleElementAddrInst: |
| case SILInstructionKind::TupleExtractInst: { |
| // Use OneTypeOneOperand layout where the field number is stored in TypeID. |
| auto Ty2 = MF->getType(TyID2); |
| SILType ST = getSILType(Ty2, (SILValueCategory)TyCategory2, Fn); |
| TupleType *TT = ST.castTo<TupleType>(); |
| |
| auto ResultTy = TT->getElement(TyID).getType(); |
| switch (OpCode) { |
| default: llvm_unreachable("Out of sync with parent switch"); |
| case SILInstructionKind::TupleElementAddrInst: |
| ResultInst = Builder.createTupleElementAddr( |
| Loc, getLocalValue(ValID, ST), TyID, |
| getSILType(ResultTy, SILValueCategory::Address, Fn)); |
| break; |
| case SILInstructionKind::TupleExtractInst: |
| ResultInst = Builder.createTupleExtract( |
| Loc, getLocalValue(ValID, ST), TyID, |
| getSILType(ResultTy, SILValueCategory::Object, Fn)); |
| break; |
| } |
| break; |
| } |
| case SILInstructionKind::TupleInst: { |
| // Format: a type followed by a list of values. A value is expressed by |
| // 2 IDs: ValueID, ValueResultNumber. |
| auto Ty = MF->getType(TyID); |
| TupleType *TT = Ty->castTo<TupleType>(); |
| assert(TT && "Type of a TupleInst should be TupleType"); |
| SmallVector<SILValue, 4> OpList; |
| for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) { |
| Type EltTy = TT->getElement(I).getType(); |
| OpList.push_back( |
| getLocalValue(ListOfValues[I], |
| getSILType(EltTy, SILValueCategory::Object, Fn))); |
| } |
| ResultInst = Builder.createTuple( |
| Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), OpList); |
| break; |
| } |
| case SILInstructionKind::ObjectInst: { |
| assert(RecordKind == SIL_ONE_TYPE_VALUES && |
| "Layout should be OneTypeValues."); |
| unsigned NumVals = ListOfValues.size(); |
| assert(NumVals >= 1 && "Not enough values"); |
| unsigned numBaseElements = ListOfValues[0]; |
| SILType ClassTy = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| SmallVector<SILValue, 4> elements; |
| for (unsigned i = 1; i < NumVals; i += 2) { |
| SILType elementType = getSILType(MF->getType(ListOfValues[i + 1]), |
| SILValueCategory::Object, Fn); |
| SILValue elementVal = getLocalValue(ListOfValues[i], elementType); |
| elements.push_back(elementVal); |
| } |
| ResultInst = Builder.createObject(Loc, ClassTy, elements, numBaseElements); |
| break; |
| } |
| case SILInstructionKind::BranchInst: { |
| SmallVector<SILValue, 4> Args; |
| for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) |
| Args.push_back( |
| getLocalValue(ListOfValues[I + 2], |
| getSILType(MF->getType(ListOfValues[I]), |
| (SILValueCategory)ListOfValues[I + 1], Fn))); |
| |
| ResultInst = Builder.createBranch(Loc, getBBForReference(Fn, TyID), Args); |
| break; |
| } |
| case SILInstructionKind::CondBranchInst: { |
| // Format: condition, true basic block ID, a list of arguments, false basic |
| // block ID, a list of arguments. Use SILOneTypeValuesLayout: the type is |
| // for condition, the list has value for condition, true basic block ID, |
| // false basic block ID, number of true arguments, and a list of true|false |
| // arguments. |
| SILValue Cond = getLocalValue( |
| ListOfValues[0], |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| |
| unsigned NumTrueArgs = ListOfValues[3]; |
| unsigned StartOfTrueArg = 4; |
| unsigned StartOfFalseArg = StartOfTrueArg + 3*NumTrueArgs; |
| SmallVector<SILValue, 4> TrueArgs; |
| for (unsigned I = StartOfTrueArg, E = StartOfFalseArg; I < E; I += 3) |
| TrueArgs.push_back( |
| getLocalValue(ListOfValues[I + 2], |
| getSILType(MF->getType(ListOfValues[I]), |
| (SILValueCategory)ListOfValues[I + 1], Fn))); |
| |
| SmallVector<SILValue, 4> FalseArgs; |
| for (unsigned I = StartOfFalseArg, E = ListOfValues.size(); I < E; I += 3) |
| FalseArgs.push_back( |
| getLocalValue(ListOfValues[I + 2], |
| getSILType(MF->getType(ListOfValues[I]), |
| (SILValueCategory)ListOfValues[I + 1], Fn))); |
| |
| ResultInst = Builder.createCondBranch( |
| Loc, Cond, getBBForReference(Fn, ListOfValues[1]), TrueArgs, |
| getBBForReference(Fn, ListOfValues[2]), FalseArgs); |
| break; |
| } |
| case SILInstructionKind::AwaitAsyncContinuationInst: { |
| // Format: continuation, resume block ID, error block ID if given |
| SILValue Cont = getLocalValue( |
| ListOfValues[0], |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| |
| SILBasicBlock *resultBB = getBBForReference(Fn, ListOfValues[1]); |
| SILBasicBlock *errorBB = nullptr; |
| if (ListOfValues.size() >= 3) { |
| errorBB = getBBForReference(Fn, ListOfValues[2]); |
| } |
| |
| ResultInst = Builder.createAwaitAsyncContinuation(Loc, Cont, resultBB, errorBB); |
| break; |
| } |
| case SILInstructionKind::SwitchEnumInst: |
| case SILInstructionKind::SwitchEnumAddrInst: { |
| // Format: condition, a list of cases (EnumElementDecl + Basic Block ID), |
| // default basic block ID. Use SILOneTypeValuesLayout: the type is |
| // for condition, the list has value for condition, hasDefault, default |
| // basic block ID, a list of (DeclID, BasicBlock ID). |
| SILValue Cond = getLocalValue( |
| ListOfValues[0], |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| |
| SILBasicBlock *DefaultBB = nullptr; |
| if (ListOfValues[1]) |
| DefaultBB = getBBForReference(Fn, ListOfValues[2]); |
| |
| SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 4> CaseBBs; |
| for (unsigned I = 3, E = ListOfValues.size(); I < E; I += 2) { |
| CaseBBs.push_back( {cast<EnumElementDecl>(MF->getDecl(ListOfValues[I])), |
| getBBForReference(Fn, ListOfValues[I+1])} ); |
| } |
| if (OpCode == SILInstructionKind::SwitchEnumInst) |
| ResultInst = Builder.createSwitchEnum(Loc, Cond, DefaultBB, CaseBBs); |
| else |
| ResultInst = Builder.createSwitchEnumAddr(Loc, Cond, DefaultBB, CaseBBs); |
| break; |
| } |
| case SILInstructionKind::SelectEnumInst: |
| case SILInstructionKind::SelectEnumAddrInst: { |
| // Format: condition, a list of cases (EnumElementDecl + Value ID), |
| // default value ID. Use SILOneTypeValuesLayout: the type is |
| // for condition, the list has value for condition, result type, |
| // hasDefault, default |
| // basic block ID, a list of (DeclID, BasicBlock ID). |
| SILValue Cond = getLocalValue(ListOfValues[0], |
| getSILType(MF->getType(TyID), |
| (SILValueCategory)TyCategory, Fn)); |
| |
| Type ResultLoweredTy = MF->getType(ListOfValues[1]); |
| SILValueCategory ResultCategory = (SILValueCategory)ListOfValues[2]; |
| SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory, Fn); |
| |
| SILValue DefaultVal = nullptr; |
| if (ListOfValues[3]) |
| DefaultVal = getLocalValue(ListOfValues[4], ResultTy); |
| |
| SmallVector<std::pair<EnumElementDecl*, SILValue>, 4> CaseVals; |
| for (unsigned I = 5, E = ListOfValues.size(); I < E; I += 2) { |
| auto Value = getLocalValue(ListOfValues[I+1], ResultTy); |
| CaseVals.push_back({cast<EnumElementDecl>(MF->getDecl(ListOfValues[I])), |
| Value}); |
| } |
| if (OpCode == SILInstructionKind::SelectEnumInst) |
| ResultInst = |
| Builder.createSelectEnum(Loc, Cond, ResultTy, DefaultVal, CaseVals); |
| else |
| ResultInst = Builder.createSelectEnumAddr(Loc, Cond, ResultTy, DefaultVal, |
| CaseVals); |
| break; |
| } |
| case SILInstructionKind::SwitchValueInst: { |
| // Format: condition, a list of cases (Value ID + Basic Block ID), |
| // default basic block ID. Use SILOneTypeValuesLayout: the type is |
| // for condition, the list contains value for condition, hasDefault, default |
| // basic block ID, a list of (Value ID, BasicBlock ID). |
| SILType ResultTy = getSILType(MF->getType(TyID), |
| (SILValueCategory)TyCategory, Fn); |
| SILValue Cond = getLocalValue( |
| ListOfValues[0], |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| |
| SILBasicBlock *DefaultBB = nullptr; |
| if (ListOfValues[1]) |
| DefaultBB = getBBForReference(Fn, ListOfValues[2]); |
| |
| SmallVector<std::pair<SILValue, SILBasicBlock*>, 4> CaseBBs; |
| for (unsigned I = 3, E = ListOfValues.size(); I < E; I += 2) { |
| auto value = getLocalValue(ListOfValues[I], ResultTy); |
| CaseBBs.push_back( {value, getBBForReference(Fn, ListOfValues[I+1])} ); |
| } |
| ResultInst = Builder.createSwitchValue(Loc, Cond, DefaultBB, CaseBBs); |
| break; |
| } |
| case SILInstructionKind::SelectValueInst: { |
| // Format: condition, a list of cases (ValueID + Value ID), |
| // default value ID. Use SILOneTypeValuesLayout: the type is |
| // for condition, the list has value for condition, result type, |
| // hasDefault, default, |
| // basic block ID, a list of (Value ID, Value ID). |
| SILValue Cond = getLocalValue( |
| ListOfValues[0], |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| |
| Type ResultLoweredTy = MF->getType(ListOfValues[1]); |
| SILValueCategory ResultCategory = (SILValueCategory)ListOfValues[2]; |
| SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory, Fn); |
| |
| SILValue DefaultVal = nullptr; |
| if (ListOfValues[3]) |
| DefaultVal = getLocalValue(ListOfValues[4], ResultTy); |
| |
| SmallVector<std::pair<SILValue, SILValue>, 4> CaseValuesAndResults; |
| for (unsigned I = 5, E = ListOfValues.size(); I < E; I += 2) { |
| auto CaseValue = getLocalValue(ListOfValues[I], Cond->getType()); |
| auto Result = getLocalValue(ListOfValues[I+1], ResultTy); |
| CaseValuesAndResults.push_back({CaseValue, Result}); |
| } |
| |
| ResultInst = Builder.createSelectValue(Loc, Cond, ResultTy, DefaultVal, |
| CaseValuesAndResults); |
| break; |
| } |
| case SILInstructionKind::EnumInst: { |
| // Format: a type, an operand and a decl ID. Use SILTwoOperandsLayout: type, |
| // (DeclID + hasOperand), and an operand. |
| SILValue Operand; |
| if (Attr) |
| Operand = |
| getLocalValue(ValID2, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)); |
| ResultInst = Builder.createEnum( |
| Loc, Operand, cast<EnumElementDecl>(MF->getDecl(ValID)), |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); |
| break; |
| } |
| case SILInstructionKind::InitEnumDataAddrInst: { |
| // Use SILOneValueOneOperandLayout. |
| EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID)); |
| SILType OperandTy = getSILType(MF->getType(TyID), |
| (SILValueCategory) TyCategory, Fn); |
| SILType ResultTy = OperandTy.getEnumElementType( |
| Elt, SILMod, Builder.getTypeExpansionContext()); |
| ResultInst = Builder.createInitEnumDataAddr( |
| Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy); |
| break; |
| } |
| case SILInstructionKind::UncheckedEnumDataInst: { |
| // Use SILOneValueOneOperandLayout. |
| EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID)); |
| SILType OperandTy = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| SILType ResultTy = OperandTy.getEnumElementType( |
| Elt, SILMod, Builder.getTypeExpansionContext()); |
| ResultInst = Builder.createUncheckedEnumData( |
| Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy); |
| break; |
| } |
| case SILInstructionKind::UncheckedTakeEnumDataAddrInst: { |
| // Use SILOneValueOneOperandLayout. |
| EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID)); |
| SILType OperandTy = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| SILType ResultTy = OperandTy.getEnumElementType( |
| Elt, SILMod, Builder.getTypeExpansionContext()); |
| ResultInst = Builder.createUncheckedTakeEnumDataAddr( |
| Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy); |
| break; |
| } |
| case SILInstructionKind::InjectEnumAddrInst: { |
| // Use SILOneValueOneOperandLayout. |
| EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID)); |
| auto Ty = MF->getType(TyID); |
| ResultInst = Builder.createInjectEnumAddr( |
| Loc, |
| getLocalValue(ValID2, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), |
| Elt); |
| break; |
| } |
| case SILInstructionKind::RefElementAddrInst: { |
| // Use SILOneValueOneOperandLayout. |
| VarDecl *Field = cast<VarDecl>(MF->getDecl(ValID)); |
| auto Ty = MF->getType(TyID); |
| auto Val = getLocalValue(ValID2, |
| getSILType(Ty, (SILValueCategory)TyCategory, Fn)); |
| auto ResultTy = Val->getType().getFieldType( |
| Field, SILMod, Builder.getTypeExpansionContext()); |
| ResultInst = Builder.createRefElementAddr(Loc, Val, Field, ResultTy, |
| /*Immutable*/ Attr & 0x1); |
| break; |
| } |
| case SILInstructionKind::RefTailAddrInst: { |
| assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && |
| "Layout should be OneTypeOneOperand."); |
| assert((SILValueCategory)TyCategory == SILValueCategory::Address); |
| ResultInst = Builder.createRefTailAddr( |
| Loc, |
| getLocalValue(ValID, getSILType(MF->getType(TyID2), |
| (SILValueCategory)TyCategory2, Fn)), |
| getSILType(MF->getType(TyID), SILValueCategory::Address, Fn), |
| /*Immutable*/ Attr & 0x1); |
| break; |
| } |
| case SILInstructionKind::ClassMethodInst: |
| case SILInstructionKind::SuperMethodInst: |
| case SILInstructionKind::ObjCMethodInst: |
| case SILInstructionKind::ObjCSuperMethodInst: { |
| // Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout: |
| // type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel), and an operand. |
| unsigned NextValueIndex = 0; |
| SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); |
| SILType Ty = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| assert(ListOfValues.size() >= NextValueIndex + 2 && |
| "Out of entries for MethodInst"); |
| SILType operandTy = |
| getSILType(MF->getType(ListOfValues[NextValueIndex]), |
| (SILValueCategory)ListOfValues[NextValueIndex + 1], Fn); |
| NextValueIndex += 2; |
| |
| switch (OpCode) { |
| default: llvm_unreachable("Out of sync with parent switch"); |
| case SILInstructionKind::ClassMethodInst: |
| ResultInst = Builder.createClassMethod( |
| Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef, |
| Ty); |
| break; |
| case SILInstructionKind::SuperMethodInst: |
| ResultInst = Builder.createSuperMethod( |
| Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef, |
| Ty); |
| break; |
| case SILInstructionKind::ObjCMethodInst: |
| ResultInst = Builder.createObjCMethod( |
| Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef, |
| Ty); |
| break; |
| case SILInstructionKind::ObjCSuperMethodInst: |
| ResultInst = Builder.createObjCSuperMethod( |
| Loc, getLocalValue(ListOfValues[NextValueIndex], operandTy), DRef, |
| Ty); |
| break; |
| } |
| break; |
| } |
| case SILInstructionKind::WitnessMethodInst: { |
| unsigned NextValueIndex = 0; |
| SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); |
| assert(ListOfValues.size() >= NextValueIndex && |
| "Out of entries for MethodInst"); |
| |
| CanType Ty = MF->getType(TyID)->getCanonicalType(); |
| SILType OperandTy = |
| getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2, Fn); |
| |
| auto Conformance = MF->readConformance(SILCursor); |
| // Read the optional opened existential. |
| SILValue ExistentialOperand; |
| if (TyID3) { |
| SILType ExistentialOperandTy = |
| getSILType(MF->getType(TyID3), (SILValueCategory)TyCategory3, Fn); |
| if (ValID3) |
| ExistentialOperand = getLocalValue(ValID3, ExistentialOperandTy); |
| } |
| ResultInst = |
| Builder.createWitnessMethod(Loc, Ty, Conformance, DRef, OperandTy); |
| break; |
| } |
| case SILInstructionKind::DynamicMethodBranchInst: { |
| // Format: a typed value, a SILDeclRef, a BasicBlock ID for method, |
| // a BasicBlock ID for no method. Use SILOneTypeValuesLayout. |
| unsigned NextValueIndex = 1; |
| SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); |
| assert(ListOfValues.size() == NextValueIndex + 2 && |
| "Wrong number of entries for DynamicMethodBranchInst"); |
| ResultInst = Builder.createDynamicMethodBranch( |
| Loc, |
| getLocalValue( |
| ListOfValues[0], |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)), |
| DRef, getBBForReference(Fn, ListOfValues[NextValueIndex]), |
| getBBForReference(Fn, ListOfValues[NextValueIndex + 1])); |
| break; |
| } |
| case SILInstructionKind::CheckedCastBranchInst: { |
| // Format: the cast kind, a typed value, a BasicBlock ID for success, |
| // a BasicBlock ID for failure. Uses SILOneTypeValuesLayout. |
| bool isExact = ListOfValues[0] != 0; |
| SILType opTy = getSILType(MF->getType(ListOfValues[2]), |
| (SILValueCategory)ListOfValues[3], Fn); |
| SILValue op = getLocalValue(ListOfValues[1], opTy); |
| SILType targetLoweredType = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| CanType targetFormalType = |
| MF->getType(ListOfValues[4])->getCanonicalType(); |
| auto *successBB = getBBForReference(Fn, ListOfValues[5]); |
| auto *failureBB = getBBForReference(Fn, ListOfValues[6]); |
| |
| ResultInst = |
| Builder.createCheckedCastBranch(Loc, isExact, op, targetLoweredType, |
| targetFormalType, successBB, failureBB); |
| break; |
| } |
| case SILInstructionKind::CheckedCastValueBranchInst: { |
| CanType srcFormalType = MF->getType(ListOfValues[0])->getCanonicalType(); |
| SILType srcLoweredType = getSILType(MF->getType(ListOfValues[2]), |
| (SILValueCategory)ListOfValues[3], Fn); |
| SILValue op = getLocalValue(ListOfValues[1], srcLoweredType); |
| SILType targetLoweredType = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| CanType targetFormalType = |
| MF->getType(ListOfValues[4])->getCanonicalType(); |
| auto *successBB = getBBForReference(Fn, ListOfValues[5]); |
| auto *failureBB = getBBForReference(Fn, ListOfValues[6]); |
| |
| ResultInst = Builder.createCheckedCastValueBranch( |
| Loc, op, srcFormalType, targetLoweredType, targetFormalType, successBB, |
| failureBB); |
| break; |
| } |
| case SILInstructionKind::UnconditionalCheckedCastValueInst: { |
| CanType srcFormalType = MF->getType(ListOfValues[0])->getCanonicalType(); |
| SILType srcLoweredType = getSILType(MF->getType(ListOfValues[2]), |
| (SILValueCategory)ListOfValues[3], Fn); |
| SILValue src = getLocalValue(ListOfValues[1], srcLoweredType); |
| |
| SILType targetLoweredType = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| CanType targetFormalType = MF->getType(ListOfValues[4])->getCanonicalType(); |
| ResultInst = Builder.createUnconditionalCheckedCastValue( |
| Loc, src, srcFormalType, targetLoweredType, targetFormalType); |
| break; |
| } |
| case SILInstructionKind::UnconditionalCheckedCastAddrInst: { |
| // ignore attr. |
| CanType srcFormalType = MF->getType(ListOfValues[0])->getCanonicalType(); |
| SILType srcLoweredType = getSILType(MF->getType(ListOfValues[2]), |
| (SILValueCategory)ListOfValues[3], Fn); |
| SILValue src = getLocalValue(ListOfValues[1], srcLoweredType); |
| |
| CanType targetFormalType = MF->getType(ListOfValues[4])->getCanonicalType(); |
| SILType targetLoweredType = |
| getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); |
| SILValue dest = getLocalValue(ListOfValues[5], targetLoweredType); |
| |
| ResultInst = Builder.createUnconditionalCheckedCastAddr( |
| Loc, src, srcFormalType, dest, targetFormalType); |
| break; |
| } |
| case SILInstructionKind::CheckedCastAddrBranchInst: { |
| CastConsumptionKind consumption = getCastConsumptionKind(ListOfValues[0]); |
| |
| CanType srcFormalType = MF->getType(ListOfValues[1])->getCanonicalType(); |
| SILType srcLoweredType = getSILType(MF->getType(ListOfValues[3]), |
| (SILValueCategory)ListOfValues[4], Fn); |
| SILValue src = getLocalValue(ListOfValues[2], srcLoweredType); |
|