Files
swift-mirror/lib/SILPasses/Link.cpp
Jordan Rose f165afe1aa Replace "-enable-sil-linking=false" with "-disable-sil-linking".
Also, restructure so that the option isn't declared in a random library file.
(And do the same with "-sil-link-all".)

Part of the migration to the new driver.

Swift SVN r13184
2014-01-31 00:02:46 +00:00

146 lines
4.8 KiB
C++

//===--- Link.cpp - Link in transparent SILFunctions from module ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "link"
#include "swift/SILPasses/Passes.h"
#include "swift/AST/Module.h"
#include "swift/Serialization/SerializedSILLoader.h"
#include "swift/SIL/SILExternalSource.h"
#include "swift/SIL/SILModule.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
using namespace swift;
STATISTIC(NumFuncLinked, "Number of SIL functions linked");
namespace {
class Callback : public SerializedSILLoader::Callback {
void didDeserialize(Module *M, SILFunction *fn) override {
updateLinkage(fn);
}
void didDeserialize(Module *M, SILGlobalVariable *var) override {
updateLinkage(var);
}
void didDeserialize(Module *M, SILVTable *vtable) override {
// TODO: should vtables get linkage?
//updateLinkage(vtable);
}
template <class T> void updateLinkage(T *decl) {
switch (decl->getLinkage()) {
case SILLinkage::Public:
decl->setLinkage(SILLinkage::PublicExternal);
return;
case SILLinkage::Hidden:
decl->setLinkage(SILLinkage::HiddenExternal);
return;
case SILLinkage::Shared:
case SILLinkage::Private: // ?
case SILLinkage::PublicExternal:
case SILLinkage::HiddenExternal:
return;
}
}
};
}
//===----------------------------------------------------------------------===//
// Top Level Driver
//===----------------------------------------------------------------------===//
void swift::performSILLinking(SILModule *M, bool LinkAll) {
Callback callback;
SerializedSILLoader *SILLoader = SerializedSILLoader::create(
M->getASTContext(), M, &callback);
SILExternalSource *ExternalSource = M->getExternalSource();
SmallVector<SILFunction*, 128> Worklist;
for (auto &Fn : *M)
Worklist.push_back(&Fn);
while (!Worklist.empty()) {
auto Fn = Worklist.pop_back_val();
for (auto &BB : *Fn) {
for (auto I = BB.begin(), E = BB.end(); I != E; I++) {
SILFunction *CalleeFunction = nullptr;
bool TryLinking = false;
if (ApplyInst *AI = dyn_cast<ApplyInst>(I)) {
SILValue Callee = AI->getCallee();
// Handles FunctionRefInst only.
if (FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(Callee.getDef())) {
CalleeFunction = FRI->getReferencedFunction();
// When EnableLinkAll is true, we always link the Callee.
TryLinking = LinkAll || AI->isTransparent() ||
CalleeFunction->getLinkage() == SILLinkage::Private;
}
}
else if (PartialApplyInst *PAI = dyn_cast<PartialApplyInst>(I)) {
SILValue Callee = PAI->getCallee();
// Handles FunctionRefInst only.
if (FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(Callee.getDef())) {
CalleeFunction = FRI->getReferencedFunction();
// When EnableLinkAll is true, we always link the Callee.
TryLinking = LinkAll || CalleeFunction->isTransparent() ||
CalleeFunction->getLinkage() == SILLinkage::Private;
} else {
continue;
}
}
else if (FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(I)) {
// When EnableLinkAll is true, we link the function referenced by
// FunctionRefInst.
CalleeFunction = LinkAll ? FRI->getReferencedFunction() :
nullptr;
TryLinking = LinkAll;
}
if (!CalleeFunction)
continue;
// The ExternalSource may wish to rewrite non-empty bodies.
if (ExternalSource) {
if (auto NewFn = ExternalSource->lookupSILFunction(CalleeFunction)) {
Worklist.push_back(NewFn);
++NumFuncLinked;
continue;
}
}
CalleeFunction->setBare(IsBare);
if (CalleeFunction->empty()) {
// Try to find the definition in a serialized module when callee is
// currently empty.
if (TryLinking) {
if (auto NewFn = SILLoader->lookupSILFunction(CalleeFunction)) {
Worklist.push_back(NewFn);
++NumFuncLinked;
continue;
}
}
}
}
}
}
if (LinkAll) {
SILLoader->getAllVTables();
SILLoader->getAllWitnessTables();
}
}