Stabilize and simplify SIL linkage and serialization

The main point of this change is to make sure that a shared function always has a body: both, in the optimizer pipeline and in the swiftmodule file.
This is important because the compiler always needs to emit code for a shared function. Shared functions cannot be referenced from outside the module.
In several corner cases we missed to maintain this invariant which resulted in unresolved-symbol linker errors.

As side-effect of this change we can drop the shared_external SIL linkage and the IsSerializable flag, which simplifies the serialization and linkage concept.
This commit is contained in:
Erik Eckstein
2022-03-07 09:36:53 +01:00
parent 05a3f1fa84
commit 6a020f8f15
159 changed files with 790 additions and 947 deletions

View File

@@ -167,7 +167,7 @@ public:
llvm::DenseMap<const SILBasicBlock *, std::string>;
enum class LinkingMode : uint8_t {
/// Link functions with non-public linkage. Used by the mandatory pipeline.
/// Link functions with shared linkage. Used by the mandatory pipeline.
LinkNormal,
/// Link all functions. Used by the performance pipeine.
@@ -349,6 +349,8 @@ private:
/// 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 non transparent functions.
/// This gets set in NonTransparent OwnershipModelEliminator pass.
@@ -455,6 +457,12 @@ public:
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();
@@ -688,9 +696,20 @@ public:
/// \return null if this module has no such function
SILFunction *lookUpFunction(SILDeclRef fnRef);
/// Attempt to deserialize the SILFunction. Returns true if deserialization
/// succeeded, false otherwise.
bool loadFunction(SILFunction *F);
/// 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,
Optional<SILLinkage> linkage = None);
/// Update the linkage of the SILFunction with the linkage of the serialized
/// function.
@@ -699,19 +718,10 @@ public:
/// AST, e.g. cross-module-optimization can change the SIL linkages.
void updateFunctionLinkage(SILFunction *F);
/// Attempt to link the SILFunction. Returns true if linking succeeded, false
/// otherwise.
/// Attempt to deserialize function \p F and all required referenced functions.
///
/// \return false if the linking failed.
bool linkFunction(SILFunction *F,
LinkingMode LinkMode = LinkingMode::LinkNormal);
/// Check if a given function exists in any of the modules with a
/// required linkage, i.e. it can be linked by linkFunction.
///
/// \return null if this module has no such function. Otherwise
/// the declaration of a function.
SILFunction *findFunction(StringRef Name, SILLinkage Linkage);
/// Returns true if linking succeeded, false otherwise.
bool linkFunction(SILFunction *F, LinkingMode LinkMode);
/// Check if a given function exists in any of the modules.
/// i.e. it can be linked by linkFunction.
@@ -725,15 +735,15 @@ public:
/// table.
/// \arg deserializeLazily If we cannot find the witness table should we
/// attempt to lazily deserialize it.
SILWitnessTable *
lookUpWitnessTable(ProtocolConformanceRef C, bool deserializeLazily=true);
SILWitnessTable *
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily=true);
SILWitnessTable *lookUpWitnessTable(const ProtocolConformance *C);
/// 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);
SILDeclRef Requirement,
SILModule::LinkingMode linkingMode);
/// Look up the SILDefaultWitnessTable representing the default witnesses
/// of a resilient protocol, if any.