mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Structurally prevent a number of common anti-patterns involving generic signatures by separating the interface into GenericSignature and the implementation into GenericSignatureBase. In particular, this allows the comparison operators to be deleted which forces callers to canonicalize the signature or ask to compare pointers explicitly.
151 lines
4.9 KiB
C++
151 lines
4.9 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,
|
|
};
|
|
|
|
static constexpr const unsigned NumFlags = 1;
|
|
|
|
static unsigned getFlagsValue(bool Mutable) {
|
|
unsigned flags = 0;
|
|
if (Mutable)
|
|
flags |= IsMutable;
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
/// 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;
|
|
}
|
|
|
|
/// Get the fields inside the layout.
|
|
ArrayRef<SILField> getFields() const {
|
|
return llvm::makeArrayRef(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);
|
|
|
|
/// Produce a profile of this locator, for use in a folding set.
|
|
void Profile(llvm::FoldingSetNodeID &id) {
|
|
Profile(id, getGenericSignature(), getFields());
|
|
}
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_SIL_LAYOUT_H
|