mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
189 lines
7.6 KiB
C++
189 lines
7.6 KiB
C++
//===--- SILFunctionBuilder.cpp -------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2018 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/SIL/SILFunctionBuilder.h"
|
|
|
|
using namespace swift;
|
|
|
|
SILFunction *SILFunctionBuilder::getOrCreateFunction(
|
|
SILLocation loc, StringRef name, SILLinkage linkage,
|
|
CanSILFunctionType type, IsBare_t isBareSILFunction,
|
|
IsTransparent_t isTransparent, IsSerialized_t isSerialized,
|
|
ProfileCounter entryCount, IsThunk_t isThunk, SubclassScope subclassScope) {
|
|
assert(!type->isNoEscape() && "Function decls always have escaping types.");
|
|
if (auto fn = mod.lookUpFunction(name)) {
|
|
assert(fn->getLoweredFunctionType() == type);
|
|
assert(stripExternalFromLinkage(fn->getLinkage()) ==
|
|
stripExternalFromLinkage(linkage));
|
|
return fn;
|
|
}
|
|
|
|
auto fn = SILFunction::create(mod, linkage, name, type, nullptr, loc,
|
|
isBareSILFunction, isTransparent, isSerialized,
|
|
entryCount, isThunk, subclassScope);
|
|
fn->setDebugScope(new (mod) SILDebugScope(loc, fn));
|
|
return fn;
|
|
}
|
|
|
|
static bool verifySILSelfParameterType(SILDeclRef DeclRef, SILFunction *F,
|
|
CanSILFunctionType FTy) {
|
|
SILModule &M = F->getModule();
|
|
SILParameterInfo PInfo = FTy->getSelfParameter();
|
|
CanType CTy = PInfo.getType();
|
|
SILType Ty = SILType::getPrimitiveObjectType(CTy);
|
|
|
|
// We do not care about trivial parameters (for now). There seem to be
|
|
// cases where we lower them as unowned.
|
|
//
|
|
// *NOTE* We do not run this check when we have a generic type since
|
|
// *generic types do not have type lowering and are always treated as
|
|
// *non-trivial since we do not know the type.
|
|
if (CTy->hasArchetype() || CTy->hasTypeParameter() ||
|
|
M.getTypeLowering(Ty).isTrivial())
|
|
return true;
|
|
|
|
// If this function is a constructor or destructor, bail. These have @owned
|
|
// parameters.
|
|
if (DeclRef.isConstructor() || DeclRef.isDestructor())
|
|
return true;
|
|
|
|
// Otherwise, if this function type has a guaranteed self parameter type,
|
|
// make sure that we have a +0 self param.
|
|
return !FTy->getExtInfo().hasGuaranteedSelfParam() || PInfo.isGuaranteed() ||
|
|
PInfo.isIndirectMutating();
|
|
}
|
|
|
|
static void addFunctionAttributes(SILFunction *F, DeclAttributes &Attrs,
|
|
SILModule &M) {
|
|
for (auto *A : Attrs.getAttributes<SemanticsAttr>())
|
|
F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
|
|
|
|
// Propagate @_specialize.
|
|
for (auto *A : Attrs.getAttributes<SpecializeAttr>()) {
|
|
auto *SA = cast<SpecializeAttr>(A);
|
|
auto kind =
|
|
SA->getSpecializationKind() == SpecializeAttr::SpecializationKind::Full
|
|
? SILSpecializeAttr::SpecializationKind::Full
|
|
: SILSpecializeAttr::SpecializationKind::Partial;
|
|
F->addSpecializeAttr(SILSpecializeAttr::create(M, SA->getRequirements(),
|
|
SA->isExported(), kind));
|
|
}
|
|
|
|
if (auto *OA = Attrs.getAttribute<OptimizeAttr>()) {
|
|
F->setOptimizationMode(OA->getMode());
|
|
}
|
|
|
|
// @_silgen_name and @_cdecl functions may be called from C code somewhere.
|
|
if (Attrs.hasAttribute<SILGenNameAttr>() || Attrs.hasAttribute<CDeclAttr>())
|
|
F->setHasCReferences(true);
|
|
|
|
if (Attrs.hasAttribute<WeakLinkedAttr>())
|
|
F->setWeakLinked();
|
|
}
|
|
|
|
SILFunction *
|
|
SILFunctionBuilder::getOrCreateFunction(SILLocation loc, SILDeclRef constant,
|
|
ForDefinition_t forDefinition,
|
|
ProfileCounter entryCount) {
|
|
auto nameTmp = constant.mangle();
|
|
auto constantType = mod.Types.getConstantFunctionType(constant);
|
|
SILLinkage linkage = constant.getLinkage(forDefinition);
|
|
|
|
if (auto fn = mod.lookUpFunction(nameTmp)) {
|
|
assert(fn->getLoweredFunctionType() == constantType);
|
|
assert(fn->getLinkage() == linkage ||
|
|
(forDefinition == ForDefinition_t::NotForDefinition &&
|
|
fn->getLinkage() ==
|
|
constant.getLinkage(ForDefinition_t::ForDefinition)));
|
|
if (forDefinition) {
|
|
// In all the cases where getConstantLinkage returns something
|
|
// different for ForDefinition, it returns an available-externally
|
|
// linkage.
|
|
if (isAvailableExternally(fn->getLinkage())) {
|
|
fn->setLinkage(constant.getLinkage(ForDefinition));
|
|
}
|
|
}
|
|
return fn;
|
|
}
|
|
|
|
IsTransparent_t IsTrans =
|
|
constant.isTransparent() ? IsTransparent : IsNotTransparent;
|
|
IsSerialized_t IsSer = constant.isSerialized();
|
|
|
|
EffectsKind EK = constant.hasEffectsAttribute()
|
|
? constant.getEffectsAttribute()
|
|
: EffectsKind::Unspecified;
|
|
|
|
Inline_t inlineStrategy = InlineDefault;
|
|
if (constant.isNoinline())
|
|
inlineStrategy = NoInline;
|
|
else if (constant.isAlwaysInline())
|
|
inlineStrategy = AlwaysInline;
|
|
|
|
StringRef name = allocateCopy(nameTmp);
|
|
auto *F =
|
|
SILFunction::create(mod, linkage, name, constantType, nullptr, None,
|
|
IsNotBare, IsTrans, IsSer, entryCount, IsNotThunk,
|
|
constant.getSubclassScope(), inlineStrategy, EK);
|
|
F->setDebugScope(new (mod) SILDebugScope(loc, F));
|
|
|
|
F->setGlobalInit(constant.isGlobal());
|
|
if (constant.hasDecl()) {
|
|
auto decl = constant.getDecl();
|
|
|
|
if (constant.isForeign && decl->hasClangNode())
|
|
F->setClangNodeOwner(decl);
|
|
|
|
if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
|
|
auto *storage = accessor->getStorage();
|
|
// Add attributes for e.g. computed properties.
|
|
addFunctionAttributes(F, storage->getAttrs(), mod);
|
|
}
|
|
addFunctionAttributes(F, decl->getAttrs(), mod);
|
|
}
|
|
|
|
// If this function has a self parameter, make sure that it has a +0 calling
|
|
// convention. This cannot be done for general function types, since
|
|
// function_ref's SILFunctionTypes do not have archetypes associated with
|
|
// it.
|
|
CanSILFunctionType FTy = F->getLoweredFunctionType();
|
|
if (FTy->hasSelfParam()) {
|
|
(void)&verifySILSelfParameterType;
|
|
assert(verifySILSelfParameterType(constant, F, FTy) &&
|
|
"Invalid signature for SIL Self parameter type");
|
|
}
|
|
|
|
return F;
|
|
}
|
|
|
|
SILFunction *SILFunctionBuilder::getOrCreateSharedFunction(
|
|
SILLocation loc, StringRef name, CanSILFunctionType type,
|
|
IsBare_t isBareSILFunction, IsTransparent_t isTransparent,
|
|
IsSerialized_t isSerialized, ProfileCounter entryCount, IsThunk_t isThunk) {
|
|
return getOrCreateFunction(loc, name, SILLinkage::Shared, type,
|
|
isBareSILFunction, isTransparent, isSerialized,
|
|
entryCount, isThunk, SubclassScope::NotApplicable);
|
|
}
|
|
|
|
SILFunction *SILFunctionBuilder::createFunction(
|
|
SILLinkage linkage, StringRef name, CanSILFunctionType loweredType,
|
|
GenericEnvironment *genericEnv, Optional<SILLocation> loc,
|
|
IsBare_t isBareSILFunction, IsTransparent_t isTrans,
|
|
IsSerialized_t isSerialized, ProfileCounter entryCount, IsThunk_t isThunk,
|
|
SubclassScope subclassScope, Inline_t inlineStrategy, EffectsKind EK,
|
|
SILFunction *InsertBefore, const SILDebugScope *DebugScope) {
|
|
return SILFunction::create(mod, linkage, name, loweredType, genericEnv, loc,
|
|
isBareSILFunction, isTrans, isSerialized,
|
|
entryCount, isThunk, subclassScope, inlineStrategy,
|
|
EK, InsertBefore, DebugScope);
|
|
}
|