1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
//===--- Linker.h -----------------------------------------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_LINKER_H
#define SWIFT_SIL_LINKER_H
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SIL/SILModule.h"
#include <functional>
namespace swift {
/// Visits the call graph and makes sure that all required functions (according
/// to the linking `Mode`) are de-serialized and the `isSerialized` flag is set
/// correctly.
///
/// If the Mode is LinkNormal, just de-serialize the bare minimum of what's
/// required for a non-optimized compilation. That are all referenced shared
/// functions, because shared functions must have a body.
///
/// If the Mode is LinkAll, de-serialize the maximum amount of functions - for
/// optimized compilation.
///
/// Also make sure that shared functions which are referenced from "IsSerialized"
/// functions also have the "IsSerialized" flag set.
/// Usually this already is enforced by SILGen and all passes which create new
/// functions.
/// Only in case a de-serialized function references a shared function which
/// already exists in the module as "IsNotSerialized", it's required to explicitly
/// set the "IsSerialized" flag.
///
/// Example:
///
/// Before de-serialization:
/// \code
/// sil @foo {
/// function_ref @publicFuncInOtherModule
/// function_ref @specializedFunction
/// }
/// sil shared @specializedFunction { // IsNotSerialized
/// function_ref @otherSpecializedFunction
/// }
/// sil shared @otherSpecializedFunction { // IsNotSerialized
/// }
/// \endcode
///
/// After de-serialization:
/// \code
/// sil @foo {
/// function_ref @publicFuncInOtherModule
/// function_ref @specializedFunction
/// }
/// sil public_external [serialized] @publicFuncInOtherModule {
/// function_ref @specializedFunction
/// }
/// // Need to be changed to "IsSerialized"
/// sil shared [serialized] @specializedFunction {
/// function_ref @otherSpecializedFunction
/// }
/// sil shared [serialized] @otherSpecializedFunction {
/// }
/// \endcode
///
class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, void> {
using LinkingMode = SILModule::LinkingMode;
/// The SILModule that we are loading from.
SILModule &Mod;
/// Break cycles visiting recursive protocol conformances.
llvm::DenseSet<ProtocolConformance *> VisitedConformances;
/// Worklist of SILFunctions we are processing.
llvm::SmallVector<SILFunction *, 128> Worklist;
llvm::SmallVector<SILFunction *, 32> toVerify;
/// The current linking mode.
LinkingMode Mode;
/// Whether any functions were deserialized.
bool Changed;
public:
SILLinkerVisitor(SILModule &M, SILModule::LinkingMode LinkingMode)
: Mod(M), Worklist(), Mode(LinkingMode), Changed(false) {}
/// Process F, recursively deserializing any thing F may reference.
/// Returns true if any deserialization was performed.
bool processFunction(SILFunction *F);
/// Process the witnesstable of \p conformanceRef.
/// Returns true if any deserialization was performed.
bool processConformance(ProtocolConformanceRef conformanceRef);
/// Deserialize the VTable mapped to C if it exists and all SIL the VTable
/// transitively references.
///
/// This method assumes that the caller made sure that no vtable existed in
/// Mod.
SILVTable *processClassDecl(const ClassDecl *C);
/// We do not want to visit callee functions if we just have a value base.
void visitSILInstruction(SILInstruction *I) { }
void visitApplyInst(ApplyInst *AI);
void visitTryApplyInst(TryApplyInst *TAI);
void visitPartialApplyInst(PartialApplyInst *PAI);
void visitFunctionRefInst(FunctionRefInst *FRI);
void visitDynamicFunctionRefInst(DynamicFunctionRefInst *FRI);
void visitPreviousDynamicFunctionRefInst(PreviousDynamicFunctionRefInst *FRI);
void visitProtocolConformance(ProtocolConformanceRef C);
void visitApplySubstitutions(SubstitutionMap subs);
void visitWitnessMethodInst(WitnessMethodInst *WMI) {
visitProtocolConformance(WMI->getConformance());
}
void visitInitExistentialAddrInst(InitExistentialAddrInst *IEI);
void visitInitExistentialRefInst(InitExistentialRefInst *IERI);
void visitAllocRefInst(AllocRefInst *ARI);
void visitAllocRefDynamicInst(AllocRefDynamicInst *ARI);
void visitMetatypeInst(MetatypeInst *MI);
void visitGlobalAddrInst(GlobalAddrInst *i);
private:
/// Cause a function to be deserialized, and visit all other functions
/// referenced from this function according to the linking mode.
void deserializeAndPushToWorklist(SILFunction *F);
/// Consider a function for deserialization if the current linking mode
/// requires it.
///
/// If `callerSerializedKind` is IsSerialized, then all shared
/// functions which are referenced from `F` are set to be serialized.
void maybeAddFunctionToWorklist(SILFunction *F,
SerializedKind_t callerSerializedKind);
/// Is the current mode link all? Link all implies we should try and link
/// everything, not just transparent/shared functions.
bool isLinkAll() const {
return Mode == LinkingMode::LinkAll ||
Mod.getASTContext().LangOpts.hasFeature(Feature::Embedded);
}
void linkInVTable(ClassDecl *D);
// Main loop of the visitor. Called by one of the other *visit* methods.
void process();
};
} // end namespace swift
#endif
|