//===--- SILInliner.h - Inlines SIL functions -------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 // //===----------------------------------------------------------------------===// // // This file defines the SILInliner class, used for inlining SIL functions into // function application sites // //===----------------------------------------------------------------------===// #ifndef SWIFT_SIL_SILINLINER_H #define SWIFT_SIL_SILINLINER_H #include "llvm/ADT/DenseMap.h" #include "swift/SIL/TypeSubstCloner.h" #include namespace swift { // For now Free is 0 and Expensive is 1. This can be changed in the future by // adding more categories. enum class InlineCost : unsigned { Free = 0, Expensive = 1 }; /// Return the 'cost' of one instruction. Instructions that are expected to /// disappear at the LLVM IR level are assigned a cost of 'Free'. InlineCost instructionInlineCost(SILInstruction &I); class SILInliner : public TypeSubstCloner { public: friend class SILVisitor; friend class SILCloner; enum class InlineKind { MandatoryInline, PerformanceInline }; SILInliner(SILFunction &To, SILFunction &From, InlineKind IKind, SubstitutionList ApplySubs, SILOpenedArchetypesTracker &OpenedArchetypesTracker, CloneCollector::CallbackType Callback = nullptr) : TypeSubstCloner(To, From, ApplySubs, OpenedArchetypesTracker, true), IKind(IKind), CalleeEntryBB(nullptr), Callback(Callback) { } /// inlineFunction - This method inlines a callee function, assuming that it /// is called with the given arguments, into the caller at a given instruction /// (as specified by a basic block iterator), assuming that the instruction /// corresponds semantically to an application of the function. It only /// performs one step of inlining: it does not recursively inline functions /// called by the callee. /// /// Returns true on success or false if it is unable to inline the function /// (for any reason). If successful, I now points to the first inlined /// instruction, or the next instruction after the removed instruction in the /// original function, in case the inlined function is completely trivial bool inlineFunction(FullApplySite AI, ArrayRef Args); private: void visitDebugValueInst(DebugValueInst *Inst); void visitDebugValueAddrInst(DebugValueAddrInst *Inst); const SILDebugScope *getOrCreateInlineScope(const SILDebugScope *DS); void postProcess(SILInstruction *Orig, SILInstruction *Cloned) { // Call client-supplied callback function. if (Callback) Callback(Orig, Cloned); // We just updated the debug scope information. Intentionally // don't call SILClonerWithScopes::postProcess(). SILCloner::postProcess(Orig, Cloned); } SILLocation remapLocation(SILLocation InLoc) { // For performance inlining return the original location. if (IKind == InlineKind::PerformanceInline) return InLoc; // Inlined location wraps the call site that is being inlined, regardless // of the input location. return Loc.hasValue() ? Loc.getValue() : MandatoryInlinedLocation::getMandatoryInlinedLocation((Decl*)nullptr); } const SILDebugScope *remapScope(const SILDebugScope *DS) { if (IKind == InlineKind::MandatoryInline) // Transparent functions are absorbed into the call // site. No soup, err, debugging for you! return CallSiteScope; else // Create an inlined version of the scope. return getOrCreateInlineScope(DS); } InlineKind IKind; SILBasicBlock *CalleeEntryBB; /// \brief The location representing the inlined instructions. /// /// This location wraps the call site AST node that is being inlined. /// Alternatively, it can be the SIL file location of the call site (in case /// of SIL-to-SIL transformations). Optional Loc; const SILDebugScope *CallSiteScope = nullptr; SILFunction *CalleeFunction; llvm::SmallDenseMap InlinedScopeCache; CloneCollector::CallbackType Callback; }; } // end namespace swift #endif