//===--- 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()) F->addSemanticsAttr(cast(A)->Value); // Propagate @_specialize. for (auto *A : Attrs.getAttributes()) { auto *SA = cast(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()) { F->setOptimizationMode(OA->getMode()); } // @_silgen_name and @_cdecl functions may be called from C code somewhere. if (Attrs.hasAttribute() || Attrs.hasAttribute()) 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(); 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() || replacedFunc->getLoweredFunctionType()->hasOpaqueArchetype()); 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(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 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); }