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.
351 lines
13 KiB
C++
351 lines
13 KiB
C++
//===--- DeserializeSIL.h - Read SIL ----------------------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ModuleFile.h"
|
|
#include "SILFormat.h"
|
|
#include "swift/AST/Types.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "swift/SIL/SILMoveOnlyDeinit.h"
|
|
#include "swift/Serialization/SerializedSILLoader.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/Support/SaveAndRestore.h"
|
|
|
|
namespace llvm {
|
|
template <typename Info> class OnDiskIterableChainedHashTable;
|
|
}
|
|
|
|
namespace swift {
|
|
class SILDeserializer {
|
|
using TypeID = serialization::TypeID;
|
|
|
|
ModuleFile *MF;
|
|
SILModule &SILMod;
|
|
DeserializationNotificationHandlerSet *Callback;
|
|
|
|
/// The cursor used to lazily load SILFunctions.
|
|
llvm::BitstreamCursor SILCursor;
|
|
llvm::BitstreamCursor SILIndexCursor;
|
|
|
|
class FuncTableInfo;
|
|
using SerializedFuncTable =
|
|
llvm::OnDiskIterableChainedHashTable<FuncTableInfo>;
|
|
|
|
class StringTableInfo;
|
|
using SerializedStringTable =
|
|
llvm::OnDiskIterableChainedHashTable<StringTableInfo>;
|
|
|
|
//-----
|
|
// Deserialization Caches
|
|
//
|
|
// NOTE: When adding more serialized tables to the deserializer,
|
|
// always add invalidate methods and make sure SILModule always
|
|
// invalidates the deserializer appropriately when it erases a
|
|
// value that we deserialized here. Otherwise, memory corruption
|
|
// may result.
|
|
|
|
std::unique_ptr<SerializedFuncTable> FuncTable;
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILFunction*>> Funcs;
|
|
|
|
std::unique_ptr<SerializedFuncTable> GlobalVarList;
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILGlobalVariable *>>
|
|
GlobalVars;
|
|
|
|
std::unique_ptr<SerializedFuncTable> VTableList;
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILVTable *>> VTables;
|
|
|
|
std::unique_ptr<SerializedFuncTable> MoveOnlyDeinitList;
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILMoveOnlyDeinit *>>
|
|
MoveOnlyDeinits;
|
|
|
|
std::unique_ptr<SerializedFuncTable> WitnessTableList;
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILWitnessTable *>>
|
|
WitnessTables;
|
|
|
|
std::unique_ptr<SerializedFuncTable> DefaultWitnessTableList;
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILDefaultWitnessTable *>>
|
|
DefaultWitnessTables;
|
|
|
|
std::unique_ptr<SerializedFuncTable> DefaultOverrideTableList;
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILDefaultOverrideTable *>>
|
|
DefaultOverrideTables;
|
|
|
|
MutableArrayRef<ModuleFile::PartiallySerialized<SILProperty *>>
|
|
Properties;
|
|
|
|
std::unique_ptr<SerializedFuncTable> DifferentiabilityWitnessList;
|
|
MutableArrayRef<
|
|
ModuleFile::PartiallySerialized<SILDifferentiabilityWitness *>>
|
|
DifferentiabilityWitnesses;
|
|
|
|
/// asmname -> SIL entity name
|
|
std::unique_ptr<SerializedStringTable> AsmNameTable;
|
|
|
|
//-----
|
|
// End Deserialization Caches
|
|
//
|
|
// Before adding a new cache here, please read the comment at the
|
|
// beginning of the deserialization cache section.
|
|
|
|
/// A declaration will only
|
|
llvm::DenseMap<NormalProtocolConformance *, SILWitnessTable *>
|
|
ConformanceToWitnessTableMap;
|
|
|
|
/// Data structures used to perform name lookup for local values.
|
|
llvm::DenseMap<uint32_t, ValueBase*> LocalValues;
|
|
|
|
/// The first two local values are reserved for SILUndef.
|
|
serialization::ValueID LastValueID = 1;
|
|
|
|
/// Data structures used to perform lookup of basic blocks.
|
|
llvm::DenseMap<unsigned, SILBasicBlock*> BlocksByID;
|
|
llvm::DenseMap<SILBasicBlock*, unsigned> UndefinedBlocks;
|
|
unsigned BasicBlockID = 0;
|
|
|
|
/// Return the SILBasicBlock of a given ID.
|
|
SILBasicBlock *getBBForReference(SILFunction *Fn, unsigned ID);
|
|
SILBasicBlock *getBBForDefinition(SILFunction *Fn, SILBasicBlock *Prev,
|
|
unsigned ID);
|
|
|
|
/// Read a SIL function.
|
|
SILFunction *readSILFunction(serialization::DeclID, SILFunction *InFunc,
|
|
StringRef Name, bool declarationOnly,
|
|
bool errorIfEmptyBody = true);
|
|
/// Read a SIL function.
|
|
llvm::Expected<SILFunction *>
|
|
readSILFunctionChecked(serialization::DeclID, SILFunction *InFunc,
|
|
StringRef Name, bool declarationOnly,
|
|
bool errorIfEmptyBody = true, bool forDebugScope = false);
|
|
|
|
/// Read a SIL basic block within a given SIL function.
|
|
SILBasicBlock *readSILBasicBlock(SILFunction *Fn,
|
|
SILBasicBlock *Prev,
|
|
SmallVectorImpl<uint64_t> &scratch);
|
|
/// Read a SIL instruction.
|
|
bool readSILInstruction(SILFunction *Fn,
|
|
SILBuilder &Builder,
|
|
unsigned RecordKind,
|
|
SmallVectorImpl<uint64_t> &scratch);
|
|
|
|
/// Read the SIL function table.
|
|
std::unique_ptr<SerializedFuncTable>
|
|
readFuncTable(ArrayRef<uint64_t> fields, StringRef blobData);
|
|
|
|
/// Read a string -> string mapping table.
|
|
std::unique_ptr<SerializedStringTable>
|
|
readStringTable(ArrayRef<uint64_t> fields, StringRef blobData);
|
|
|
|
/// When an instruction or block argument is defined, this method is used to
|
|
/// register it and update our symbol table.
|
|
void setLocalValue(ValueBase *Value, serialization::ValueID Id);
|
|
|
|
/// Get a reference to a local value with the specified ID and type.
|
|
///
|
|
/// NOTE: \p inContext is expected to be nullptr if we are inserting into a
|
|
/// global variable initializer.
|
|
SILValue getLocalValue(SILFunction *inContext, serialization::ValueID Id,
|
|
SILType Type);
|
|
|
|
SILType getSILType(Type ty, SILValueCategory category,
|
|
SILFunction *inContext);
|
|
|
|
SILDifferentiabilityWitness *
|
|
getSILDifferentiabilityWitnessForReference(StringRef mangledKey);
|
|
|
|
llvm::Expected<const SILDebugScope *>
|
|
readDebugScopes(SILFunction *F, SmallVectorImpl<uint64_t> &scratch,
|
|
SILBuilder &Builder, unsigned kind);
|
|
llvm::Expected<unsigned> readNextRecord(SmallVectorImpl<uint64_t> &scratch);
|
|
std::optional<SILLocation> readLoc(unsigned kind, SmallVectorImpl<uint64_t> &scratch);
|
|
|
|
llvm::DenseMap<unsigned, const SILDebugScope *> ParsedScopes;
|
|
llvm::SmallVector<SILLocation::FilenameAndLocation *> ParsedLocs;
|
|
|
|
SILFunction *getFuncForReference(StringRef Name, SILType Ty, TypeExpansionContext context);
|
|
SILFunction *getFuncForReference(StringRef Name, bool forDebugScope = false);
|
|
SILVTable *readVTable(serialization::DeclID);
|
|
SILMoveOnlyDeinit *readMoveOnlyDeinit(serialization::DeclID);
|
|
SILGlobalVariable *getGlobalForReference(StringRef Name,
|
|
bool byAsmName = false);
|
|
SILGlobalVariable *readGlobalVar(StringRef Name, bool byAsmName = false);
|
|
|
|
/// Read and return the witness table identified with \p WId.
|
|
SILWitnessTable *readWitnessTable(serialization::DeclID WId,
|
|
SILWitnessTable *existingWt);
|
|
|
|
/// Read the witness table identified with \p WId, return the table or
|
|
/// the first error if any.
|
|
llvm::Expected<SILWitnessTable *>
|
|
readWitnessTableChecked(serialization::DeclID WId,
|
|
SILWitnessTable *existingWt);
|
|
|
|
void readWitnessTableEntries(
|
|
llvm::BitstreamEntry &entry,
|
|
std::vector<SILWitnessTable::Entry> &witnessEntries,
|
|
std::vector<ProtocolConformanceRef> &conditionalConformances);
|
|
SILProperty *readProperty(serialization::DeclID);
|
|
SILDefaultWitnessTable *
|
|
readDefaultWitnessTable(serialization::DeclID,
|
|
SILDefaultWitnessTable *existingWt);
|
|
void readDefaultOverrideTableEntries(
|
|
llvm::BitstreamEntry &entry,
|
|
std::vector<SILDefaultOverrideTable::Entry> &entries);
|
|
SILDefaultOverrideTable *
|
|
readDefaultOverrideTable(serialization::DeclID,
|
|
SILDefaultOverrideTable *existingOt);
|
|
SILDifferentiabilityWitness *
|
|
readDifferentiabilityWitness(serialization::DeclID);
|
|
|
|
std::optional<KeyPathPatternComponent>
|
|
readKeyPathComponent(ArrayRef<uint64_t> ListOfValues, unsigned &nextValue);
|
|
|
|
public:
|
|
Identifier getModuleIdentifier() const {
|
|
return MF->getAssociatedModule()->getName();
|
|
}
|
|
FileUnit *getFile() const {
|
|
return MF->getFile();
|
|
}
|
|
SILFunction *lookupSILFunction(SILFunction *InFunc, bool onlyUpdateLinkage);
|
|
SILFunction *lookupSILFunction(StringRef Name,
|
|
bool declarationOnly = false,
|
|
bool byAsmName = false);
|
|
SILGlobalVariable *lookupSILGlobalVariable(StringRef Name,
|
|
bool byAsmName = false);
|
|
bool hasSILFunction(StringRef Name,
|
|
std::optional<SILLinkage> Linkage = std::nullopt);
|
|
SILVTable *lookupVTable(StringRef MangledClassName);
|
|
SILMoveOnlyDeinit *lookupMoveOnlyDeinit(StringRef mangledNominalTypeName);
|
|
SILWitnessTable *lookupWitnessTable(SILWitnessTable *wt);
|
|
SILDefaultWitnessTable *
|
|
lookupDefaultWitnessTable(SILDefaultWitnessTable *wt);
|
|
SILDefaultOverrideTable *
|
|
lookupDefaultOverrideTable(SILDefaultOverrideTable *ot);
|
|
SILDifferentiabilityWitness *
|
|
lookupDifferentiabilityWitness(StringRef mangledDiffWitnessKey);
|
|
|
|
/// Invalidate all cached SILFunctions.
|
|
void invalidateFunctionCache();
|
|
|
|
/// Invalidate a specific cached SILFunction.
|
|
bool invalidateFunction(SILFunction *F);
|
|
|
|
/// Invalidate all cached SILGlobalVariable.
|
|
void invalidateGlobalVariableCache();
|
|
|
|
/// Invalidate a specific cached GlobalVariable.
|
|
bool invalidateGlobalVariable(SILGlobalVariable *gv);
|
|
|
|
/// Invalidate all cached SILVTable.
|
|
void invalidateVTableCache();
|
|
|
|
/// Invalidate a specific cached SILVTable.
|
|
bool invalidateVTable(SILVTable *v);
|
|
|
|
/// Invalidate all cached SILWitnessTable.
|
|
void invalidateWitnessTableCache();
|
|
|
|
/// Invalidate a specific cached SILWitnessTable.
|
|
bool invalidateWitnessTable(SILWitnessTable *v);
|
|
|
|
/// Invalidate all cached SILDefaultWitnessTable.
|
|
void invalidateDefaultWitnessTableCache();
|
|
|
|
/// Invalidate a specific cached SILDefaultWitnessTable.
|
|
bool invalidateDefaultWitnessTable(SILDefaultWitnessTable *v);
|
|
|
|
/// Invalidate all cached SILProperty.
|
|
void invalidatePropertyCache();
|
|
|
|
/// Invalidate a specific cached SILProperty.
|
|
bool invalidateProperty(SILProperty *v);
|
|
|
|
/// Invalidate all cached SILDifferentiabilityWitness.
|
|
void invalidateDifferentiabilityWitnessCache();
|
|
|
|
/// Invalidate a specific cached SILDifferentiabilityWitness.
|
|
bool invalidateDifferentiabilityWitness(SILDifferentiabilityWitness *v);
|
|
|
|
/// Invalidate all caches in this deserializer.
|
|
void invalidateAllCaches() {
|
|
invalidateFunctionCache();
|
|
invalidateGlobalVariableCache();
|
|
invalidateVTableCache();
|
|
invalidateWitnessTableCache();
|
|
invalidateDefaultWitnessTableCache();
|
|
invalidatePropertyCache();
|
|
invalidateDifferentiabilityWitnessCache();
|
|
}
|
|
|
|
/// Deserialize all SILFunctions, VTables, WitnessTables, and
|
|
/// DefaultWitnessTables inside the module, and add them to SILMod.
|
|
///
|
|
/// TODO: Globals.
|
|
void getAll(bool UseCallback = true) {
|
|
llvm::SaveAndRestore<DeserializationNotificationHandlerSet *> SaveCB(
|
|
Callback);
|
|
|
|
if (!UseCallback)
|
|
Callback = nullptr;
|
|
|
|
getAllSILFunctions();
|
|
getAllSILGlobalVariables();
|
|
getAllVTables();
|
|
getAllWitnessTables();
|
|
getAllDefaultWitnessTables();
|
|
getAllDefaultOverrideTables();
|
|
getAllProperties();
|
|
getAllDifferentiabilityWitnesses();
|
|
getAllMoveOnlyDeinits();
|
|
}
|
|
|
|
/// Deserialize all SILFunctions inside the module and add them to SILMod.
|
|
void getAllSILFunctions();
|
|
|
|
/// Deserialize all SILGlobalVariables inside the module and add them to
|
|
/// SILMod.
|
|
void getAllSILGlobalVariables();
|
|
|
|
/// Deserialize all VTables inside the module and add them to SILMod.
|
|
void getAllVTables();
|
|
|
|
/// Deserialize all move only deinit tables inside the module and add them
|
|
/// to SILMod.
|
|
void getAllMoveOnlyDeinits();
|
|
|
|
/// Deserialize all WitnessTables inside the module and add them to SILMod.
|
|
void getAllWitnessTables();
|
|
|
|
/// Deserialize all DefaultWitnessTables inside the module and add them
|
|
/// to SILMod.
|
|
void getAllDefaultWitnessTables();
|
|
|
|
/// Deserialize all DefaultOverrideTables inside the module and add them to
|
|
/// SILMod.
|
|
void getAllDefaultOverrideTables();
|
|
|
|
/// Deserialize all Property descriptors inside the module and add them
|
|
/// to SILMod.
|
|
void getAllProperties();
|
|
|
|
/// Deserialize all DifferentiabilityWitnesses inside the module and add
|
|
/// them to SILMod.
|
|
void getAllDifferentiabilityWitnesses();
|
|
|
|
SILDeserializer(ModuleFile *MF, SILModule &M,
|
|
DeserializationNotificationHandlerSet *callback);
|
|
|
|
// Out of line to avoid instantiation OnDiskChainedHashTable here.
|
|
~SILDeserializer();
|
|
};
|
|
} // end namespace swift
|