mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Whenever we have a reference to a foreign function/variable in SIL, use a mangled name at the SIL level with the C name in the asmname attribute. The expands the use of asmname to three kinds of cases that it hadn't been used in yet: * Declarations imported from C headers/modules * @_cdecl @implementation of C headers/modules * @_cdecl functions in general Some code within the SIL pipeline makes assumptions that the C names of various runtime functions are reflected at the SIL level. For example, the linking of Embedded Swift runtime functions is done by-name, and some of those names refer to C functions (like `swift_retain`) and others refer to Swift functions that use `@_silgen_name` (like `swift_getDefaultExecutor`). Extend the serialized module format to include a table that maps from the asmname of functions/variables over to their mangled names, so we can look up functions by asmname if we want. These tables could also be used for checking for declarations that conflict on their asmname in the future. Right now, we leave it up to LLVM or the linker to do the checking. `@_silgen_name` is not affected by these changes, nor should it be: that hidden feature is specifically meant to affect the name at the SIL level. The vast majority of test changes are SIL tests where we had expected to see the C/C++/Objective-C names in the tests for references to foreign entities, and now we see Swift mangled names (ending in To). The SIL declarations themselves will have a corresponding asmname. Notably, the IRGen tests have *not* changed, because we generally the same IR as before. It's only the modeling at the SIL lever that has changed. Another part of rdar://137014448.
1204 lines
47 KiB
C++
1204 lines
47 KiB
C++
//===--- SILModule.h - Defines the SILModule class --------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the SILModule class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_SILMODULE_H
|
|
#define SWIFT_SIL_SILMODULE_H
|
|
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/Builtins.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/SILLayout.h"
|
|
#include "swift/AST/SILOptions.h"
|
|
#include "swift/Basic/IndexTrie.h"
|
|
#include "swift/Basic/LangOptions.h"
|
|
#include "swift/Basic/ProfileCounter.h"
|
|
#include "swift/Basic/Range.h"
|
|
#include "swift/SIL/Notifications.h"
|
|
#include "swift/SIL/SILCoverageMap.h"
|
|
#include "swift/SIL/SILDeclRef.h"
|
|
#include "swift/SIL/SILDefaultOverrideTable.h"
|
|
#include "swift/SIL/SILDefaultWitnessTable.h"
|
|
#include "swift/SIL/SILDifferentiabilityWitness.h"
|
|
#include "swift/SIL/SILFunction.h"
|
|
#include "swift/SIL/SILGlobalVariable.h"
|
|
#include "swift/SIL/SILMoveOnlyDeinit.h"
|
|
#include "swift/SIL/SILPrintContext.h"
|
|
#include "swift/SIL/SILProperty.h"
|
|
#include "swift/SIL/SILType.h"
|
|
#include "swift/SIL/SILVTable.h"
|
|
#include "swift/SIL/SILWitnessTable.h"
|
|
#include "swift/SIL/TypeLowering.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
#include "llvm/ADT/MapVector.h"
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
#include "llvm/ADT/SetVector.h"
|
|
#include "llvm/ADT/STLFunctionalExtras.h"
|
|
#include "llvm/ADT/ilist.h"
|
|
#include "llvm/ProfileData/InstrProfReader.h"
|
|
#include "llvm/Support/Allocator.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <functional>
|
|
|
|
namespace llvm {
|
|
namespace yaml {
|
|
class Output;
|
|
} // end namespace yaml
|
|
} // end namespace llvm
|
|
|
|
namespace swift {
|
|
|
|
/// The payload for the FixedSizeSlab.
|
|
/// This is a super-class rather than a member of FixedSizeSlab to make swift
|
|
/// bridging easier.
|
|
class FixedSizeSlabPayload {
|
|
public:
|
|
/// The capacity of the payload.
|
|
static constexpr size_t capacity = 64 * sizeof(uintptr_t);
|
|
|
|
private:
|
|
friend class SILModule;
|
|
|
|
/// The magic number which is stored in overflowGuard.
|
|
static constexpr uintptr_t magicNumber = (uintptr_t)0xdeadbeafdeadbeafull;
|
|
|
|
/// The payload.
|
|
char data[capacity];
|
|
|
|
/// Used for a cheap buffer overflow check - in the spirit of libgmalloc.
|
|
uintptr_t overflowGuard = magicNumber;
|
|
|
|
public:
|
|
void operator=(const FixedSizeSlabPayload &) = delete;
|
|
void operator delete(void *Ptr, size_t) = delete;
|
|
|
|
/// Returns the payload pointing to \p T.
|
|
template<typename T> T *dataFor() { return (T *)(&data[0]); }
|
|
|
|
/// Returns the payload pointing to const \p T
|
|
template<typename T> const T *dataFor() const { return (const T *)(&data[0]); }
|
|
};
|
|
|
|
/// A fixed size slab of memory, which can be allocated and freed by the
|
|
/// SILModule at (basically) zero cost.
|
|
/// See SILModule::allocSlab().
|
|
class FixedSizeSlab : public llvm::ilist_node<FixedSizeSlab>,
|
|
public SILAllocated<FixedSizeSlab>,
|
|
public FixedSizeSlabPayload {
|
|
public:
|
|
void operator=(const FixedSizeSlab &) = delete;
|
|
void operator delete(void *Ptr, size_t) = delete;
|
|
};
|
|
|
|
class AnyFunctionType;
|
|
class ASTContext;
|
|
class FileUnit;
|
|
class FuncDecl;
|
|
class IRGenOptions;
|
|
class KeyPathPattern;
|
|
class ModuleDecl;
|
|
class SourceFile;
|
|
class SerializedSILLoader;
|
|
class SILFunctionBuilder;
|
|
class SILOptFunctionBuilder;
|
|
class SILRemarkStreamer;
|
|
|
|
namespace Lowering {
|
|
class SILGenModule;
|
|
} // namespace Lowering
|
|
|
|
/// A stage of SIL processing.
|
|
enum class SILStage {
|
|
/// "Raw" SIL, emitted by SILGen, but not yet run through guaranteed
|
|
/// optimization and diagnostic passes.
|
|
///
|
|
/// Raw SIL does not have fully-constructed SSA and may contain undiagnosed
|
|
/// dataflow errors.
|
|
Raw,
|
|
|
|
/// Canonical SIL, which has been run through at least the guaranteed
|
|
/// optimization and diagnostic passes.
|
|
///
|
|
/// Canonical SIL has stricter invariants than raw SIL. It must not contain
|
|
/// dataflow errors, and some instructions must be canonicalized to simpler
|
|
/// forms.
|
|
Canonical,
|
|
|
|
/// Lowered SIL, which has been prepared for IRGen and will no longer
|
|
/// be passed to canonical SIL transform passes.
|
|
///
|
|
/// In lowered SIL, the SILType of all SILValues is its SIL storage
|
|
/// type. Explicit storage is required for all address-only and resilient
|
|
/// types.
|
|
///
|
|
/// Generating the initial Raw SIL is typically referred to as lowering (from
|
|
/// the AST). To disambiguate, refer to the process of generating the lowered
|
|
/// stage of SIL as "address lowering".
|
|
Lowered,
|
|
};
|
|
|
|
/// A SIL module. The SIL module owns all of the SILFunctions generated
|
|
/// when a Swift compilation context is lowered to SIL.
|
|
class SILModule {
|
|
friend class SILFunctionBuilder;
|
|
|
|
public:
|
|
using FunctionListType = llvm::ilist<SILFunction>;
|
|
using GlobalListType = llvm::ilist<SILGlobalVariable>;
|
|
using VTableListType = llvm::ArrayRef<SILVTable*>;
|
|
using PropertyListType = llvm::ilist<SILProperty>;
|
|
using WitnessTableListType = llvm::ilist<SILWitnessTable>;
|
|
using DefaultWitnessTableListType = llvm::ilist<SILDefaultWitnessTable>;
|
|
using DefaultOverrideTableListType = llvm::ilist<SILDefaultOverrideTable>;
|
|
using DifferentiabilityWitnessListType =
|
|
llvm::ilist<SILDifferentiabilityWitness>;
|
|
using SILMoveOnlyDeinitListType = llvm::ArrayRef<SILMoveOnlyDeinit *>;
|
|
using CoverageMapCollectionType =
|
|
llvm::MapVector<StringRef, SILCoverageMap *>;
|
|
using BasicBlockNameMapType =
|
|
llvm::DenseMap<const SILBasicBlock *, std::string>;
|
|
|
|
enum class LinkingMode : uint8_t {
|
|
/// Link functions with shared linkage. Used by the mandatory pipeline.
|
|
LinkNormal,
|
|
|
|
/// Link all functions. Used by the performance pipeline.
|
|
LinkAll
|
|
};
|
|
|
|
using ActionCallback = std::function<void()>;
|
|
using SlabList = llvm::simple_ilist<FixedSizeSlab>;
|
|
|
|
private:
|
|
friend KeyPathPattern;
|
|
friend SILBasicBlock;
|
|
friend SILCoverageMap;
|
|
friend SILDefaultWitnessTable;
|
|
friend SILDefaultOverrideTable;
|
|
friend SILDifferentiabilityWitness;
|
|
friend SILFunction;
|
|
friend SILGlobalVariable;
|
|
friend SILLayout;
|
|
friend SILType;
|
|
friend SILVTable;
|
|
friend SILProperty;
|
|
friend SILWitnessTable;
|
|
friend SILMoveOnlyDeinit;
|
|
friend Lowering::SILGenModule;
|
|
friend Lowering::TypeConverter;
|
|
class SerializationCallback;
|
|
|
|
/// Allocator that manages the memory of all the pieces of the SILModule.
|
|
mutable llvm::BumpPtrAllocator BPA;
|
|
|
|
/// The list of freed slabs, which can be reused.
|
|
SlabList freeSlabs;
|
|
|
|
/// For consistency checking.
|
|
size_t numAllocatedSlabs = 0;
|
|
|
|
/// When an instruction is "deleted" from the SIL, it is put into this list.
|
|
/// The instructions in this list are eventually deleted for real in
|
|
/// flushDeletedInsts(), which is called by the pass manager after each pass
|
|
/// run.
|
|
/// In other words: instruction deletion is deferred to the end of a pass.
|
|
///
|
|
/// This avoids dangling instruction pointers within the run of a pass and in
|
|
/// analysis caches. Note that the analysis invalidation mechanism ensures
|
|
/// that analysis caches are invalidated before flushDeletedInsts().
|
|
std::vector<SILInstruction*> scheduledForDeletion;
|
|
|
|
/// The swift Module associated with this SILModule.
|
|
ModuleDecl *TheSwiftModule;
|
|
|
|
/// A specific context for AST-level declarations associated with this SIL
|
|
/// module.
|
|
///
|
|
/// \sa getAssociatedContext
|
|
const DeclContext *AssociatedDeclContext;
|
|
|
|
/// Lookup table for SIL functions. This needs to be declared before \p
|
|
/// functions so that the destructor of \p functions is called first.
|
|
llvm::StringMap<SILFunction *> FunctionTable;
|
|
llvm::StringMap<SILFunction *> ZombieFunctionTable;
|
|
|
|
/// Lookup table for SIL functions by their asmnames, for those that
|
|
/// have them.
|
|
llvm::StringMap<SILFunction *> FunctionByAsmNameTable;
|
|
|
|
/// The list of SILFunctions in the module.
|
|
FunctionListType functions;
|
|
|
|
/// Functions, which are dead (and not in the functions list anymore),
|
|
/// but kept alive for debug info generation.
|
|
FunctionListType zombieFunctions;
|
|
|
|
/// Lookup table for SIL vtables from class decls.
|
|
llvm::DenseMap<const ClassDecl *, SILVTable *> VTableMap;
|
|
|
|
/// Lookup table for specialized SIL vtables from types.
|
|
llvm::DenseMap<SILType, SILVTable *> SpecializedVTableMap;
|
|
|
|
/// The list of SILVTables in the module.
|
|
std::vector<SILVTable*> vtables;
|
|
|
|
/// This is a cache of vtable entries for quick look-up
|
|
llvm::DenseMap<std::pair<const SILVTable *, SILDeclRef>, SILVTable::Entry>
|
|
VTableEntryCache;
|
|
|
|
/// Lookup table for SIL witness tables from conformances.
|
|
llvm::DenseMap<const RootProtocolConformance *, SILWitnessTable *>
|
|
WitnessTableMap;
|
|
|
|
/// Lookup table for specialized witness tables from conformances.
|
|
/// Currently only used in embedded mode.
|
|
llvm::DenseMap<const ProtocolConformance *, SILWitnessTable *>
|
|
specializedWitnessTableMap;
|
|
|
|
/// The list of SILWitnessTables in the module.
|
|
WitnessTableListType witnessTables;
|
|
|
|
/// Lookup table for SIL default witness tables from protocols.
|
|
llvm::DenseMap<const ProtocolDecl *, SILDefaultWitnessTable *>
|
|
DefaultWitnessTableMap;
|
|
|
|
/// The list of SILDefaultWitnessTables in the module.
|
|
DefaultWitnessTableListType defaultWitnessTables;
|
|
|
|
/// Lookup table for SIL default override tables from classes.
|
|
llvm::DenseMap<const ClassDecl *, SILDefaultOverrideTable *>
|
|
DefaultOverrideTableMap;
|
|
|
|
DefaultOverrideTableListType defaultOverrideTables;
|
|
|
|
/// Lookup table for SIL differentiability witnesses, keyed by mangled name.
|
|
llvm::StringMap<SILDifferentiabilityWitness *> DifferentiabilityWitnessMap;
|
|
|
|
/// Lookup table for SILDifferentiabilityWitnesses, keyed by original
|
|
/// function name.
|
|
llvm::StringMap<llvm::SmallVector<SILDifferentiabilityWitness *, 1>>
|
|
DifferentiabilityWitnessesByFunction;
|
|
|
|
/// The list of SILDifferentiabilityWitnesses in the module.
|
|
DifferentiabilityWitnessListType differentiabilityWitnesses;
|
|
|
|
/// Lookup table for SIL vtables from class decls.
|
|
llvm::DenseMap<const NominalTypeDecl *, SILMoveOnlyDeinit *>
|
|
MoveOnlyDeinitMap;
|
|
|
|
/// The list of move only deinits in the module.
|
|
std::vector<SILMoveOnlyDeinit *> moveOnlyDeinits;
|
|
|
|
/// Declarations which are externally visible.
|
|
///
|
|
/// These are method declarations which are referenced from inlinable
|
|
/// functions due to cross-module-optimization. Those declarations don't have
|
|
/// any attributes or linkage which mark them as externally visible by
|
|
/// default.
|
|
/// Currently this table is not serialized.
|
|
llvm::SetVector<ValueDecl *> externallyVisible;
|
|
|
|
/// Lookup table for SIL Global Variables.
|
|
llvm::StringMap<SILGlobalVariable *> GlobalVariableMap;
|
|
|
|
/// Lookup table for SIL Global Variables, indexed by their asmnames.
|
|
llvm::StringMap<SILGlobalVariable *> GlobalVariableByAsmNameMap;
|
|
|
|
/// The list of SILGlobalVariables in the module.
|
|
GlobalListType silGlobals;
|
|
|
|
// The map of SILCoverageMaps in the module.
|
|
CoverageMapCollectionType coverageMaps;
|
|
|
|
// The list of SILProperties in the module.
|
|
PropertyListType properties;
|
|
|
|
/// The remark streamer used to serialize SIL remarks to a file.
|
|
std::unique_ptr<swift::SILRemarkStreamer> silRemarkStreamer;
|
|
|
|
/// This is a cache of intrinsic Function declarations to numeric ID mappings.
|
|
llvm::DenseMap<Identifier, IntrinsicInfo> IntrinsicIDCache;
|
|
|
|
/// This is a cache of builtin Function declarations to numeric ID mappings.
|
|
llvm::DenseMap<Identifier, BuiltinInfo> BuiltinIDCache;
|
|
|
|
llvm::DenseMap<std::pair<Decl *, VarDecl *>, unsigned> fieldIndices;
|
|
llvm::DenseMap<EnumElementDecl *, unsigned> enumCaseIndices;
|
|
|
|
/// The stage of processing this module is at.
|
|
SILStage Stage;
|
|
|
|
/// True if SIL conventions force address-only to be passed by address.
|
|
///
|
|
/// Used for bootstrapping the AddressLowering pass. This should eventually
|
|
/// be inferred from the SIL stage to be true only when Stage == Lowered.
|
|
bool loweredAddresses;
|
|
|
|
/// The set of deserialization notification handlers.
|
|
DeserializationNotificationHandlerSet deserializationNotificationHandlers;
|
|
|
|
/// The SILLoader used when linking functions into this module.
|
|
///
|
|
/// This is lazily initialized the first time we attempt to
|
|
/// deserialize. Previously this was created when the SILModule was
|
|
/// constructed. In certain cases this was before all Modules had been loaded
|
|
/// causing us to not
|
|
std::unique_ptr<SerializedSILLoader> SILLoader;
|
|
|
|
/// The indexed profile data to be used for PGO, or nullptr.
|
|
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
|
|
|
|
/// A trie of integer indices that gives pointer identity to a path of
|
|
/// projections, shared between all functions in the module.
|
|
std::unique_ptr<IndexTrieNode> indexTrieRoot;
|
|
|
|
/// A mapping from local generic environments to the instructions which define
|
|
/// them.
|
|
///
|
|
/// The value is either a SingleValueInstruction or a PlaceholderValue,
|
|
/// in case a local archetype definition is looked up during parsing or
|
|
/// deserializing SIL, where local archetypes can be forward referenced.
|
|
///
|
|
/// In theory we wouldn't need to have the SILFunction in the key, because
|
|
/// local environments should be unique across the module. But currently
|
|
/// in some rare cases SILGen re-uses the same local archetype for multiple
|
|
/// functions.
|
|
using LocalArchetypeKey = std::pair<GenericEnvironment *, SILFunction *>;
|
|
llvm::DenseMap<LocalArchetypeKey, SILValue> RootLocalArchetypeDefs;
|
|
|
|
/// The number of PlaceholderValues in RootLocalArchetypeDefs.
|
|
int numUnresolvedLocalArchetypes = 0;
|
|
|
|
/// The options passed into this SILModule.
|
|
const SILOptions &Options;
|
|
|
|
/// IRGen options to be used by target specific SIL optimization passes.
|
|
///
|
|
/// Not null, if the module is created by the compiler itself (and not
|
|
/// e.g. by lldb).
|
|
const IRGenOptions *irgenOptions;
|
|
|
|
/// The number of functions created in this module, which will be the index of
|
|
/// the next function.
|
|
unsigned nextFunctionIndex = 0;
|
|
|
|
/// Set if the SILModule was serialized already. It is used
|
|
/// to ensure that the module is serialized only once.
|
|
bool serialized;
|
|
|
|
bool parsedAsSerializedSIL;
|
|
|
|
/// Set if we have registered a deserialization notification handler for
|
|
/// lowering ownership in transparent functions.
|
|
/// This gets set in OwnershipModelEliminator pass.
|
|
bool regDeserializationNotificationHandlerForAllFuncOME;
|
|
|
|
// True if a DeserializationNotificationHandler is set for
|
|
// AccessMarkerElimination.
|
|
bool hasAccessMarkerHandler;
|
|
|
|
bool prespecializedFunctionDeclsImported;
|
|
|
|
/// Action to be executed for serializing the SILModule.
|
|
ActionCallback SerializeSILAction;
|
|
|
|
BasicBlockNameMapType basicBlockNames;
|
|
|
|
// Specialization attributes which need to be added to a function once it is created.
|
|
// The key of this map is the function name.
|
|
llvm::StringMap<std::vector<SILSpecializeAttr *>> pendingSpecializeAttrs;
|
|
|
|
SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
|
|
Lowering::TypeConverter &TC, const SILOptions &Options,
|
|
const IRGenOptions *irgenOptions = nullptr);
|
|
|
|
SILModule(const SILModule&) = delete;
|
|
void operator=(const SILModule&) = delete;
|
|
|
|
/// Folding set for key path patterns.
|
|
llvm::FoldingSet<KeyPathPattern> KeyPathPatterns;
|
|
|
|
public:
|
|
~SILModule();
|
|
|
|
/// Method which returns the SerializedSILLoader, creating the loader if it
|
|
/// has not been created yet.
|
|
SerializedSILLoader *getSILLoader();
|
|
|
|
/// Add a callback for each newly deserialized SIL function body.
|
|
void registerDeserializationNotificationHandler(
|
|
std::unique_ptr<DeserializationNotificationHandler> &&handler);
|
|
|
|
/// Return the set of registered deserialization callbacks.
|
|
DeserializationNotificationHandlerSet::range
|
|
getDeserializationHandlers() const {
|
|
return deserializationNotificationHandlers.getRange();
|
|
}
|
|
|
|
void removeDeserializationNotificationHandler(
|
|
DeserializationNotificationHandler *handler) {
|
|
deserializationNotificationHandlers.erase(handler);
|
|
}
|
|
|
|
bool hasRegisteredDeserializationNotificationHandlerForAllFuncOME() {
|
|
return regDeserializationNotificationHandlerForAllFuncOME;
|
|
}
|
|
void setRegisteredDeserializationNotificationHandlerForAllFuncOME() {
|
|
regDeserializationNotificationHandlerForAllFuncOME = true;
|
|
}
|
|
|
|
bool checkHasAccessMarkerHandler() {
|
|
return hasAccessMarkerHandler;
|
|
}
|
|
void setHasAccessMarkerHandler() {
|
|
hasAccessMarkerHandler = true;
|
|
}
|
|
|
|
/// Returns the instruction which defines the given local generic environment,
|
|
/// e.g. an open_existential_addr.
|
|
///
|
|
/// In case the generic environment is not defined yet (e.g. during parsing or
|
|
/// deserialization), a PlaceholderValue is returned. This should not be the
|
|
/// case outside of parsing or deserialization.
|
|
SILValue getLocalGenericEnvironmentDef(GenericEnvironment *genericEnv,
|
|
SILFunction *inFunction);
|
|
|
|
/// Returns the instruction which defines the given local generic environment,
|
|
/// e.g. an open_existential_addr.
|
|
///
|
|
/// In contrast to getLocalGenericEnvironmentDef, it is required that all local
|
|
/// generic environments are resolved.
|
|
SingleValueInstruction *
|
|
getLocalGenericEnvironmentDefInst(GenericEnvironment *genericEnv,
|
|
SILFunction *inFunction) {
|
|
return dyn_cast<SingleValueInstruction>(
|
|
getLocalGenericEnvironmentDef(genericEnv, inFunction));
|
|
}
|
|
|
|
/// Returns the instruction which defines the given root local archetype,
|
|
/// e.g. an open_existential_addr.
|
|
///
|
|
/// In case the local archetype is not defined yet (e.g. during parsing or
|
|
/// deserialization), a PlaceholderValue is returned. This should not be the
|
|
/// case outside of parsing or deserialization.
|
|
SILValue getRootLocalArchetypeDef(CanLocalArchetypeType archetype,
|
|
SILFunction *inFunction);
|
|
|
|
/// Returns the instruction which defines the given root local archetype,
|
|
/// e.g. an open_existential_addr.
|
|
///
|
|
/// In contrast to getLocalArchetypeDef, it is required that all local
|
|
/// archetypes are resolved.
|
|
SingleValueInstruction *
|
|
getRootLocalArchetypeDefInst(CanLocalArchetypeType archetype,
|
|
SILFunction *inFunction) {
|
|
return dyn_cast<SingleValueInstruction>(
|
|
getRootLocalArchetypeDef(archetype, inFunction));
|
|
}
|
|
|
|
/// Returns true if there are unresolved local archetypes in the module.
|
|
///
|
|
/// This should only be the case during parsing or deserialization.
|
|
bool hasUnresolvedLocalArchetypeDefinitions();
|
|
|
|
/// If we added any instructions that reference unresolved local archetypes
|
|
/// and then deleted those instructions without resolving those archetypes,
|
|
/// we must reclaim those unresolved local archetypes.
|
|
void reclaimUnresolvedLocalArchetypeDefinitions();
|
|
|
|
/// Get a unique index for a struct or class field in layout order.
|
|
///
|
|
/// Precondition: \p decl must be a non-resilient struct or class.
|
|
///
|
|
/// Precondition: \p field must be a stored property declared in \p decl,
|
|
/// not in a superclass.
|
|
///
|
|
/// Postcondition: The returned index is unique across all properties in the
|
|
/// object, including properties declared in a superclass.
|
|
unsigned getFieldIndex(NominalTypeDecl *decl, VarDecl *property);
|
|
|
|
unsigned getCaseIndex(EnumElementDecl *enumElement);
|
|
|
|
/// Called by SILBuilder whenever a new instruction is created and inserted.
|
|
void notifyAddedInstruction(SILInstruction *inst);
|
|
|
|
/// Called after an instruction is moved from one function to another.
|
|
void notifyMovedInstruction(SILInstruction *inst, SILFunction *fromFunction);
|
|
|
|
unsigned getNewFunctionIndex() { return nextFunctionIndex++; }
|
|
|
|
// This may be larger that the number of live functions in the 'functions'
|
|
// linked list because it includes the indices of zombie functions.
|
|
unsigned getNumFunctionIndices() const { return nextFunctionIndex; }
|
|
|
|
/// Set a serialization action.
|
|
void setSerializeSILAction(ActionCallback SerializeSILAction);
|
|
ActionCallback getSerializeSILAction() const;
|
|
|
|
/// Set a flag indicating that this module is serialized already.
|
|
void setSerialized() { serialized = true; }
|
|
bool isSerialized() const { return serialized; }
|
|
|
|
void setParsedAsSerializedSIL() {
|
|
serialized = true;
|
|
parsedAsSerializedSIL = true;
|
|
}
|
|
bool isParsedAsSerializedSIL() const { return parsedAsSerializedSIL; }
|
|
|
|
void setBasicBlockName(const SILBasicBlock *block, StringRef name) {
|
|
#ifndef NDEBUG
|
|
basicBlockNames[block] = name.str();
|
|
#endif
|
|
}
|
|
std::optional<StringRef> getBasicBlockName(const SILBasicBlock *block) {
|
|
#ifndef NDEBUG
|
|
auto Known = basicBlockNames.find(block);
|
|
if (Known == basicBlockNames.end())
|
|
return std::nullopt;
|
|
|
|
return StringRef(Known->second);
|
|
#else
|
|
return std::nullopt;
|
|
#endif
|
|
}
|
|
|
|
/// Serialize a SIL module using the configured SerializeSILAction.
|
|
void serialize();
|
|
|
|
/// This converts Swift types to SILTypes.
|
|
Lowering::TypeConverter &Types;
|
|
|
|
/// Invalidate cached entries in SIL Loader.
|
|
void invalidateSILLoaderCaches();
|
|
|
|
/// Erase a function from the module.
|
|
void eraseFunction(SILFunction *F);
|
|
|
|
/// Invalidate a function in SILLoader cache.
|
|
void invalidateFunctionInSILCache(SILFunction *F);
|
|
|
|
/// Specialization can cause a function that was erased before by dead function
|
|
/// elimination to become alive again. If this happens we need to remove it
|
|
/// from the list of zombies.
|
|
SILFunction *removeFromZombieList(StringRef Name);
|
|
|
|
/// Erase a global SIL variable from the module.
|
|
void eraseGlobalVariable(SILGlobalVariable *G);
|
|
|
|
/// Erase a differentiability witness from the module.
|
|
void eraseDifferentiabilityWitness(SILDifferentiabilityWitness *dw);
|
|
|
|
/// Erase all differentiability witnesses for function f.
|
|
void eraseAllDifferentiabilityWitnesses(SILFunction *f);
|
|
|
|
/// Create and return an empty SIL module suitable for generating or parsing
|
|
/// SIL into.
|
|
///
|
|
/// \param context The associated decl context. This should be a FileUnit in
|
|
/// single-file mode, and a ModuleDecl in whole-module mode.
|
|
static std::unique_ptr<SILModule>
|
|
createEmptyModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
|
|
Lowering::TypeConverter &TC, const SILOptions &Options,
|
|
const IRGenOptions *irgenOptions = nullptr);
|
|
|
|
/// Get the Swift module associated with this SIL module.
|
|
ModuleDecl *getSwiftModule() const { return TheSwiftModule; }
|
|
/// Get the AST context used for type uniquing etc. by this SIL module.
|
|
ASTContext &getASTContext() const;
|
|
SourceManager &getSourceManager() const { return getASTContext().SourceMgr; }
|
|
|
|
/// Get the Swift DeclContext associated with this SIL module. This is never
|
|
/// null.
|
|
///
|
|
/// All AST declarations within this context are assumed to have been fully
|
|
/// processed as part of generating this module. This allows certain passes
|
|
/// to make additional assumptions about these declarations.
|
|
///
|
|
/// If this is the same as TheSwiftModule, the entire module is being
|
|
/// compiled as a single unit.
|
|
const DeclContext *getAssociatedContext() const {
|
|
return AssociatedDeclContext;
|
|
}
|
|
|
|
/// Returns true if this SILModule really contains the whole module, i.e.
|
|
/// optimizations can assume that they see the whole module.
|
|
bool isWholeModule() const {
|
|
return isa<ModuleDecl>(AssociatedDeclContext);
|
|
}
|
|
|
|
bool isStdlibModule() const;
|
|
|
|
/// Returns true if it is the optimized OnoneSupport module.
|
|
bool isOptimizedOnoneSupportModule() const;
|
|
|
|
const SILOptions &getOptions() const { return Options; }
|
|
const IRGenOptions *getIRGenOptionsOrNull() const {
|
|
// This exposes target specific information, therefore serialized SIL
|
|
// is also target specific.
|
|
return irgenOptions;
|
|
}
|
|
|
|
using iterator = FunctionListType::iterator;
|
|
using const_iterator = FunctionListType::const_iterator;
|
|
FunctionListType &getFunctionList() { return functions; }
|
|
const FunctionListType &getFunctionList() const { return functions; }
|
|
iterator begin() { return functions.begin(); }
|
|
iterator end() { return functions.end(); }
|
|
const_iterator begin() const { return functions.begin(); }
|
|
const_iterator end() const { return functions.end(); }
|
|
iterator_range<iterator> getFunctions() {
|
|
return {functions.begin(), functions.end()};
|
|
}
|
|
iterator_range<const_iterator> getFunctions() const {
|
|
return {functions.begin(), functions.end()};
|
|
}
|
|
|
|
/// Move \p fn to be in the function list before \p moveBefore.
|
|
void moveBefore(SILModule::iterator moveBefore, SILFunction *fn);
|
|
|
|
/// Move \p fn to be in the function list after \p moveAfter. It is assumed
|
|
/// that \p moveAfter is not end.
|
|
void moveAfter(SILModule::iterator moveAfter, SILFunction *fn);
|
|
|
|
const_iterator zombies_begin() const { return zombieFunctions.begin(); }
|
|
const_iterator zombies_end() const { return zombieFunctions.end(); }
|
|
|
|
llvm::ArrayRef<SILVTable*> getVTables() const {
|
|
return llvm::ArrayRef<SILVTable*>(vtables);
|
|
}
|
|
using vtable_iterator = VTableListType::iterator;
|
|
using vtable_const_iterator = VTableListType::const_iterator;
|
|
vtable_iterator vtable_begin() { return getVTables().begin(); }
|
|
vtable_iterator vtable_end() { return getVTables().end(); }
|
|
vtable_const_iterator vtable_begin() const { return getVTables().begin(); }
|
|
vtable_const_iterator vtable_end() const { return getVTables().end(); }
|
|
|
|
ArrayRef<SILMoveOnlyDeinit *> getMoveOnlyDeinits() const {
|
|
return ArrayRef<SILMoveOnlyDeinit *>(moveOnlyDeinits);
|
|
}
|
|
using moveonlydeinit_iterator = SILMoveOnlyDeinitListType::iterator;
|
|
using moveonlydeinit_const_iterator =
|
|
SILMoveOnlyDeinitListType::const_iterator;
|
|
moveonlydeinit_iterator moveonlydeinit_begin() {
|
|
return getMoveOnlyDeinits().begin();
|
|
}
|
|
moveonlydeinit_iterator moveonlydeinit_end() {
|
|
return getMoveOnlyDeinits().end();
|
|
}
|
|
moveonlydeinit_const_iterator moveonlydeinit_begin() const {
|
|
return getMoveOnlyDeinits().begin();
|
|
}
|
|
moveonlydeinit_const_iterator moveonlydeinit_end() const {
|
|
return getMoveOnlyDeinits().end();
|
|
}
|
|
|
|
using witness_table_iterator = WitnessTableListType::iterator;
|
|
using witness_table_const_iterator = WitnessTableListType::const_iterator;
|
|
WitnessTableListType &getWitnessTableList() { return witnessTables; }
|
|
const WitnessTableListType &getWitnessTableList() const { return witnessTables; }
|
|
witness_table_iterator witness_table_begin() { return witnessTables.begin(); }
|
|
witness_table_iterator witness_table_end() { return witnessTables.end(); }
|
|
witness_table_const_iterator witness_table_begin() const { return witnessTables.begin(); }
|
|
witness_table_const_iterator witness_table_end() const { return witnessTables.end(); }
|
|
iterator_range<witness_table_iterator> getWitnessTables() {
|
|
return {witnessTables.begin(), witnessTables.end()};
|
|
}
|
|
iterator_range<witness_table_const_iterator> getWitnessTables() const {
|
|
return {witnessTables.begin(), witnessTables.end()};
|
|
}
|
|
|
|
using default_witness_table_iterator = DefaultWitnessTableListType::iterator;
|
|
using default_witness_table_const_iterator = DefaultWitnessTableListType::const_iterator;
|
|
DefaultWitnessTableListType &getDefaultWitnessTableList() { return defaultWitnessTables; }
|
|
const DefaultWitnessTableListType &getDefaultWitnessTableList() const { return defaultWitnessTables; }
|
|
default_witness_table_iterator default_witness_table_begin() { return defaultWitnessTables.begin(); }
|
|
default_witness_table_iterator default_witness_table_end() { return defaultWitnessTables.end(); }
|
|
default_witness_table_const_iterator default_witness_table_begin() const { return defaultWitnessTables.begin(); }
|
|
default_witness_table_const_iterator default_witness_table_end() const { return defaultWitnessTables.end(); }
|
|
iterator_range<default_witness_table_iterator> getDefaultWitnessTables() {
|
|
return {defaultWitnessTables.begin(), defaultWitnessTables.end()};
|
|
}
|
|
iterator_range<default_witness_table_const_iterator> getDefaultWitnessTables() const {
|
|
return {defaultWitnessTables.begin(), defaultWitnessTables.end()};
|
|
}
|
|
|
|
using default_override_table_iterator = DefaultOverrideTableListType::iterator;
|
|
using default_override_table_const_iterator = DefaultOverrideTableListType::const_iterator;
|
|
DefaultOverrideTableListType &getDefaultOverrideTableList() { return defaultOverrideTables; }
|
|
const DefaultOverrideTableListType &getDefaultOverrideTableList() const { return defaultOverrideTables; }
|
|
default_override_table_iterator default_override_table_begin() { return defaultOverrideTables.begin(); }
|
|
default_override_table_iterator default_override_table_end() { return defaultOverrideTables.end(); }
|
|
default_override_table_const_iterator default_override_table_begin() const { return defaultOverrideTables.begin(); }
|
|
default_override_table_const_iterator default_override_table_end() const { return defaultOverrideTables.end(); }
|
|
iterator_range<default_override_table_iterator> getDefaultOverrideTables() {
|
|
return {defaultOverrideTables.begin(), defaultOverrideTables.end()};
|
|
}
|
|
iterator_range<default_override_table_const_iterator>
|
|
getDefaultOverrideTables() const {
|
|
return {defaultOverrideTables.begin(), defaultOverrideTables.end()};
|
|
}
|
|
|
|
using differentiability_witness_iterator = DifferentiabilityWitnessListType::iterator;
|
|
using differentiability_witness_const_iterator = DifferentiabilityWitnessListType::const_iterator;
|
|
DifferentiabilityWitnessListType &getDifferentiabilityWitnessList() { return differentiabilityWitnesses; }
|
|
const DifferentiabilityWitnessListType &getDifferentiabilityWitnessList() const { return differentiabilityWitnesses; }
|
|
differentiability_witness_iterator differentiability_witness_begin() { return differentiabilityWitnesses.begin(); }
|
|
differentiability_witness_iterator differentiability_witness_end() { return differentiabilityWitnesses.end(); }
|
|
differentiability_witness_const_iterator differentiability_witness_begin() const { return differentiabilityWitnesses.begin(); }
|
|
differentiability_witness_const_iterator differentiability_witness_end() const { return differentiabilityWitnesses.end(); }
|
|
iterator_range<differentiability_witness_iterator>
|
|
getDifferentiabilityWitnesses() {
|
|
return {differentiabilityWitnesses.begin(),
|
|
differentiabilityWitnesses.end()};
|
|
}
|
|
iterator_range<differentiability_witness_const_iterator>
|
|
getDifferentiabilityWitnesses() const {
|
|
return {differentiabilityWitnesses.begin(),
|
|
differentiabilityWitnesses.end()};
|
|
}
|
|
|
|
void addExternallyVisibleDecl(ValueDecl *decl) {
|
|
externallyVisible.insert(decl);
|
|
}
|
|
bool isExternallyVisibleDecl(ValueDecl *decl) {
|
|
return externallyVisible.count(decl) != 0;
|
|
}
|
|
|
|
using sil_global_iterator = GlobalListType::iterator;
|
|
using sil_global_const_iterator = GlobalListType::const_iterator;
|
|
GlobalListType &getSILGlobalList() { return silGlobals; }
|
|
const GlobalListType &getSILGlobalList() const { return silGlobals; }
|
|
sil_global_iterator sil_global_begin() { return silGlobals.begin(); }
|
|
sil_global_iterator sil_global_end() { return silGlobals.end(); }
|
|
sil_global_const_iterator sil_global_begin() const {
|
|
return silGlobals.begin();
|
|
}
|
|
sil_global_const_iterator sil_global_end() const {
|
|
return silGlobals.end();
|
|
}
|
|
iterator_range<sil_global_iterator> getSILGlobals() {
|
|
return {silGlobals.begin(), silGlobals.end()};
|
|
}
|
|
iterator_range<sil_global_const_iterator> getSILGlobals() const {
|
|
return {silGlobals.begin(), silGlobals.end()};
|
|
}
|
|
|
|
using coverage_map_iterator = CoverageMapCollectionType::iterator;
|
|
using coverage_map_const_iterator = CoverageMapCollectionType::const_iterator;
|
|
CoverageMapCollectionType &getCoverageMaps() { return coverageMaps; }
|
|
const CoverageMapCollectionType &getCoverageMaps() const {
|
|
return coverageMaps;
|
|
}
|
|
|
|
swift::SILRemarkStreamer *getSILRemarkStreamer() {
|
|
return silRemarkStreamer.get();
|
|
}
|
|
|
|
void installSILRemarkStreamer();
|
|
|
|
// This is currently limited to VarDecl because the visibility of global
|
|
// variables and class properties is straightforward, while the visibility of
|
|
// class methods (ValueDecls) depends on the subclass scope. "Visibility" has
|
|
// a different meaning when vtable layout is at stake.
|
|
bool isVisibleExternally(const VarDecl *decl) {
|
|
return isPossiblyUsedExternally(getDeclSILLinkage(decl), isWholeModule());
|
|
}
|
|
|
|
/// Promote the linkage of every entity in this SIL module so that they are
|
|
/// externally visible. This is used to promote the linkage of private
|
|
/// entities that are compiled on-demand for lazy immediate mode, as each is
|
|
/// emitted into its own `SILModule`.
|
|
void promoteLinkages();
|
|
|
|
PropertyListType &getPropertyList() { return properties; }
|
|
const PropertyListType &getPropertyList() const { return properties; }
|
|
|
|
/// Look for a global variable by name.
|
|
///
|
|
/// \return null if this module has no such global variable
|
|
SILGlobalVariable *lookUpGlobalVariable(StringRef name,
|
|
bool byAsmName = false) const {
|
|
if (byAsmName)
|
|
return GlobalVariableByAsmNameMap.lookup(name);
|
|
|
|
return GlobalVariableMap.lookup(name);
|
|
}
|
|
|
|
/// Look for a function by name.
|
|
///
|
|
/// \return null if this module has no such function
|
|
SILFunction *lookUpFunction(StringRef name, bool byAsmName = false) const {
|
|
if (byAsmName)
|
|
return FunctionByAsmNameTable.lookup(name);
|
|
return FunctionTable.lookup(name);
|
|
}
|
|
|
|
/// Look for a function by declaration.
|
|
///
|
|
/// \return null if this module has no such function
|
|
SILFunction *lookUpFunction(SILDeclRef fnRef);
|
|
|
|
/// Attempt to deserialize function \p F and all functions which are referenced
|
|
/// from \p F (according to the \p LinkMode).
|
|
///
|
|
/// Returns true if deserialization succeeded, false otherwise.
|
|
bool loadFunction(SILFunction *F, LinkingMode LinkMode);
|
|
|
|
/// Attempt to deserialize a function with \p name and all functions which are
|
|
/// referenced from that function (according to the \p LinkMode).
|
|
///
|
|
/// If \p linkage is provided, the deserialized function is required to have
|
|
/// that linkage. Returns null, if this is not the case.
|
|
SILFunction *loadFunction(StringRef name, LinkingMode LinkMode,
|
|
std::optional<SILLinkage> linkage = std::nullopt);
|
|
|
|
/// Update the linkage of the SILFunction with the linkage of the serialized
|
|
/// function.
|
|
///
|
|
/// The serialized SILLinkage can differ from the linkage derived from the
|
|
/// AST, e.g. cross-module-optimization can change the SIL linkages.
|
|
void updateFunctionLinkage(SILFunction *F);
|
|
|
|
/// Attempt to deserialize function \p F and all required referenced functions.
|
|
///
|
|
/// Returns true if linking succeeded, false otherwise.
|
|
bool linkFunction(SILFunction *F, LinkingMode LinkMode);
|
|
|
|
/// Attempt to deserialize witness table for protocol conformance \p PC.
|
|
///
|
|
/// Returns true if linking succeeded, false otherwise.
|
|
bool linkWitnessTable(ProtocolConformance *PC, LinkingMode LinkMode);
|
|
|
|
/// Check if a given function exists in any of the modules.
|
|
/// i.e. it can be linked by linkFunction.
|
|
bool hasFunction(StringRef Name);
|
|
|
|
/// Look up the SILWitnessTable representing the lowering of a conformance `C`.
|
|
/// If a specialized witness table exists for the conformance, return the specialized table.
|
|
/// Specialized witness tables are currently only used in embedded mode.
|
|
SILWitnessTable *lookUpWitnessTable(const ProtocolConformance *C);
|
|
|
|
/// Look up the SILWitnessTable representing the lowering of a conformance `C`.
|
|
/// The `isSpecialized` flag specifies if only non-specialized or specialized witness
|
|
/// tables are looked up.
|
|
/// Specialized witness tables are currently only used in embedded mode.
|
|
SILWitnessTable *lookUpWitnessTable(const ProtocolConformance *C, bool isSpecialized);
|
|
|
|
/// Attempt to lookup \p Member in the witness table for \p C.
|
|
///
|
|
/// Also, deserialize all referenced functions according to the \p linkgingMode.
|
|
std::pair<SILFunction *, SILWitnessTable *>
|
|
lookUpFunctionInWitnessTable(ProtocolConformanceRef C,
|
|
SILDeclRef Requirement,
|
|
bool lookupInSpecializedWitnessTable,
|
|
SILModule::LinkingMode linkingMode);
|
|
|
|
/// Look up the SILDefaultWitnessTable representing the default witnesses
|
|
/// of a resilient protocol, if any.
|
|
SILDefaultWitnessTable *lookUpDefaultWitnessTable(const ProtocolDecl *Protocol,
|
|
bool deserializeLazily=true);
|
|
|
|
/// Attempt to lookup \p Member in the default witness table for \p Protocol.
|
|
std::pair<SILFunction *, SILDefaultWitnessTable *>
|
|
lookUpFunctionInDefaultWitnessTable(const ProtocolDecl *Protocol,
|
|
SILDeclRef Requirement,
|
|
bool deserializeLazily=true);
|
|
|
|
/// Look up the SILDefaultOverrideTable containing the default overrides to be
|
|
/// applied to subclasses of a resilient class.
|
|
SILDefaultOverrideTable *
|
|
lookUpDefaultOverrideTable(const ClassDecl *decl,
|
|
bool deserializeLazily = true);
|
|
|
|
/// Look up the VTable mapped to the given ClassDecl. Returns null on failure.
|
|
SILVTable *lookUpVTable(const ClassDecl *C, bool deserializeLazily = true);
|
|
|
|
/// Look up a specialized VTable
|
|
SILVTable *lookUpSpecializedVTable(SILType classTy);
|
|
|
|
/// Attempt to lookup the function corresponding to \p Member in the class
|
|
/// hierarchy of \p Class.
|
|
SILFunction *lookUpFunctionInVTable(ClassDecl *Class, SILDeclRef Member);
|
|
|
|
/// Look up the deinit mapped to the given move only nominal type decl.
|
|
/// Returns null on failure.
|
|
SILMoveOnlyDeinit *lookUpMoveOnlyDeinit(const NominalTypeDecl *nomDecl,
|
|
bool deserializeLazily = true);
|
|
|
|
/// Look up the function mapped to the given move only nominal type decl.
|
|
/// Returns null on failure.
|
|
SILFunction *lookUpMoveOnlyDeinitFunction(const NominalTypeDecl *nomDecl);
|
|
|
|
/// Look up the differentiability witness with the given name.
|
|
SILDifferentiabilityWitness *lookUpDifferentiabilityWitness(StringRef name);
|
|
|
|
/// Look up the differentiability witness corresponding to the given key.
|
|
SILDifferentiabilityWitness *
|
|
lookUpDifferentiabilityWitness(SILDifferentiabilityWitnessKey key);
|
|
|
|
/// Look up the differentiability witness corresponding to the given function.
|
|
llvm::ArrayRef<SILDifferentiabilityWitness *>
|
|
lookUpDifferentiabilityWitnessesForFunction(StringRef name);
|
|
|
|
/// Attempt to deserialize the SILDifferentiabilityWitness. Returns true if
|
|
/// deserialization succeeded, false otherwise.
|
|
bool loadDifferentiabilityWitness(SILDifferentiabilityWitness *dw);
|
|
|
|
// Given a protocol, attempt to create a default witness table declaration
|
|
// for it.
|
|
SILDefaultWitnessTable *
|
|
createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol,
|
|
SILLinkage Linkage);
|
|
|
|
/// Deletes a dead witness table.
|
|
void deleteWitnessTable(SILWitnessTable *Wt);
|
|
|
|
/// Define a default override table for the indicated resilient class \p decl
|
|
/// consisting of the specified \p entries.
|
|
SILDefaultOverrideTable *createDefaultOverrideTableDefinition(
|
|
const ClassDecl *decl, SILLinkage linkage,
|
|
ArrayRef<SILDefaultOverrideTable::Entry> entries);
|
|
|
|
/// Return the stage of processing this module is at.
|
|
SILStage getStage() const { return Stage; }
|
|
|
|
/// Advance the module to a further stage of processing.
|
|
void setStage(SILStage s) {
|
|
assert(s >= Stage && "regressing stage?!");
|
|
Stage = s;
|
|
}
|
|
|
|
/// True if SIL conventions force address-only to be passed by address.
|
|
bool useLoweredAddresses() const { return loweredAddresses; }
|
|
|
|
void setLoweredAddresses(bool val) {
|
|
loweredAddresses = val;
|
|
if (val) {
|
|
Types.setLoweredAddresses();
|
|
}
|
|
}
|
|
|
|
llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); }
|
|
|
|
void setPGOReader(std::unique_ptr<llvm::IndexedInstrProfReader> IPR) {
|
|
PGOReader = std::move(IPR);
|
|
}
|
|
|
|
IndexTrieNode *getIndexTrieRoot() { return indexTrieRoot.get(); }
|
|
|
|
/// Can value operations (copies and destroys) on the given lowered type
|
|
/// be performed in this module?
|
|
bool isTypeABIAccessible(SILType type,
|
|
TypeExpansionContext forExpansion);
|
|
|
|
/// Can type metadata for the given formal type be fetched in
|
|
/// the given module?
|
|
bool isTypeMetadataAccessible(CanType type);
|
|
|
|
/// Can type metadata necessary for value operations for the given sil type be
|
|
/// fetched in the given module?
|
|
bool isTypeMetadataForLayoutAccessible(SILType type);
|
|
|
|
void verify(bool isCompleteOSSA = true,
|
|
bool checkLinearLifetime = true) const;
|
|
|
|
/// Run the SIL verifier to make sure that all Functions follow
|
|
/// invariants.
|
|
void verify(CalleeCache *calleeCache,
|
|
bool isCompleteOSSA = true,
|
|
bool checkLinearLifetime = true) const;
|
|
|
|
/// Run the SIL verifier without assuming OSSA lifetimes end at dead end
|
|
/// blocks.
|
|
void verifyIncompleteOSSA() const {
|
|
verify(/*isCompleteOSSA=*/false);
|
|
}
|
|
|
|
/// Check linear OSSA lifetimes, assuming complete OSSA.
|
|
void verifyOwnership() const;
|
|
|
|
/// Pretty-print the module.
|
|
void dump(bool Verbose = false) const;
|
|
|
|
/// Pretty-print the module with DebugInfo.
|
|
void dump(bool Verbose, bool DebugInfo) const;
|
|
|
|
/// Pretty-print the module to a file.
|
|
/// Useful for dumping the module when running in a debugger.
|
|
/// Warning: no error handling is done. Fails with an assert if the file
|
|
/// cannot be opened.
|
|
void dump(const char *FileName, bool Verbose = false,
|
|
bool PrintASTDecls = false) const;
|
|
|
|
/// Pretty-print the module to the designated stream.
|
|
///
|
|
/// \param M If present, the types and declarations from this module will be
|
|
/// printed. The module would usually contain the types and Decls that
|
|
/// the SIL module depends on.
|
|
/// \param Opts The SIL options, used to determine printing verbosity and
|
|
/// and sorting.
|
|
/// \param PrintASTDecls If set to true print AST decls.
|
|
void print(raw_ostream &OS, ModuleDecl *M = nullptr,
|
|
const SILOptions &Opts = SILOptions(),
|
|
bool PrintASTDecls = true) const {
|
|
SILPrintContext PrintCtx(OS, Opts);
|
|
print(PrintCtx, M, PrintASTDecls);
|
|
}
|
|
|
|
/// Pretty-print the module with the context \p PrintCtx.
|
|
///
|
|
/// \param M If present, the types and declarations from this module will be
|
|
/// printed. The module would usually contain the types and Decls that
|
|
/// the SIL module depends on.
|
|
/// \param PrintASTDecls If set to true print AST decls.
|
|
void print(SILPrintContext &PrintCtx, ModuleDecl *M = nullptr,
|
|
bool PrintASTDecls = true) const;
|
|
|
|
/// Allocate memory using the module's internal allocator.
|
|
void *allocate(unsigned Size, unsigned Align) const;
|
|
|
|
template <typename T> T *allocate(unsigned Count) const {
|
|
return static_cast<T *>(allocate(sizeof(T) * Count, alignof(T)));
|
|
}
|
|
|
|
/// Allocates a slab of memory.
|
|
///
|
|
/// This has (almost) zero cost, because for the first time, the allocation is
|
|
/// done with the BPA.
|
|
/// Subsequent allocations are reusing the already freed slabs.
|
|
FixedSizeSlab *allocSlab();
|
|
|
|
/// Frees a slab.
|
|
///
|
|
/// This has (almost) zero cost, because the slab is just put into the
|
|
/// freeSlabs list.
|
|
void freeSlab(FixedSizeSlab *slab);
|
|
|
|
/// Frees all slabs of a list.
|
|
void freeAllSlabs(SlabList &slabs);
|
|
|
|
template <typename T>
|
|
MutableArrayRef<T> allocateCopy(ArrayRef<T> Array) const {
|
|
MutableArrayRef<T> result(allocate<T>(Array.size()), Array.size());
|
|
std::uninitialized_copy(Array.begin(), Array.end(), result.begin());
|
|
return result;
|
|
}
|
|
|
|
StringRef allocateCopy(StringRef Str) const {
|
|
auto result = allocateCopy<char>({Str.data(), Str.size()});
|
|
return {result.data(), result.size()};
|
|
}
|
|
|
|
/// Allocate memory for an instruction using the module's internal allocator.
|
|
void *allocateInst(unsigned Size, unsigned Align) const;
|
|
|
|
/// Called before \p I is removed from its basic block and scheduled for
|
|
/// deletion.
|
|
void willDeleteInstruction(SILInstruction *I);
|
|
|
|
/// Schedules the (already removed) instruction \p I for deletion.
|
|
/// See scheduledForDeletion for details.
|
|
void scheduleForDeletion(SILInstruction *I);
|
|
|
|
/// Deletes all scheduled instructions for real.
|
|
/// See scheduledForDeletion for details.
|
|
void flushDeletedInsts();
|
|
|
|
bool hasInstructionsScheduledForDeletion() const {
|
|
return !scheduledForDeletion.empty();
|
|
}
|
|
|
|
/// Looks up the llvm intrinsic ID and type for the builtin function.
|
|
///
|
|
/// \returns Returns llvm::Intrinsic::not_intrinsic if the function is not an
|
|
/// intrinsic. The particular intrinsic functions which correspond to the
|
|
/// returned value are defined in llvm/Intrinsics.h.
|
|
const IntrinsicInfo &getIntrinsicInfo(Identifier ID);
|
|
|
|
/// Looks up the lazily cached identification for the builtin function.
|
|
///
|
|
/// \returns Returns builtin info of BuiltinValueKind::None kind if the
|
|
/// declaration is not a builtin.
|
|
const BuiltinInfo &getBuiltinInfo(Identifier ID);
|
|
|
|
/// Returns true if the builtin or intrinsic is no-return.
|
|
bool isNoReturnBuiltinOrIntrinsic(Identifier Name);
|
|
|
|
/// Returns true if the default atomicity of the module is Atomic.
|
|
bool isDefaultAtomic() const {
|
|
return !getOptions().AssumeSingleThreaded;
|
|
}
|
|
|
|
/// Returns true if SIL entities associated with declarations in the given
|
|
/// declaration context ought to be serialized as part of this module.
|
|
bool
|
|
shouldSerializeEntitiesAssociatedWithDeclContext(const DeclContext *DC) const;
|
|
|
|
/// Gather prespecialized from extensions.
|
|
void performOnceForPrespecializedImportedExtensions(
|
|
llvm::function_ref<void(AbstractFunctionDecl *)> action);
|
|
|
|
void addPendingSpecializeAttr(StringRef functionName, SILSpecializeAttr *attr) {
|
|
pendingSpecializeAttrs[functionName].push_back(attr);
|
|
}
|
|
};
|
|
|
|
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){
|
|
M.print(OS);
|
|
return OS;
|
|
}
|
|
|
|
void verificationFailure(const Twine &complaint,
|
|
const SILInstruction *atInstruction,
|
|
const SILArgument *atArgument,
|
|
llvm::function_ref<void(SILPrintContext &ctx)> extraContext);
|
|
|
|
inline bool SILOptions::supportsLexicalLifetimes(const SILModule &mod) const {
|
|
switch (mod.getStage()) {
|
|
case SILStage::Raw:
|
|
// In raw SIL, lexical markers are used for diagnostics and are always
|
|
// present.
|
|
return true;
|
|
case SILStage::Canonical:
|
|
case SILStage::Lowered:
|
|
// In Canonical SIL, lexical markers are used to ensure that object
|
|
// lifetimes do not get observably shortened from the end of a lexical
|
|
// scope. That behavior only occurs when lexical lifetimes is (fully)
|
|
// enabled. (When only diagnostic markers are enabled, the markers are
|
|
// stripped as part of lowering from raw to canonical SIL.)
|
|
return LexicalLifetimes == LexicalLifetimesOption::On;
|
|
}
|
|
}
|
|
|
|
/// Print a simple description of a SILModule for the request evaluator.
|
|
void simple_display(llvm::raw_ostream &out, const SILModule *M);
|
|
|
|
/// Retrieve a SourceLoc for a SILModule that the request evaluator can use for
|
|
/// diagnostics.
|
|
SourceLoc extractNearestSourceLoc(const SILModule *SM);
|
|
|
|
namespace Lowering {
|
|
/// Determine whether the given class will be allocated/deallocated using the
|
|
/// Objective-C runtime, i.e., +alloc and -dealloc.
|
|
LLVM_LIBRARY_VISIBILITY bool usesObjCAllocator(ClassDecl *theClass);
|
|
/// Determine if isolating destructor is needed.
|
|
LLVM_LIBRARY_VISIBILITY bool needsIsolatingDestructor(DestructorDecl *dd);
|
|
|
|
} // namespace Lowering
|
|
} // namespace swift
|
|
|
|
#endif
|