blob: da2e378dc657053a24163ab11b12a64f82648c19 [file] [log] [blame]
//===--- 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"
#include "swift/AST/Availability.h"
#include "swift/AST/Decl.h"
using namespace swift;
SILFunction *SILFunctionBuilder::getOrCreateFunction(
SILLocation loc, StringRef name, SILLinkage linkage,
CanSILFunctionType type, IsBare_t isBareSILFunction,
IsTransparent_t isTransparent, IsSerialized_t isSerialized,
IsDynamicallyReplaceable_t isDynamic, 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, isDynamic, isThunk, subclassScope);
fn->setDebugScope(new (mod) SILDebugScope(loc, fn));
return fn;
}
void SILFunctionBuilder::addFunctionAttributes(SILFunction *F,
DeclAttributes &Attrs,
SILModule &M,
SILDeclRef constant) {
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);
// Propagate @_dynamicReplacement(for:).
if (constant.isNull())
return;
auto *decl = constant.getDecl();
// Only emit replacements for the objc entry point of objc methods.
if (decl->isObjC() &&
F->getLoweredFunctionType()->getExtInfo().getRepresentation() !=
SILFunctionTypeRepresentation::ObjCMethod)
return;
auto *replacedFuncAttr = Attrs.getAttribute<DynamicReplacementAttr>();
if (!replacedFuncAttr)
return;
auto *replacedDecl = replacedFuncAttr->getReplacedFunction();
assert(replacedDecl);
if (decl->isObjC()) {
F->setObjCReplacement(replacedDecl);
return;
}
if (!constant.canBeDynamicReplacement())
return;
SILDeclRef declRef(replacedDecl, constant.kind, false);
auto *replacedFunc =
getOrCreateFunction(replacedDecl, declRef, NotForDefinition);
assert(replacedFunc->getLoweredFunctionType() == F->getLoweredFunctionType());
F->setDynamicallyReplacedFunction(replacedFunc);
}
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 = mod.allocateCopy(nameTmp);
IsDynamicallyReplaceable_t IsDyn = IsNotDynamic;
if (constant.isDynamicallyReplaceable()) {
IsDyn = IsDynamic;
IsTrans = IsNotTransparent;
}
auto *F = SILFunction::create(mod, linkage, name, constantType, nullptr, None,
IsNotBare, IsTrans, IsSer, entryCount, IsDyn,
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 (decl->isWeakImported(/*forModule=*/nullptr, availCtx))
F->setWeakLinked();
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, constant);
}
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,
IsDynamicallyReplaceable_t isDynamic) {
return getOrCreateFunction(loc, name, SILLinkage::Shared, type,
isBareSILFunction, isTransparent, isSerialized,
isDynamic, 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, IsDynamicallyReplaceable_t isDynamic,
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, isDynamic, isThunk, subclassScope,
inlineStrategy, EK, InsertBefore, DebugScope);
}