blob: a1cbe59cc17ca97aa7aa15482c8a266f4487983c [file] [log] [blame]
//===--- 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 <functional>
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<SILInliner> {
public:
friend class SILVisitor<SILInliner>;
friend class SILCloner<SILInliner>;
enum class InlineKind {
MandatoryInline,
PerformanceInline
};
SILInliner(SILFunction &To, SILFunction &From, InlineKind IKind,
SubstitutionList ApplySubs,
SILOpenedArchetypesTracker &OpenedArchetypesTracker,
CloneCollector::CallbackType Callback = nullptr)
: TypeSubstCloner<SILInliner>(To, From, ApplySubs,
OpenedArchetypesTracker, true),
IKind(IKind), CalleeEntryBB(nullptr), CallSiteScope(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<SILValue> 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<SILInliner>::postProcess().
SILCloner<SILInliner>::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<SILLocation> Loc;
const SILDebugScope *CallSiteScope;
SILFunction *CalleeFunction;
llvm::SmallDenseMap<const SILDebugScope *,
const SILDebugScope *> InlinedScopeCache;
CloneCollector::CallbackType Callback;
};
} // end namespace swift
#endif