mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
719 lines
23 KiB
C++
719 lines
23 KiB
C++
//===--- SILLocation.h - Location information for SIL nodes -----*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_LOCATION_H
|
|
#define SWIFT_SIL_LOCATION_H
|
|
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/Expr.h"
|
|
#include "swift/AST/Pattern.h"
|
|
#include "swift/AST/Stmt.h"
|
|
|
|
#include <cstddef>
|
|
#include <type_traits>
|
|
|
|
namespace swift {
|
|
|
|
class SourceLoc;
|
|
|
|
/// This is a pointer to the AST node that a SIL instruction was
|
|
/// derived from. This may be null if AST information is unavailable or
|
|
/// stripped.
|
|
///
|
|
/// FIXME: This should eventually include inlining history, generics
|
|
/// instantiation info, etc (when we get to it).
|
|
///
|
|
class SILLocation {
|
|
private:
|
|
template <class T, class Enable = void>
|
|
struct base_type;
|
|
|
|
template <class T>
|
|
struct base_type<T,
|
|
typename std::enable_if<std::is_base_of<Decl, T>::value>::type> {
|
|
using type = Decl;
|
|
};
|
|
|
|
template <class T>
|
|
struct base_type<T,
|
|
typename std::enable_if<std::is_base_of<Expr, T>::value>::type> {
|
|
using type = Expr;
|
|
};
|
|
|
|
template <class T>
|
|
struct base_type<T,
|
|
typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> {
|
|
using type = Stmt;
|
|
};
|
|
|
|
template <class T>
|
|
struct base_type<T,
|
|
typename std::enable_if<std::is_base_of<Pattern, T>::value>::type> {
|
|
using type = Pattern;
|
|
};
|
|
|
|
typedef llvm::PointerUnion4<Stmt*, Expr*, Decl*, Pattern*> ASTNodeTy;
|
|
|
|
public:
|
|
enum LocationKind : unsigned {
|
|
// FIXME: NoneKind is to be removed.
|
|
NoneKind = 0,
|
|
RegularKind = 1,
|
|
ReturnKind = 2,
|
|
ImplicitReturnKind = 3,
|
|
InlinedKind = 4,
|
|
MandatoryInlinedKind = 5,
|
|
CleanupKind = 6,
|
|
ArtificialUnreachableKind = 7
|
|
};
|
|
|
|
enum StorageKind : unsigned {
|
|
UnknownKind = 0,
|
|
ASTNodeKind = 1 << 3,
|
|
SILFileKind = 1 << 4,
|
|
DebugInfoKind = 1 << 3 | 1 << 4
|
|
};
|
|
|
|
struct DebugLoc {
|
|
unsigned Line;
|
|
unsigned Column;
|
|
const char *Filename;
|
|
|
|
DebugLoc(unsigned Line = 0, unsigned Column = 0,
|
|
const char *Filename = nullptr) : Line(Line), Column(Column),
|
|
Filename(Filename) { }
|
|
};
|
|
|
|
protected:
|
|
union UnderlyingLocation {
|
|
UnderlyingLocation() : DebugInfoLoc({}) {}
|
|
UnderlyingLocation(ASTNodeTy N) : ASTNode(N) {}
|
|
UnderlyingLocation(SourceLoc L) : SILFileLoc(L) {}
|
|
UnderlyingLocation(DebugLoc D) : DebugInfoLoc(D) {}
|
|
struct ASTNodeLoc {
|
|
ASTNodeLoc(ASTNodeTy N) : Primary(N) {}
|
|
/// Primary AST location, always used for diagnostics.
|
|
ASTNodeTy Primary;
|
|
/// Sometimes the location for diagnostics needs to be
|
|
/// different than the one used to emit the line table. If
|
|
/// HasDebugLoc is set, this is used for the debug info.
|
|
ASTNodeTy ForDebugger;
|
|
} ASTNode;
|
|
|
|
/// A location inside a textual .sil file.
|
|
SourceLoc SILFileLoc;
|
|
|
|
/// A deserialized source location.
|
|
DebugLoc DebugInfoLoc;
|
|
} Loc;
|
|
|
|
/// The kind of this SIL location.
|
|
unsigned KindData;
|
|
|
|
enum {
|
|
LocationKindBits = 3,
|
|
LocationKindMask = 7,
|
|
|
|
StorageKindBits = 2,
|
|
StorageKindMask = (1 << 3) | (1 << 4),
|
|
SpecialFlagsMask = ~ (LocationKindMask | StorageKindMask),
|
|
|
|
/// Used to mark this instruction as part of auto-generated
|
|
/// code block.
|
|
AutoGeneratedBit = 5,
|
|
|
|
/// Used to redefine the default source location used to
|
|
/// represent this SILLocation. For example, when the host instruction
|
|
/// is known to correspond to the beginning or the end of the source
|
|
/// range of the ASTNode.
|
|
PointsToStartBit = 6,
|
|
PointsToEndBit = 7,
|
|
|
|
/// Used to notify that this instruction belongs to the top-
|
|
/// level (module) scope.
|
|
///
|
|
/// FIXME: If Module becomes a Decl, this could be removed.
|
|
IsInTopLevel = 8,
|
|
|
|
/// Marks this instruction as belonging to the function prologue.
|
|
IsInPrologue = 9
|
|
};
|
|
|
|
template <typename T>
|
|
T *getNodeAs(ASTNodeTy Node) const {
|
|
using base = typename base_type<T>::type*;
|
|
return dyn_cast_or_null<T>(Node.dyn_cast<base>());
|
|
}
|
|
|
|
template <typename T>
|
|
bool isNode(ASTNodeTy Node) const {
|
|
assert(isASTNode());
|
|
if (Loc.ASTNode.Primary.is<typename base_type<T>::type*>())
|
|
return isa<T>(Node.get<typename base_type<T>::type*>());
|
|
return false;
|
|
}
|
|
|
|
template <typename T>
|
|
T *castNodeTo(ASTNodeTy Node) const {
|
|
return cast<T>(Node.get<typename base_type<T>::type*>());
|
|
}
|
|
|
|
/// \defgroup SILLocation constructors.
|
|
/// @{
|
|
|
|
/// This constructor is used to support getAs operation.
|
|
SILLocation() { assert(Loc.DebugInfoLoc.Line == 0); }
|
|
SILLocation(LocationKind K, unsigned Flags = 0) : KindData(K | Flags) {
|
|
assert(Loc.DebugInfoLoc.Line == 0);
|
|
}
|
|
|
|
SILLocation(Stmt *S, LocationKind K, unsigned Flags = 0)
|
|
: Loc(S), KindData(K | Flags) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
|
|
SILLocation(Expr *E, LocationKind K, unsigned Flags = 0)
|
|
: Loc(E), KindData(K | Flags) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
|
|
SILLocation(Decl *D, LocationKind K, unsigned Flags = 0)
|
|
: Loc(D), KindData(K | Flags) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
|
|
SILLocation(Pattern *P, LocationKind K, unsigned Flags = 0)
|
|
: Loc(P), KindData(K | Flags) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
|
|
SILLocation(SourceLoc L, LocationKind K, unsigned Flags = 0)
|
|
: Loc(L), KindData(K | Flags) {
|
|
setStorageKind(SILFileKind);
|
|
assert(isSILFile());
|
|
}
|
|
|
|
SILLocation(DebugLoc L, LocationKind K, unsigned Flags = 0)
|
|
: Loc(L), KindData(K | Flags) {
|
|
setStorageKind(DebugInfoKind);
|
|
assert(isDebugInfoLoc());
|
|
}
|
|
/// @}
|
|
|
|
private:
|
|
friend class ImplicitReturnLocation;
|
|
friend class MandatoryInlinedLocation;
|
|
friend class InlinedLocation;
|
|
friend class CleanupLocation;
|
|
|
|
void setLocationKind(LocationKind K) { KindData |= (K & LocationKindMask); }
|
|
void setStorageKind(StorageKind K) { KindData |= (K & StorageKindMask); }
|
|
unsigned getSpecialFlags() const { return KindData & SpecialFlagsMask; }
|
|
void setSpecialFlags(unsigned Flags) {
|
|
KindData |= (Flags & SpecialFlagsMask);
|
|
}
|
|
|
|
SourceLoc getSourceLoc(ASTNodeTy N) const;
|
|
SourceLoc getStartSourceLoc(ASTNodeTy N) const;
|
|
SourceLoc getEndSourceLoc(ASTNodeTy N) const;
|
|
|
|
public:
|
|
|
|
/// When an ASTNode gets implicitly converted into a SILLocation we
|
|
/// construct a RegularLocation. Since RegularLocations represent the majority
|
|
/// of locations, this greatly simplifies the user code.
|
|
SILLocation(Stmt *S) : Loc(S), KindData(RegularKind) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
SILLocation(Expr *E) : Loc(E), KindData(RegularKind) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
SILLocation(Decl *D) : Loc(D), KindData(RegularKind) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
SILLocation(Pattern *P) : Loc(P), KindData(RegularKind) {
|
|
setStorageKind(ASTNodeKind);
|
|
assert(isASTNode());
|
|
}
|
|
|
|
/// Check if the location wraps an AST node or a valid SIL file
|
|
/// location.
|
|
///
|
|
/// Artificial locations and the top-level module locations will be null.
|
|
bool isNull() const {
|
|
switch (getStorageKind()) {
|
|
case ASTNodeKind: return Loc.ASTNode.Primary.isNull();
|
|
case DebugInfoKind: return Loc.DebugInfoLoc.Filename;
|
|
case SILFileKind: return Loc.SILFileLoc.isInvalid();
|
|
default: return true;
|
|
}
|
|
}
|
|
explicit operator bool() const { return !isNull(); }
|
|
|
|
/// Return whether this location is backed by an AST node.
|
|
bool isASTNode() const { return getStorageKind() == ASTNodeKind; }
|
|
|
|
/// Return whether this location came from a SIL file.
|
|
bool isSILFile() const { return getStorageKind() == SILFileKind; }
|
|
|
|
/// Return whether this location came from a textual SIL file.
|
|
bool isDebugInfoLoc() const { return getStorageKind() == DebugInfoKind; }
|
|
|
|
/// Marks the location as coming from auto-generated body.
|
|
void markAutoGenerated() { KindData |= (1 << AutoGeneratedBit); }
|
|
|
|
/// Returns true if the location represents an artificially generated
|
|
/// body, such as thunks or default destructors.
|
|
///
|
|
/// These locations should not be included in the debug line table.
|
|
/// These might also need special handling by the debugger since they might
|
|
/// contain calls, which the debugger could be able to step into.
|
|
bool isAutoGenerated() const { return KindData & (1 << AutoGeneratedBit); }
|
|
|
|
/// Changes the default source location position to point to start of
|
|
/// the AST node.
|
|
void pointToStart() { KindData |= (1 << PointsToStartBit); }
|
|
|
|
/// Changes the default source location position to point to the end of
|
|
/// the AST node.
|
|
void pointToEnd() { KindData |= (1 << PointsToEndBit); }
|
|
|
|
/// Mark this location as the location corresponding to the top-level
|
|
/// (module-level) code.
|
|
void markAsInTopLevel() { KindData |= (1 << IsInTopLevel); }
|
|
|
|
/// Check is this location is associated with the top level/module.
|
|
bool isInTopLevel() const { return KindData & (1 << IsInTopLevel); }
|
|
|
|
/// Mark this location as being part of the function
|
|
/// prologue, which means that it deals with setting up the stack
|
|
/// frame. The first breakpoint location in a function is at the end
|
|
/// of the prologue.
|
|
void markAsPrologue() { KindData |= (1 << IsInPrologue); }
|
|
|
|
/// Check is this location is part of a function's implicit prologue.
|
|
bool isInPrologue() const { return KindData & (1 << IsInPrologue); }
|
|
|
|
/// Add an ASTNode to use as the location for debugging
|
|
/// purposes if this location is different from the location used
|
|
/// for diagnostics.
|
|
template <typename T>
|
|
void setDebugLoc(T *ASTNodeForDebugging) {
|
|
assert(!hasDebugLoc() && "DebugLoc already present");
|
|
assert(isASTNode() && "not an AST location");
|
|
Loc.ASTNode.ForDebugger = ASTNodeForDebugging;
|
|
}
|
|
bool hasDebugLoc() const {
|
|
return isASTNode() && !Loc.ASTNode.ForDebugger.isNull();
|
|
}
|
|
|
|
/// Populate this empty SILLocation with a DebugLoc.
|
|
void setDebugInfoLoc(DebugLoc L) {
|
|
Loc.DebugInfoLoc = L;
|
|
setStorageKind(DebugInfoKind);
|
|
}
|
|
|
|
/// Check if the corresponding source code location definitely points
|
|
/// to the start of the AST node.
|
|
bool alwaysPointsToStart() const { return KindData & (1 << PointsToStartBit);}
|
|
|
|
/// Check if the corresponding source code location definitely points
|
|
/// to the end of the AST node.
|
|
bool alwaysPointsToEnd() const { return KindData & (1 << PointsToEndBit); }
|
|
|
|
LocationKind getKind() const {
|
|
return LocationKind(KindData & LocationKindMask);
|
|
}
|
|
StorageKind getStorageKind() const {
|
|
return StorageKind(KindData & StorageKindMask);
|
|
}
|
|
|
|
template <typename T>
|
|
bool is() const {
|
|
return T::isKind(*this);
|
|
}
|
|
|
|
template <typename T>
|
|
T castTo() const {
|
|
assert(T::isKind(*this));
|
|
T t;
|
|
SILLocation& tr = t;
|
|
tr = *this;
|
|
return t;
|
|
}
|
|
|
|
template <typename T>
|
|
Optional<T> getAs() const {
|
|
if (!T::isKind(*this))
|
|
return Optional<T>();
|
|
T t;
|
|
SILLocation& tr = t;
|
|
tr = *this;
|
|
return t;
|
|
}
|
|
|
|
/// If the current value is of the specified AST unit type T,
|
|
/// return it, otherwise return null.
|
|
template <typename T> T *getAsASTNode() const {
|
|
return isASTNode() ? getNodeAs<T>(Loc.ASTNode.Primary) : nullptr;
|
|
}
|
|
|
|
/// Returns true if the Location currently points to the AST node
|
|
/// matching type T.
|
|
template <typename T> bool isASTNode() const {
|
|
return isASTNode() && isNode<T>(Loc.ASTNode.Primary);
|
|
}
|
|
|
|
/// Returns the primary value as the specified AST node type. If the
|
|
/// specified type is incorrect, asserts.
|
|
template <typename T> T *castToASTNode() const {
|
|
assert(isASTNode());
|
|
return castNodeTo<T>(Loc.ASTNode.Primary);
|
|
}
|
|
|
|
/// If the DebugLoc is of the specified AST unit type T,
|
|
/// return it, otherwise return null.
|
|
template <typename T> T *getDebugLocAsASTNode() const {
|
|
assert(hasDebugLoc() && "no debug location");
|
|
return getNodeAs<T>(Loc.ASTNode.ForDebugger);
|
|
}
|
|
|
|
SourceLoc getDebugSourceLoc() const;
|
|
SourceLoc getSourceLoc() const;
|
|
SourceLoc getStartSourceLoc() const;
|
|
SourceLoc getEndSourceLoc() const;
|
|
|
|
SourceRange getSourceRange() const {
|
|
return { getStartSourceLoc(), getEndSourceLoc() };
|
|
}
|
|
|
|
/// Fingerprint a DebugLoc for use in a DenseMap.
|
|
typedef std::pair<std::pair<unsigned, unsigned>, const void *> DebugLocKey;
|
|
struct DebugLocHash : public DebugLocKey {
|
|
DebugLocHash(DebugLoc L) : DebugLocKey({{L.Line, L.Column}, L.Filename}) {}
|
|
};
|
|
|
|
/// Extract the line, column, and filename.
|
|
static DebugLoc decode(SourceLoc Loc, const SourceManager &SM);
|
|
|
|
/// Return the decoded debug location.
|
|
DebugLoc decodeDebugLoc(const SourceManager &SM) const {
|
|
return isDebugInfoLoc() ? Loc.DebugInfoLoc
|
|
: decode(getDebugSourceLoc(), SM);
|
|
}
|
|
|
|
/// Pretty-print the value.
|
|
void dump(const SourceManager &SM) const;
|
|
void print(raw_ostream &OS, const SourceManager &SM) const;
|
|
|
|
/// Returns an opaque pointer value for the debug location that may
|
|
/// be used to unique debug locations.
|
|
const void *getOpaquePointerValue() const {
|
|
if (isSILFile())
|
|
return Loc.SILFileLoc.getOpaquePointerValue();
|
|
if (isASTNode())
|
|
return Loc.ASTNode.Primary.getOpaqueValue();
|
|
else
|
|
return 0;
|
|
}
|
|
unsigned getOpaqueKind() const { return KindData; }
|
|
|
|
inline bool operator==(const SILLocation& R) const {
|
|
return KindData == R.KindData &&
|
|
Loc.ASTNode.Primary.getOpaqueValue() ==
|
|
R.Loc.ASTNode.Primary.getOpaqueValue() &&
|
|
Loc.ASTNode.ForDebugger.getOpaqueValue() ==
|
|
R.Loc.ASTNode.ForDebugger.getOpaqueValue();
|
|
}
|
|
};
|
|
|
|
/// Allowed on any instruction.
|
|
class RegularLocation : public SILLocation {
|
|
public:
|
|
RegularLocation(Stmt *S) : SILLocation(S, RegularKind) {}
|
|
RegularLocation(Expr *E) : SILLocation(E, RegularKind) {}
|
|
RegularLocation(Decl *D) : SILLocation(D, RegularKind) {}
|
|
RegularLocation(Pattern *P) : SILLocation(P, RegularKind) {}
|
|
RegularLocation(SourceLoc L) : SILLocation(L, RegularKind) {}
|
|
RegularLocation(DebugLoc L) : SILLocation(L, RegularKind) {}
|
|
|
|
/// Returns a location representing the module.
|
|
static RegularLocation getModuleLocation() {
|
|
RegularLocation Loc;
|
|
Loc.markAsInTopLevel();
|
|
return Loc;
|
|
}
|
|
|
|
/// If the current value is of the specified AST unit type T,
|
|
/// return it, otherwise return null.
|
|
template <typename T> T *getAs() const { return getNodeAs<T>(Loc.ASTNode); }
|
|
|
|
/// Returns true if the Location currently points to the AST node
|
|
/// matching type T.
|
|
template <typename T> bool is() const { return isNode<T>(Loc.ASTNode); }
|
|
|
|
/// Returns the primary value as the specified AST node type. If the
|
|
/// specified type is incorrect, asserts.
|
|
template <typename T> T *castTo() const { return castNodeTo<T>(Loc.ASTNode); }
|
|
|
|
static RegularLocation getAutoGeneratedLocation() {
|
|
RegularLocation AL;
|
|
AL.markAutoGenerated();
|
|
return AL;
|
|
}
|
|
|
|
private:
|
|
RegularLocation() : SILLocation(RegularKind) {}
|
|
|
|
friend class SILLocation;
|
|
static bool isKind(const SILLocation& L) {
|
|
return L.getKind() == RegularKind;
|
|
}
|
|
};
|
|
|
|
/// Used to represent a return instruction in user code.
|
|
///
|
|
/// Allowed on an BranchInst, ReturnInst.
|
|
class ReturnLocation : public SILLocation {
|
|
public:
|
|
ReturnLocation(ReturnStmt *RS) : SILLocation(RS, ReturnKind) {}
|
|
|
|
/// Construct the return location for a constructor or a destructor.
|
|
ReturnLocation(BraceStmt *BS)
|
|
: SILLocation(BS, ReturnKind) {}
|
|
|
|
ReturnStmt *get() {
|
|
return castToASTNode<ReturnStmt>();
|
|
}
|
|
private:
|
|
friend class SILLocation;
|
|
static bool isKind(const SILLocation& L) {
|
|
return L.getKind() == ReturnKind;
|
|
}
|
|
};
|
|
|
|
/// Used on the instruction that was generated to represent an implicit
|
|
/// return from a function.
|
|
///
|
|
/// Allowed on an BranchInst, ReturnInst.
|
|
class ImplicitReturnLocation : public SILLocation {
|
|
public:
|
|
|
|
ImplicitReturnLocation(AbstractClosureExpr *E)
|
|
: SILLocation(E, ImplicitReturnKind) { }
|
|
|
|
ImplicitReturnLocation(ReturnStmt *S)
|
|
: SILLocation(S, ImplicitReturnKind) { }
|
|
|
|
ImplicitReturnLocation(AbstractFunctionDecl *AFD)
|
|
: SILLocation(AFD, ImplicitReturnKind) { }
|
|
|
|
/// Construct from a RegularLocation; preserve all special bits.
|
|
///
|
|
/// Note, this can construct an implicit return for an arbitrary expression
|
|
/// (specifically, in case of auto-generated bodies).
|
|
static SILLocation getImplicitReturnLoc(SILLocation L) {
|
|
assert(L.isASTNode<Expr>() ||
|
|
L.isASTNode<ValueDecl>() ||
|
|
L.isASTNode<PatternBindingDecl>() ||
|
|
(L.isNull() && L.isInTopLevel()));
|
|
L.setLocationKind(ImplicitReturnKind);
|
|
return L;
|
|
}
|
|
|
|
AbstractClosureExpr *get() {
|
|
return castToASTNode<AbstractClosureExpr>();
|
|
}
|
|
|
|
private:
|
|
friend class SILLocation;
|
|
static bool isKind(const SILLocation& L) {
|
|
return L.getKind() == ImplicitReturnKind;
|
|
}
|
|
ImplicitReturnLocation() : SILLocation(ImplicitReturnKind) {}
|
|
};
|
|
|
|
/// Marks instructions that correspond to inlined function body and
|
|
/// setup code. This location should not be used for inlined transparent
|
|
/// bodies, see MandatoryInlinedLocation.
|
|
///
|
|
/// This location wraps the call site ASTNode.
|
|
///
|
|
/// Allowed on any instruction except for ReturnInst.
|
|
class InlinedLocation : public SILLocation {
|
|
public:
|
|
InlinedLocation(Expr *CallSite) : SILLocation(CallSite, InlinedKind) {}
|
|
InlinedLocation(Stmt *S) : SILLocation(S, InlinedKind) {}
|
|
InlinedLocation(Pattern *P) : SILLocation(P, InlinedKind) {}
|
|
InlinedLocation(Decl *D) : SILLocation(D, InlinedKind) {}
|
|
|
|
/// Constructs an inlined location when the call site is represented by a
|
|
/// SILFile location.
|
|
InlinedLocation(SourceLoc L) : SILLocation(InlinedKind) {
|
|
setStorageKind(SILFileKind);
|
|
Loc.SILFileLoc = L;
|
|
}
|
|
|
|
static InlinedLocation getInlinedLocation(SILLocation L);
|
|
|
|
private:
|
|
friend class SILLocation;
|
|
static bool isKind(const SILLocation& L) {
|
|
return L.getKind() == InlinedKind;
|
|
}
|
|
InlinedLocation() : SILLocation(InlinedKind) {}
|
|
|
|
InlinedLocation(Expr *E, unsigned F) : SILLocation(E, InlinedKind, F) {}
|
|
InlinedLocation(Stmt *S, unsigned F) : SILLocation(S, InlinedKind, F) {}
|
|
InlinedLocation(Pattern *P, unsigned F) : SILLocation(P, InlinedKind, F) {}
|
|
InlinedLocation(Decl *D, unsigned F) : SILLocation(D, InlinedKind, F) {}
|
|
InlinedLocation(SourceLoc L, unsigned F) : SILLocation(L, InlinedKind, F) {}
|
|
|
|
static InlinedLocation getModuleLocation(unsigned Flags) {
|
|
auto L = InlinedLocation();
|
|
L.setSpecialFlags(Flags);
|
|
return L;
|
|
}
|
|
|
|
};
|
|
|
|
/// Marks instructions that correspond to inlined function body and
|
|
/// setup code for transparent functions, inlined as part of mandatory inlining
|
|
/// pass.
|
|
///
|
|
/// This location wraps the call site ASTNode.
|
|
///
|
|
/// Allowed on any instruction except for ReturnInst.
|
|
class MandatoryInlinedLocation : public SILLocation {
|
|
public:
|
|
MandatoryInlinedLocation(Expr *CallSite) :
|
|
SILLocation(CallSite, MandatoryInlinedKind) {}
|
|
MandatoryInlinedLocation(Stmt *S) : SILLocation(S, MandatoryInlinedKind) {}
|
|
MandatoryInlinedLocation(Pattern *P) : SILLocation(P, MandatoryInlinedKind) {}
|
|
MandatoryInlinedLocation(Decl *D) : SILLocation(D, MandatoryInlinedKind) {}
|
|
|
|
/// Constructs an inlined location when the call site is represented by a
|
|
/// SILFile location.
|
|
MandatoryInlinedLocation(SourceLoc L)
|
|
: SILLocation(L, MandatoryInlinedKind) {}
|
|
|
|
static MandatoryInlinedLocation getMandatoryInlinedLocation(SILLocation L);
|
|
|
|
static MandatoryInlinedLocation getModuleLocation(unsigned Flags) {
|
|
auto L = MandatoryInlinedLocation();
|
|
L.setSpecialFlags(Flags);
|
|
return L;
|
|
}
|
|
|
|
private:
|
|
friend class SILLocation;
|
|
static bool isKind(const SILLocation& L) {
|
|
return L.getKind() == MandatoryInlinedKind;
|
|
}
|
|
MandatoryInlinedLocation() : SILLocation(MandatoryInlinedKind) {}
|
|
MandatoryInlinedLocation(Expr *E, unsigned F)
|
|
: SILLocation(E, MandatoryInlinedKind, F) {}
|
|
MandatoryInlinedLocation(Stmt *S, unsigned F)
|
|
: SILLocation(S, MandatoryInlinedKind, F) {}
|
|
MandatoryInlinedLocation(Pattern *P, unsigned F)
|
|
: SILLocation(P, MandatoryInlinedKind, F) {}
|
|
MandatoryInlinedLocation(Decl *D, unsigned F)
|
|
: SILLocation(D, MandatoryInlinedKind, F) {}
|
|
MandatoryInlinedLocation(SourceLoc L, unsigned F)
|
|
: SILLocation(L, MandatoryInlinedKind, F) {}
|
|
};
|
|
|
|
/// Used on the instruction performing auto-generated cleanup such as
|
|
/// deallocs, destructor calls.
|
|
///
|
|
/// The cleanups are performed after completing the evaluation of the AST Node
|
|
/// wrapped inside the SILLocation. This location wraps the statement
|
|
/// representing the enclosing scope, for example, FuncDecl, ParenExpr. The
|
|
/// scope's end location points to the SourceLoc that shows when the operation
|
|
/// is performed at runtime.
|
|
///
|
|
/// Allowed on any instruction except for ReturnInst.
|
|
/// Locations of an inlined destructor should also be represented by this.
|
|
class CleanupLocation : public SILLocation {
|
|
public:
|
|
CleanupLocation(Expr *E) : SILLocation(E, CleanupKind) {}
|
|
CleanupLocation(Stmt *S) : SILLocation(S, CleanupKind) {}
|
|
CleanupLocation(Pattern *P) : SILLocation(P, CleanupKind) {}
|
|
CleanupLocation(Decl *D) : SILLocation(D, CleanupKind) {}
|
|
|
|
static CleanupLocation get(SILLocation L);
|
|
|
|
/// Returns a location representing a cleanup on the module level.
|
|
static CleanupLocation getModuleCleanupLocation() {
|
|
CleanupLocation Loc;
|
|
Loc.markAsInTopLevel();
|
|
return Loc;
|
|
}
|
|
|
|
private:
|
|
friend class SILLocation;
|
|
static bool isKind(const SILLocation& L) {
|
|
return L.getKind() == CleanupKind;
|
|
}
|
|
CleanupLocation() : SILLocation(CleanupKind) {}
|
|
|
|
CleanupLocation(Expr *E, unsigned F) : SILLocation(E, CleanupKind, F) {}
|
|
CleanupLocation(Stmt *S, unsigned F) : SILLocation(S, CleanupKind, F) {}
|
|
CleanupLocation(Pattern *P, unsigned F) : SILLocation(P, CleanupKind, F) {}
|
|
CleanupLocation(Decl *D, unsigned F) : SILLocation(D, CleanupKind, F) {}
|
|
};
|
|
|
|
/// Used to represent an unreachable location that was
|
|
/// auto-generated and has no correspondence to user code. It should
|
|
/// not be used in diagnostics or for debugging.
|
|
///
|
|
/// Differentiates an unreachable instruction, which is generated by
|
|
/// DCE, from an unreachable instruction in user code (output of SILGen).
|
|
/// Allowed on an unreachable instruction.
|
|
class ArtificialUnreachableLocation : public SILLocation {
|
|
public:
|
|
ArtificialUnreachableLocation() : SILLocation(ArtificialUnreachableKind) {}
|
|
private:
|
|
friend class SILLocation;
|
|
static bool isKind(const SILLocation& L) {
|
|
return (L.getKind() == ArtificialUnreachableKind);
|
|
}
|
|
};
|
|
|
|
class SILDebugScope;
|
|
|
|
/// A SILLocation paired with a SILDebugScope.
|
|
class SILDebugLocation {
|
|
const SILDebugScope *Scope = nullptr;
|
|
SILLocation Location;
|
|
|
|
public:
|
|
SILDebugLocation() : Scope(nullptr), Location(RegularLocation(SourceLoc())) {}
|
|
SILDebugLocation(SILLocation Loc, const SILDebugScope *DS)
|
|
: Scope(DS), Location(Loc) {}
|
|
SILLocation getLocation() const { return Location; }
|
|
const SILDebugScope *getScope() const { return Scope; }
|
|
};
|
|
|
|
} // end swift namespace
|
|
|
|
|
|
#endif
|