//===--- 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()) 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); if (Attrs.hasAttribute()) 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(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 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); }