mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Previous attempts to update the callgraph explicitly after calls to linkFunction() weren't completely effective because we can deserialize deeply and introduce multiple new function bodies in the process. This gets us a bit closer, but only adds new call graph nodes. It does not currently add edges for everything that gets deserialized (and this is not fatal, so it is a step forward). Swift SVN r27120
110 lines
3.9 KiB
C++
110 lines
3.9 KiB
C++
//===--- Linker.h --------------------------------------------*- C++ -*----===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://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/SILExternalSource.h"
|
|
#include "swift/SIL/SILVisitor.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "swift/Serialization/SerializedSILLoader.h"
|
|
#include <functional>
|
|
|
|
namespace swift {
|
|
|
|
/// Visitor that knows how to link in dependencies of SILInstructions.
|
|
class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, bool> {
|
|
using LinkingMode = SILModule::LinkingMode;
|
|
|
|
/// The SILModule that we are loading from.
|
|
SILModule &Mod;
|
|
|
|
/// The SILLoader that this visitor is using to link.
|
|
SerializedSILLoader *Loader;
|
|
|
|
/// The external SIL source to use when linking this module.
|
|
SILExternalSource *ExternalSource = nullptr;
|
|
|
|
/// Worklist of SILFunctions we are processing.
|
|
llvm::SmallVector<SILFunction *, 128> Worklist;
|
|
|
|
/// A list of callees of the current instruction being visited. cleared after
|
|
/// every instruction is visited.
|
|
llvm::SmallVector<SILFunction *, 4> FunctionDeserializationWorklist;
|
|
|
|
/// The current linking mode.
|
|
LinkingMode Mode;
|
|
|
|
/// The callback which is called each time a new function body is
|
|
/// deserialized.
|
|
std::function<void(SILFunction *)> Callback;
|
|
|
|
public:
|
|
SILLinkerVisitor(SILModule &M, SerializedSILLoader *L,
|
|
SILModule::LinkingMode LinkingMode,
|
|
SILExternalSource *E = nullptr,
|
|
std::function<void(SILFunction *)> Callback =nullptr)
|
|
: Mod(M), Loader(L), ExternalSource(E), Worklist(),
|
|
FunctionDeserializationWorklist(), Mode(LinkingMode),
|
|
Callback(Callback) {}
|
|
|
|
/// Process F, recursively deserializing any thing F may reference.
|
|
bool processFunction(SILFunction *F);
|
|
|
|
/// Process Decl, recursively deserializing any thing that
|
|
/// the SILFunction corresponding to Decl may reference.
|
|
bool processDeclRef(SILDeclRef Decl);
|
|
|
|
/// 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.
|
|
bool visitValueBase(ValueBase *V) { return false; }
|
|
|
|
bool visitApplyInst(ApplyInst *AI);
|
|
bool visitPartialApplyInst(PartialApplyInst *PAI);
|
|
bool visitFunctionRefInst(FunctionRefInst *FRI);
|
|
bool visitProtocolConformance(ProtocolConformance *C,
|
|
const Optional<SILDeclRef> &Member);
|
|
bool visitWitnessMethodInst(WitnessMethodInst *WMI) {
|
|
return visitProtocolConformance(WMI->getConformance(), WMI->getMember());
|
|
}
|
|
bool visitInitExistentialAddrInst(InitExistentialAddrInst *IEI);
|
|
bool visitInitExistentialRefInst(InitExistentialRefInst *IERI);
|
|
bool visitAllocRefInst(AllocRefInst *ARI);
|
|
bool visitMetatypeInst(MetatypeInst *MI);
|
|
|
|
private:
|
|
/// Add a function to our function worklist for processing.
|
|
void addFunctionToWorklist(SILFunction *F) {
|
|
FunctionDeserializationWorklist.push_back(F);
|
|
}
|
|
|
|
/// 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; }
|
|
|
|
bool linkInVTable(ClassDecl *D);
|
|
|
|
// Main loop of the visitor. Called by one of the other *visit* methods.
|
|
bool process();
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|