mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Enable SIL parsing and SIL serialization of semantics. We add one more field to SILFunctionLayout for semantics. We should refactor handling of attributes at SIL level, right now they are in SILFunction as bool or std::string and in SIL serializer as a 1-bit field or an ID field. rdar://17525564 Swift SVN r19434
343 lines
12 KiB
C++
343 lines
12 KiB
C++
//===--- SILFunction.h - Defines the SILFunction class ----------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the SILFunction class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_SILFUNCTION_H
|
|
#define SWIFT_SIL_SILFUNCTION_H
|
|
|
|
#include "swift/SIL/SILBasicBlock.h"
|
|
#include "swift/SIL/SILLinkage.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
|
|
/// The symbol name used for the program entry point function.
|
|
/// FIXME: Hardcoding this is lame.
|
|
#define SWIFT_ENTRY_POINT_FUNCTION "top_level_code"
|
|
|
|
namespace swift {
|
|
|
|
class ASTContext;
|
|
class SILInstruction;
|
|
class SILModule;
|
|
|
|
enum IsBare_t { IsNotBare, IsBare };
|
|
enum IsTransparent_t { IsNotTransparent, IsTransparent };
|
|
|
|
/// SILFunction - A function body that has been lowered to SIL. This consists of
|
|
/// zero or more SIL SILBasicBlock objects that contain the SILInstruction
|
|
/// objects making up the function.
|
|
class SILFunction
|
|
: public llvm::ilist_node<SILFunction>, public SILAllocated<SILFunction> {
|
|
public:
|
|
typedef llvm::iplist<SILBasicBlock> BlockListType;
|
|
|
|
private:
|
|
friend class SILBasicBlock;
|
|
friend class SILModule;
|
|
|
|
/// Module - The SIL module that the function belongs to.
|
|
SILModule &Module;
|
|
|
|
/// The mangled name of the SIL function, which will be propagated
|
|
/// to the binary. A pointer into the module's lookup table.
|
|
StringRef Name;
|
|
|
|
/// The lowered type of the function.
|
|
CanSILFunctionType LoweredType;
|
|
|
|
/// The context archetypes of the function.
|
|
GenericParamList *ContextGenericParams;
|
|
|
|
/// The collection of all BasicBlocks in the SILFunction. Empty for external
|
|
/// function references.
|
|
BlockListType BlockList;
|
|
|
|
/// The SIL location of the function, which provides a link back to the AST.
|
|
/// The function only gets a location after it's been emitted.
|
|
Optional<SILLocation> Location;
|
|
|
|
/// The declcontext of this function.
|
|
DeclContext *DeclCtx;
|
|
|
|
/// The source location and scope of the function.
|
|
SILDebugScope *DebugScope;
|
|
|
|
/// The function's bare attribute. Bare means that the function is SIL-only.
|
|
unsigned Bare : 1;
|
|
|
|
/// The function's transparent attribute.
|
|
unsigned Transparent : 1; // FIXME: pack this somewhere
|
|
|
|
/// The function's global_init attribute.
|
|
unsigned GlobalInitFlag : 1;
|
|
|
|
/// The function's noinline attribute.
|
|
unsigned NoinlineFlag : 1;
|
|
|
|
/// The linkage of the function.
|
|
unsigned Linkage : NumSILLinkageBits;
|
|
|
|
/// This is the number of uses of this SILFunction.
|
|
unsigned RefCount = 0;
|
|
|
|
/// The function's semantics attribute.
|
|
std::string SemanticsAttr;
|
|
|
|
SILFunction(SILModule &module, SILLinkage linkage,
|
|
StringRef mangledName, CanSILFunctionType loweredType,
|
|
GenericParamList *contextGenericParams,
|
|
Optional<SILLocation> loc,
|
|
IsBare_t isBareSILFunction,
|
|
IsTransparent_t isTrans,
|
|
bool isNoinline,
|
|
SILFunction *insertBefore,
|
|
SILDebugScope *debugScope,
|
|
DeclContext *DC);
|
|
|
|
public:
|
|
static SILFunction *create(SILModule &M, SILLinkage linkage, StringRef name,
|
|
CanSILFunctionType loweredType,
|
|
GenericParamList *contextGenericParams,
|
|
Optional<SILLocation> loc = Nothing,
|
|
IsBare_t isBareSILFunction = IsNotBare,
|
|
IsTransparent_t isTrans = IsNotTransparent,
|
|
bool isNoinline = false,
|
|
SILFunction *InsertBefore = nullptr,
|
|
SILDebugScope *DebugScope = nullptr,
|
|
DeclContext *DC = nullptr);
|
|
~SILFunction();
|
|
|
|
SILModule &getModule() const { return Module; }
|
|
|
|
SILType getLoweredType() const {
|
|
return SILType::getPrimitiveObjectType(LoweredType);
|
|
}
|
|
CanSILFunctionType getLoweredFunctionType() const {
|
|
return LoweredType;
|
|
}
|
|
|
|
/// Return the number of entities referring to this function (other
|
|
/// than the SILModule).
|
|
unsigned getRefCount() const { return RefCount; }
|
|
|
|
/// Increase the reference count.
|
|
void incrementRefCount() { RefCount++; }
|
|
void decrementRefCount() { RefCount--; }
|
|
|
|
/// Drops all uses belonging to instructions in this function. The only valid
|
|
/// operation performable on this object after this is called is called the
|
|
/// destructor or deallocation.
|
|
void dropAllReferences() {
|
|
for (SILBasicBlock &BB : *this)
|
|
BB.dropAllReferences();
|
|
}
|
|
|
|
/// Returns the calling convention used by this entry point.
|
|
AbstractCC getAbstractCC() const {
|
|
return getLoweredFunctionType()->getAbstractCC();
|
|
}
|
|
|
|
StringRef getName() const { return Name; }
|
|
|
|
/// True if this is a declaration of a function defined in another module.
|
|
bool isExternalDeclaration() const { return BlockList.empty(); }
|
|
bool isDefinition() const { return !isExternalDeclaration(); }
|
|
|
|
/// Get this function's linkage attribute.
|
|
SILLinkage getLinkage() const { return SILLinkage(Linkage); }
|
|
void setLinkage(SILLinkage linkage) { Linkage = unsigned(linkage); }
|
|
|
|
/// Helper method which returns true if this function has "external" linkage.
|
|
bool isAvailableExternally() const {
|
|
return swift::isAvailableExternally(getLinkage());
|
|
}
|
|
|
|
/// Get the DeclContext of this function. (Debug info only).
|
|
DeclContext *getDeclContext() const { return DeclCtx; }
|
|
void setDeclContext(Decl *D);
|
|
void setDeclContext(Expr *E);
|
|
|
|
/// Initialize the source location of the function.
|
|
void setLocation(SILLocation L) { Location = L; }
|
|
|
|
/// Check if the function has a location.
|
|
/// FIXME: All functions should have locations, so this method should not be
|
|
/// necessary.
|
|
bool hasLocation() const {
|
|
return Location.hasValue();
|
|
}
|
|
|
|
/// Get the source location of the function.
|
|
SILLocation getLocation() const {
|
|
assert(Location.hasValue());
|
|
return Location.getValue();
|
|
}
|
|
|
|
/// Initialize the debug scope of the function.
|
|
void setDebugScope(SILDebugScope *DS) { DebugScope = DS; }
|
|
|
|
/// Get the source location of the function.
|
|
SILDebugScope *getDebugScope() const { return DebugScope; }
|
|
|
|
/// Get this function's bare attribute.
|
|
IsBare_t isBare() const { return IsBare_t(Bare); }
|
|
void setBare(IsBare_t isB) { Bare = isB; }
|
|
|
|
/// Get this function's transparent attribute.
|
|
IsTransparent_t isTransparent() const { return IsTransparent_t(Transparent); }
|
|
void setTransparent(IsTransparent_t isT) { Transparent = isT; }
|
|
|
|
/// Get this function's noinline attribute.
|
|
bool isNoinline() const { return NoinlineFlag; }
|
|
void setNoinline(bool isNI) { NoinlineFlag = isNI; }
|
|
|
|
/// Get this function's global_init attribute.
|
|
///
|
|
/// The implied semantics are:
|
|
/// - side-effects can occur any time before the first invocation.
|
|
/// - all calls to the same global_init function have the same side-effects.
|
|
/// - any operation that may observe the initializer's side-effects must be
|
|
/// preceded by a call to the initializer.
|
|
///
|
|
/// This is currently true if the function is an addressor that was lazily
|
|
/// generated from a global variable access. Note that the initialization
|
|
/// function itself does not need this attribute. It is private and only
|
|
/// called within the addressor.
|
|
bool isGlobalInit() const { return GlobalInitFlag; }
|
|
void setGlobalInit(bool isGI) { GlobalInitFlag = isGI; }
|
|
|
|
StringRef getSemanticsAttr() const { return SemanticsAttr; }
|
|
void setSemanticsAttr(StringRef attr) { SemanticsAttr = attr; }
|
|
|
|
/// Retrieve the generic parameter list containing the contextual archetypes
|
|
/// of the function.
|
|
///
|
|
/// FIXME: We should remove this in favor of lazy archetype instantiation
|
|
/// using the 'getArchetype' and 'mapTypeIntoContext' interfaces.
|
|
GenericParamList *getContextGenericParams() const {
|
|
return ContextGenericParams;
|
|
}
|
|
void setContextGenericParams(GenericParamList *params) {
|
|
ContextGenericParams = params;
|
|
}
|
|
|
|
/// Map the given type, which is based on an interface SILFunctionType and may
|
|
/// therefore be dependent, to a type based on the context archetypes of this
|
|
/// SILFunction.
|
|
Type mapTypeIntoContext(Type type) const;
|
|
|
|
/// Map the given type, which is based on an interface SILFunctionType and may
|
|
/// therefore be dependent, to a type based on the context archetypes of this
|
|
/// SILFunction.
|
|
SILType mapTypeIntoContext(SILType type) const {
|
|
return SILType::getPrimitiveType(
|
|
mapTypeIntoContext(type.getSwiftRValueType())->getCanonicalType(),
|
|
type.getCategory());
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Block List Access
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
BlockListType &getBlocks() { return BlockList; }
|
|
const BlockListType &getBlocks() const { return BlockList; }
|
|
|
|
typedef BlockListType::iterator iterator;
|
|
typedef BlockListType::const_iterator const_iterator;
|
|
|
|
bool empty() const { return BlockList.empty(); }
|
|
iterator begin() { return BlockList.begin(); }
|
|
iterator end() { return BlockList.end(); }
|
|
const_iterator begin() const { return BlockList.begin(); }
|
|
const_iterator end() const { return BlockList.end(); }
|
|
unsigned size() const { return BlockList.size(); }
|
|
|
|
SILBasicBlock &front() { return *begin(); }
|
|
const SILBasicBlock &front() const { return *begin(); }
|
|
|
|
SILBasicBlock *createBasicBlock();
|
|
//===--------------------------------------------------------------------===//
|
|
// Miscellaneous
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// verify - Run the IR verifier to make sure that the SILFunction follows
|
|
/// invariants.
|
|
void verify() const;
|
|
|
|
/// Pretty-print the SILFunction.
|
|
void dump(bool Verbose) const;
|
|
void dump() const;
|
|
|
|
/// Pretty-print the SILFunction with the designated stream as a 'sil'
|
|
/// definition.
|
|
///
|
|
/// \param Verbose In verbose mode, print the SIL locations.
|
|
void print(raw_ostream &OS, bool Verbose = false) const;
|
|
|
|
/// Pretty-print the SILFunction's name using SIL syntax,
|
|
/// '@function_mangled_name'.
|
|
void printName(raw_ostream &OS) const;
|
|
|
|
ASTContext &getASTContext() const;
|
|
|
|
/// This function is meant for use from the debugger. You can just say 'call
|
|
/// F->viewCFG()' and a ghostview window should pop up from the program,
|
|
/// displaying the CFG of the current function with the code for each basic
|
|
/// block inside. This depends on there being a 'dot' and 'gv' program in
|
|
/// your path.
|
|
void viewCFG() const;
|
|
|
|
};
|
|
|
|
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
|
|
const SILFunction &F) {
|
|
F.print(OS);
|
|
return OS;
|
|
}
|
|
|
|
} // end swift namespace
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ilist_traits for SILFunction
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace llvm {
|
|
|
|
template <>
|
|
struct ilist_traits<::swift::SILFunction> :
|
|
public ilist_default_traits<::swift::SILFunction> {
|
|
typedef ::swift::SILFunction SILFunction;
|
|
|
|
private:
|
|
mutable ilist_half_node<SILFunction> Sentinel;
|
|
|
|
public:
|
|
SILFunction *createSentinel() const {
|
|
return static_cast<SILFunction*>(&Sentinel);
|
|
}
|
|
void destroySentinel(SILFunction *) const {}
|
|
|
|
SILFunction *provideInitialHead() const { return createSentinel(); }
|
|
SILFunction *ensureHead(SILFunction*) const { return createSentinel(); }
|
|
static void noteHead(SILFunction*, SILFunction*) {}
|
|
static void deleteNode(SILFunction *V) { V->~SILFunction(); }
|
|
|
|
private:
|
|
void createNode(const SILFunction &);
|
|
};
|
|
|
|
} // end llvm namespace
|
|
|
|
#endif
|