Skip to content

[WIP] Serialize local functions inside transparent functions #1814

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ class SILFunction
/// Set the function's linkage attribute.
void setLinkage(SILLinkage linkage) { Linkage = unsigned(linkage); }

/// Returns true if this function can be referenced from a fragile function
/// body.
bool hasValidLinkageForFragileRef() const;

/// Get's the effective linkage which is used to derive the llvm linkage.
/// Usually this is the same as getLinkage(), except in one case: if this
/// function is a method in a class which has higher visibility than the
Expand Down
4 changes: 0 additions & 4 deletions include/swift/SILOptimizer/Utils/Local.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,6 @@ bool tryCheckedCastBrJumpThreading(SILFunction *Fn, DominanceInfo *DT,

void recalcDomTreeForCCBOpt(DominanceInfo *DT, SILFunction &F);

/// Checks if a symbol with a given linkage can be referenced from fragile
/// functions.
bool isValidLinkageForFragileRef(SILLinkage linkage);

/// A structure containing callbacks that are called when an instruction is
/// removed or added.
struct InstModCallbacks {
Expand Down
28 changes: 25 additions & 3 deletions lib/SIL/SILFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,9 +510,31 @@ bool SILFunction::hasName(const char *Name) const {
return getName() == Name;
}

/// Helper method which returns true if the linkage of the SILFunction
/// indicates that the objects definition might be required outside the
/// current SILModule.
/// Returns true if this function can be referenced from a fragile function
/// body.
bool SILFunction::hasValidLinkageForFragileRef() const {
// Fragile functions can reference other fragile functions.
if (isFragile())
return true;

// Fragile functions can reference 'static inline' functions imported
// from C.
if (hasForeignBody())
return true;

// Fragile functions can reference non-fragile shared functions only
// if they are thunks.
SILLinkage linkage = getLinkage();
if (hasSharedVisibility(linkage))
return isThunk();

// Otherwise, only public functions can be referenced.
return hasPublicVisibility(linkage);
}

/// Helper method which returns true if the linkage of the SILFunction
/// indicates that the objects definition might be required outside the
/// current SILModule.
bool
SILFunction::isPossiblyUsedExternally() const {
return swift::isPossiblyUsedExternally(getLinkage(),
Expand Down
35 changes: 3 additions & 32 deletions lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,35 +902,6 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
verifyLLVMIntrinsic(BI, BI->getIntrinsicInfo().ID);
}

bool isValidLinkageForFragileRef(SILLinkage linkage) {
switch (linkage) {
case SILLinkage::Private:
case SILLinkage::PrivateExternal:
case SILLinkage::Hidden:
case SILLinkage::HiddenExternal:
return false;

case SILLinkage::Shared:
case SILLinkage::SharedExternal:
// This allows fragile functions to reference thunks, generated
// methods on Clang types, and optimizer specializations.
return true;

case SILLinkage::Public:
case SILLinkage::PublicExternal:
return true;
}
}

bool isValidLinkageForFragileRef(const SILFunction *RefF) {
if (RefF->isFragile() ||
RefF->isExternalDeclaration()) {
return true;
}

return isValidLinkageForFragileRef(RefF->getLinkage());
}

/// Returns true if \p FRI is only used as a callee and will always be
/// inlined at those call sites.
static bool isAlwaysInlined(FunctionRefInst *FRI) {
Expand All @@ -955,7 +926,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
if (F.isFragile()) {
SILFunction *RefF = FRI->getReferencedFunction();
require(isAlwaysInlined(FRI)
|| isValidLinkageForFragileRef(RefF),
|| RefF->hasValidLinkageForFragileRef(),
"function_ref inside fragile function cannot "
"reference a private or hidden symbol");
}
Expand All @@ -966,7 +937,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
if (F.isFragile()) {
SILGlobalVariable *RefG = AGI->getReferencedGlobal();
require(RefG->isFragile()
|| isValidLinkageForFragileRef(RefG->getLinkage()),
|| hasPublicVisibility(RefG->getLinkage()),
"alloc_global inside fragile function cannot "
"reference a private or hidden symbol");
}
Expand All @@ -982,7 +953,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
if (F.isFragile()) {
SILGlobalVariable *RefG = GAI->getReferencedGlobal();
require(RefG->isFragile()
|| isValidLinkageForFragileRef(RefG->getLinkage()),
|| hasPublicVisibility(RefG->getLinkage()),
"global_addr inside fragile function cannot "
"reference a private or hidden symbol");
}
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ PromotedParamCloner::initCloned(SILFunction *Orig,
auto *Fn = M.getOrCreateFunction(
SILLinkage::Shared, ClonedName, ClonedTy, Orig->getContextGenericParams(),
Orig->getLocation(), Orig->isBare(), IsNotTransparent, Orig->isFragile(),
Orig->isThunk(), Orig->getClassVisibility(), Orig->getInlineStrategy(),
IsThunk, Orig->getClassVisibility(), Orig->getInlineStrategy(),
Orig->getEffectsKind(), Orig, Orig->getDebugScope());
for (auto &Attr : Orig->getSemanticsAttrs()) {
Fn->addSemanticsAttr(Attr);
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Transforms/FunctionSignatureOptCloner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ createEmptyFunctionWithOptimizedSig(const std::string &NewFName) {
// Create the new function.
auto *NewF = M.getOrCreateFunction(
F->getLinkage(), NewFName, NewFTy, nullptr, F->getLocation(), F->isBare(),
F->isTransparent(), F->isFragile(), F->isThunk(), F->getClassVisibility(),
F->isTransparent(), F->isFragile(), IsThunk, F->getClassVisibility(),
F->getInlineStrategy(), F->getEffectsKind(), 0, F->getDebugScope(),
F->getDeclContext());

Expand Down
3 changes: 1 addition & 2 deletions lib/SILOptimizer/Utils/Devirtualize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,7 @@ bool swift::canDevirtualizeClassMethod(FullApplySite AI,
if (AI.getFunction()->isFragile()) {
// function_ref inside fragile function cannot reference a private or
// hidden symbol.
if (!(F->isFragile() || isValidLinkageForFragileRef(F->getLinkage()) ||
F->isExternalDeclaration()))
if (!F->hasValidLinkageForFragileRef())
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Utils/GenericCloner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ SILFunction *GenericCloner::initCloned(SILFunction *Orig,
getSpecializedLinkage(Orig, Orig->getLinkage()), NewName,
ReInfo.getSpecializedType(), nullptr,
Orig->getLocation(), Orig->isBare(), Orig->isTransparent(),
Orig->isFragile(), Orig->isThunk(), Orig->getClassVisibility(),
Orig->isFragile(), IsThunk, Orig->getClassVisibility(),
Orig->getInlineStrategy(), Orig->getEffectsKind(), Orig,
Orig->getDebugScope(), Orig->getDeclContext());
NewF->setDeclCtx(Orig->getDeclContext());
Expand Down
26 changes: 1 addition & 25 deletions lib/SILOptimizer/Utils/Local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1481,28 +1481,6 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
return (NewI) ? NewI : AI;
}

bool swift::isValidLinkageForFragileRef(SILLinkage linkage) {
switch (linkage) {
case SILLinkage::Private:
case SILLinkage::PrivateExternal:
case SILLinkage::Hidden:
case SILLinkage::HiddenExternal:
return false;

case SILLinkage::Shared:
case SILLinkage::SharedExternal:
// This handles some kind of generated functions, like constructors
// of clang imported types.
// TODO: check why those functions are not fragile anyway and make
// a less conservative check here.
return true;

case SILLinkage::Public:
case SILLinkage::PublicExternal:
return true;
}
}

/// Create a call of _bridgeToObjectiveC which converts an _ObjectiveCBridgeable
/// instance into a bridged ObjC type.
SILInstruction *
Expand Down Expand Up @@ -1568,9 +1546,7 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
"Implementation of _bridgeToObjectiveC could not be found");

if (Inst->getFunction()->isFragile() &&
!(BridgedFunc->isFragile() ||
isValidLinkageForFragileRef(BridgedFunc->getLinkage()) ||
BridgedFunc->isExternalDeclaration()))
!BridgedFunc->hasValidLinkageForFragileRef())
return nullptr;

auto ParamTypes = BridgedFunc->getLoweredFunctionType()->getParameters();
Expand Down
2 changes: 2 additions & 0 deletions lib/Serialization/SerializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ void SILSerializer::addReferencedSILFunction(const SILFunction *F,
// have enough information at the time we emit the function to
// know if it should be marked fragile or not.
if (F->getLinkage() == SILLinkage::Shared && !DeclOnly) {
assert(F->isThunk() && "Reference to non-thunk, non-fragile shared "
"function from a fragile function");
FuncsToEmit[F] = false;
Worklist.push_back(F);
return;
Expand Down
1 change: 1 addition & 0 deletions stdlib/public/Platform/tgmath.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ public func lgamma(x: ${T}) -> (${T}, Int) {
#else
% # On Darwin platform,
% # The real lgamma_r is not imported because it hides behind macro _REENTRANT.
@_versioned
@warn_unused_result
@_silgen_name("_swift_Darwin_lgamma${f}_r")
func _swift_Darwin_lgamma${f}_r(_: ${CT},
Expand Down
3 changes: 2 additions & 1 deletion stdlib/public/core/ArrayBody.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import SwiftShims

internal struct _ArrayBody {
var _storage: _SwiftArrayBodyStorage


@_versioned
init(count: Int, capacity: Int, elementTypeIsBridgedVerbatim: Bool = false) {
_sanityCheck(count >= 0)
_sanityCheck(capacity >= 0)
Expand Down
5 changes: 5 additions & 0 deletions stdlib/public/core/AssertCommon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func _reportFatalError(
_ message: UnsafePointer<UInt8>, _ messageLength: UInt,
flags: UInt32)

@_versioned
@_silgen_name("_swift_stdlib_reportUnimplementedInitializerInFile")
func _reportUnimplementedInitializerInFile(
className: UnsafePointer<UInt8>, _ classNameLength: UInt,
Expand All @@ -94,6 +95,7 @@ func _reportUnimplementedInitializerInFile(
_ line: UInt, _ column: UInt,
flags: UInt32)

@_versioned
@_silgen_name("_swift_stdlib_reportUnimplementedInitializer")
func _reportUnimplementedInitializer(
className: UnsafePointer<UInt8>, _ classNameLength: UInt,
Expand All @@ -105,6 +107,7 @@ func _reportUnimplementedInitializer(
///
/// This function should not be inlined because it is cold and inlining just
/// bloats code.
@_versioned
@noreturn @inline(never)
@_semantics("stdlib_binary_only")
func _assertionFailed(
Expand Down Expand Up @@ -135,6 +138,7 @@ func _assertionFailed(
///
/// This function should not be inlined because it is cold and inlining just
/// bloats code.
@_versioned
@noreturn @inline(never)
@_semantics("stdlib_binary_only")
func _assertionFailed(
Expand Down Expand Up @@ -166,6 +170,7 @@ func _assertionFailed(
///
/// This function should not be inlined because it is cold and it inlining just
/// bloats code.
@_versioned
@noreturn @inline(never)
@_semantics("stdlib_binary_only")
@_semantics("arc.programtermination_point")
Expand Down
1 change: 1 addition & 0 deletions stdlib/public/core/HashedCollections.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -1749,6 +1749,7 @@ final internal class _Native${Self}StorageImpl<${TypeParameters}> :
}
}

@_versioned
internal var _capacity: Int {
@warn_unused_result
get {
Expand Down
2 changes: 2 additions & 0 deletions stdlib/public/core/IntegerArithmetic.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ public prefix func + <T : SignedNumber>(x: T) -> T {

//===--- abs(x) -----------------------------------------------------------===//
public struct _Abs {}

@_versioned
internal func _abs<Args>(args: Args) -> (_Abs, Args) {
return (_Abs(), args)
}
Expand Down
3 changes: 3 additions & 0 deletions stdlib/public/core/Process.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ public enum Process {
return result
}

@_versioned
internal static var _argc: CInt = CInt()

@_versioned
internal static var _unsafeArgv:
UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
= nil
Expand Down