mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
LLVM has removed `make*ArrayRef`, migrate all references to their constructor equivalent.
164 lines
5.5 KiB
C++
164 lines
5.5 KiB
C++
//===--- SILLayout.h - Defines SIL-level aggregate layouts ------*- 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 classes that describe the physical layout of nominal
|
|
// types in SIL, including structs, classes, and boxes. This is distinct from
|
|
// the AST-level layout for several reasons:
|
|
// - It avoids redundant work lowering the layout of aggregates from the AST.
|
|
// - It allows optimizations to manipulate the layout of aggregates without
|
|
// requiring changes to the AST. For instance, optimizations can eliminate
|
|
// dead fields from instances or turn invariant fields into global variables.
|
|
// - It allows for SIL-only aggregates to exist, such as boxes.
|
|
// - It improves the robustness of code in the face of resilience. A resilient
|
|
// type can be modeled in SIL as not having a layout at all, preventing the
|
|
// inappropriate use of fragile projection and injection operations on the
|
|
// type.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_LAYOUT_H
|
|
#define SWIFT_SIL_LAYOUT_H
|
|
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
#include "swift/AST/GenericSignature.h"
|
|
#include "swift/AST/Identifier.h"
|
|
#include "swift/AST/Type.h"
|
|
|
|
namespace swift {
|
|
|
|
class SILType;
|
|
|
|
/// A field of a SIL aggregate layout.
|
|
class SILField final {
|
|
enum : unsigned {
|
|
IsMutable = 0x1,
|
|
};
|
|
|
|
static constexpr const unsigned NumFlags = 1;
|
|
|
|
llvm::PointerIntPair<CanType, NumFlags, unsigned> LoweredTypeAndFlags;
|
|
|
|
static unsigned getFlagsValue(bool Mutable) {
|
|
unsigned flags = 0;
|
|
if (Mutable) flags |= IsMutable;
|
|
|
|
assert(flags >> NumFlags == 0
|
|
&& "more flags than flag bits?!");
|
|
return flags;
|
|
}
|
|
|
|
public:
|
|
SILField(CanType LoweredType, bool Mutable)
|
|
: LoweredTypeAndFlags(LoweredType, getFlagsValue(Mutable))
|
|
{}
|
|
|
|
/// Get the lowered type of the field in the aggregate.
|
|
///
|
|
/// This must be a lowered SIL type. If the containing aggregate is generic,
|
|
/// then this type specifies the abstraction pattern at which values stored
|
|
/// in this aggregate should be lowered.
|
|
CanType getLoweredType() const { return LoweredTypeAndFlags.getPointer(); }
|
|
|
|
SILType getAddressType() const; // In SILType.h
|
|
SILType getObjectType() const; // In SILType.h
|
|
|
|
/// True if this field is mutable inside its aggregate.
|
|
///
|
|
/// This is only effectively a constraint on shared mutable reference types,
|
|
/// such as classes and boxes. A value type or uniquely-owned immutable
|
|
/// reference can always be mutated, since doing so is equivalent to
|
|
/// destroying the old value and emplacing a new value with the modified
|
|
/// field in the same place.
|
|
bool isMutable() const { return LoweredTypeAndFlags.getInt() & IsMutable; }
|
|
};
|
|
|
|
/// A layout.
|
|
class SILLayout final : public llvm::FoldingSetNode,
|
|
private llvm::TrailingObjects<SILLayout, SILField>
|
|
{
|
|
friend TrailingObjects;
|
|
|
|
enum : unsigned {
|
|
IsMutable = 0x1,
|
|
CapturesGenericEnvironment = 0x2,
|
|
};
|
|
|
|
static constexpr const unsigned NumFlags = 2;
|
|
|
|
static unsigned getFlagsValue(bool Mutable, bool CapturesGenerics) {
|
|
unsigned flags = 0;
|
|
if (Mutable)
|
|
flags |= IsMutable;
|
|
if (CapturesGenerics)
|
|
flags |= CapturesGenericEnvironment;
|
|
|
|
assert(flags >> NumFlags == 0
|
|
&& "more flags than flag bits?!");
|
|
return flags;
|
|
}
|
|
|
|
llvm::PointerIntPair<CanGenericSignature, NumFlags, unsigned>
|
|
GenericSigAndFlags;
|
|
|
|
unsigned NumFields;
|
|
|
|
SILLayout(CanGenericSignature Signature,
|
|
ArrayRef<SILField> Fields,
|
|
bool CapturesGenericEnvironment);
|
|
|
|
SILLayout(const SILLayout &) = delete;
|
|
SILLayout &operator=(const SILLayout &) = delete;
|
|
public:
|
|
/// Get or create a layout.
|
|
static SILLayout *get(ASTContext &C,
|
|
CanGenericSignature Generics,
|
|
ArrayRef<SILField> Fields,
|
|
bool CapturesGenericEnvironment);
|
|
|
|
/// Get the generic signature in which this layout exists.
|
|
CanGenericSignature getGenericSignature() const {
|
|
return GenericSigAndFlags.getPointer();
|
|
}
|
|
|
|
/// True if the layout contains any mutable fields.
|
|
bool isMutable() const {
|
|
return GenericSigAndFlags.getInt() & IsMutable;
|
|
}
|
|
|
|
/// True if the layout captures the generic arguments it is substituted with
|
|
/// and can provide generic bindings when passed as a closure argument.
|
|
bool capturesGenericEnvironment() const {
|
|
return GenericSigAndFlags.getInt() & CapturesGenericEnvironment;
|
|
}
|
|
|
|
/// Get the fields inside the layout.
|
|
ArrayRef<SILField> getFields() const {
|
|
return llvm::ArrayRef(getTrailingObjects<SILField>(), NumFields);
|
|
}
|
|
|
|
/// Produce a profile of this layout, for use in a folding set.
|
|
static void Profile(llvm::FoldingSetNodeID &id,
|
|
CanGenericSignature Generics,
|
|
ArrayRef<SILField> Fields,
|
|
bool CapturesGenericEnvironment);
|
|
|
|
/// Produce a profile of this locator, for use in a folding set.
|
|
void Profile(llvm::FoldingSetNodeID &id) {
|
|
Profile(id, getGenericSignature(), getFields(),
|
|
capturesGenericEnvironment());
|
|
}
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_SIL_LAYOUT_H
|