[sil-module] Create SILFunctionBuilder and hide creation/erasing functions on SILModule.

This commit does not modify those APIs or their usage. It just:

1. Moves the APIs onto SILFunctionBuilder and makes SILFunctionBuilder a friend
   of SILModule.
2. Hides the APIs on SILModule so all users need to use SILFunctionBuilder to
   create/destroy functions.

I am doing this in order to allow for adding/removing function notifications to
be enforced via the type system in the SILOptimizer. In the process of finishing
off CallerAnalysis for FSO, I discovered that we were not doing this everywhere
we need to. After considering various other options such as:

1. Verifying after all passes that the notifications were sent correctly and
   asserting. Turned out to be expensive.
2. Putting a callback in SILModule. This would add an unnecessary virtual call.

I realized that by using a builder we can:

1. Enforce that users of SILFunctionBuilder can only construct composed function
   builders by making the composed function builder's friends of
   SILFunctionBuilder (notice I did not use the word subclass, I am talking
   about a pure composition).
2. Refactor a huge amount of code in SILOpt/SILGen that involve function
   creation onto a SILGenFunctionBuilder/SILOptFunctionBuilder struct. Many of
   the SILFunction creation code in question are straight up copies of each
   other with small variations. A builder would be a great way to simplify that
   code.
3. Reduce the size of SILModule.cpp by 25% from ~30k -> ~23k making the whole
   file easier to read.

NOTE: In this commit, I do not hide the constructor of SILFunctionBuilder since
I have not created the derived builder structs yet. Once I have created those in
a subsequent commit, I will hide that constructor.

rdar://42301529
This commit is contained in:
Michael Gottesman
2018-07-27 12:55:56 -07:00
parent 14f7799f16
commit 11b24415c1
27 changed files with 449 additions and 347 deletions

View File

@@ -65,6 +65,7 @@ class ModuleDecl;
class SILUndef;
class SourceFile;
class SerializedSILLoader;
class SILFunctionBuilder;
namespace Lowering {
class SILGenModule;
@@ -103,6 +104,8 @@ enum class SILStage {
/// \brief A SIL module. The SIL module owns all of the SILFunctions generated
/// when a Swift compilation context is lowered to SIL.
class SILModule {
friend class SILFunctionBuilder;
public:
using FunctionListType = llvm::ilist<SILFunction>;
using GlobalListType = llvm::ilist<SILGlobalVariable>;
@@ -531,51 +534,6 @@ public:
/// the same AST module.
void linkAllFromCurrentModule();
/// \brief Return the declaration of a utility function that can,
/// but needn't, be shared between modules.
SILFunction *getOrCreateSharedFunction(SILLocation loc, StringRef name,
CanSILFunctionType type,
IsBare_t isBareSILFunction,
IsTransparent_t isTransparent,
IsSerialized_t isSerialized,
ProfileCounter entryCount,
IsThunk_t isThunk);
/// \brief Return the declaration of a function, or create it if it doesn't
/// exist.
SILFunction *getOrCreateFunction(
SILLocation loc, StringRef name, SILLinkage linkage,
CanSILFunctionType type, IsBare_t isBareSILFunction,
IsTransparent_t isTransparent, IsSerialized_t isSerialized,
ProfileCounter entryCount = ProfileCounter(),
IsThunk_t isThunk = IsNotThunk,
SubclassScope subclassScope = SubclassScope::NotApplicable);
/// \brief Return the declaration of a function, or create it if it doesn't
/// exist.
SILFunction *
getOrCreateFunction(SILLocation loc, SILDeclRef constant,
ForDefinition_t forDefinition,
ProfileCounter entryCount = ProfileCounter());
/// \brief Create a function declaration.
///
/// This signature is a direct copy of the signature of SILFunction::create()
/// in order to simplify refactoring all SILFunction creation use-sites to use
/// SILModule. Eventually the uses should probably be refactored.
SILFunction *
createFunction(SILLinkage linkage, StringRef name,
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
IsTransparent_t isTrans, IsSerialized_t isSerialized,
ProfileCounter entryCount = ProfileCounter(),
IsThunk_t isThunk = IsNotThunk,
SubclassScope subclassScope = SubclassScope::NotApplicable,
Inline_t inlineStrategy = InlineDefault,
EffectsKind EK = EffectsKind::Unspecified,
SILFunction *InsertBefore = nullptr,
const SILDebugScope *DebugScope = nullptr);
/// Look up the SILWitnessTable representing the lowering of a protocol
/// conformance, and collect the substitutions to apply to the referenced
/// witnesses, if any.