mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
189 lines
7.0 KiB
C++
189 lines
7.0 KiB
C++
//===--- Initialization.h - Buffer initialization. --------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// A storage structure for representing a buffer or collection of buffers to
|
|
// be initialized.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_LOWERING_INITIALIZATION_H
|
|
#define SWIFT_LOWERING_INITIALIZATION_H
|
|
|
|
#include "RValue.h"
|
|
#include <memory>
|
|
|
|
namespace swift {
|
|
namespace Lowering {
|
|
class ManagedValue;
|
|
class SILGenFunction;
|
|
|
|
class Initialization;
|
|
using InitializationPtr = std::unique_ptr<Initialization>;
|
|
|
|
/// Initialization - Abstract base class for initialization buffers. An
|
|
/// initialization represents an uninitialized buffer or a tuple of
|
|
/// uninitialized buffers that must be initialized with the result of an
|
|
/// expression, such as in a var declaration or return statement. An
|
|
/// initialization may also have partial cleanups that should be disabled and
|
|
/// replaced when the buffer is initialized; for instance, a freshly allocated
|
|
/// box with an uninitialized value must be deallocated with `dealloc_ref`, but
|
|
/// once the box is fully initialized, both the box and the contained value can
|
|
/// be cleaned up together with `release`.
|
|
///
|
|
/// FIXME: provide a reset() operation to support multiple
|
|
/// initialization paths.
|
|
class Initialization {
|
|
public:
|
|
enum class Kind {
|
|
/// This Initialization is for a _ binding or other ignored value; the
|
|
/// corresponding result can be discarded.
|
|
Ignored,
|
|
/// This Initialization is for an inout or address-only argument binding,
|
|
/// which is initialized using bindAddress().
|
|
AddressBinding,
|
|
/// This Initialization is to bind a 'let' declaration into VarLocs
|
|
/// directly.
|
|
LetValue,
|
|
/// This Initialization is for a single buffer with a physical address,
|
|
/// which can be accessed with getAddress() and stored to.
|
|
SingleBuffer,
|
|
/// This Initialization performs a semantic translation on its
|
|
/// operand and cannot be directly stored to.
|
|
Translating,
|
|
/// This Initialization is for a tuple of sub-initializations, which can
|
|
/// be accessed with getSubInitializations().
|
|
Tuple
|
|
};
|
|
|
|
/// The Kind of initialization.
|
|
const Kind kind;
|
|
|
|
Initialization(Kind kind) : kind(kind) {}
|
|
virtual ~Initialization() {}
|
|
|
|
/// Return true if this initialization can be forwarded down along
|
|
/// multiple branches of a conditional branch.
|
|
bool canForwardInBranch() const;
|
|
|
|
/// Return true if we can get the addresses of elements with the
|
|
/// 'getSubInitializationsForTuple' method.
|
|
bool canSplitIntoSubelementAddresses() const {
|
|
return kind != Kind::LetValue || hasAddress();
|
|
}
|
|
|
|
/// If this initialization represents a single contiguous buffer, return the
|
|
/// SILValue of that buffer's address. If not, returns an invalid SILValue.
|
|
virtual SILValue getAddressOrNull() const = 0;
|
|
|
|
/// Binds an address value to this initialization. Called only on
|
|
/// initializations with Kind::AddressBinding.
|
|
virtual void bindAddress(SILValue address, SILGenFunction &gen,
|
|
SILLocation loc) {
|
|
llvm_unreachable("unexpected address value in initialization!");
|
|
}
|
|
|
|
/// Provide a value to this initialization. Called only on
|
|
/// initializations with Kind::Translating.
|
|
virtual void translateValue(SILGenFunction &gen, SILLocation loc,
|
|
ManagedValue value) {
|
|
llvm_unreachable("unexpected translated value in initialization!");
|
|
}
|
|
|
|
virtual void bindValue(SILValue value, SILGenFunction &gen) {
|
|
llvm_unreachable("can only bind letvalue!");
|
|
}
|
|
|
|
/// Returns true if this initialization represents a single contiguous buffer.
|
|
bool hasAddress() const { return getAddressOrNull().isValid(); }
|
|
|
|
/// Returns the address of the single contiguous buffer represented by this
|
|
/// initialization. Once the address has been stored to,
|
|
/// finishInitialization must be called.
|
|
SILValue getAddress() {
|
|
SILValue address = getAddressOrNull();
|
|
assert(address && "initialization does not represent a single buffer");
|
|
return address;
|
|
}
|
|
|
|
/// If this initialization represents an aggregation of sub-initializations,
|
|
/// return the sub-initializations. Once all the sub-initializations have been
|
|
/// initialized and finalized with finishInitialization, finishInitialization
|
|
/// must then be called on this aggregate initialization.
|
|
virtual ArrayRef<InitializationPtr> getSubInitializations() const = 0;
|
|
|
|
/// If this initialization represents an aggregation of sub-initializations,
|
|
/// return the sub-initializations. If it represents a single
|
|
/// initialization of tuple type, explode it into initializations for each
|
|
/// individual tuple element. In either case, once all the sub-initializations
|
|
/// have been initialized and finalized with finishInitialization,
|
|
/// finishInitialization must then be called on this aggregate initialization.
|
|
///
|
|
/// \param buf - If new Initializations need to be created, their ownership
|
|
/// is given to this vector.
|
|
/// \param Loc The location with which the single initialization should be
|
|
/// associated.
|
|
ArrayRef<InitializationPtr>
|
|
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
|
|
SmallVectorImpl<InitializationPtr> &buf,
|
|
SILLocation Loc);
|
|
|
|
/// Perform post-initialization bookkeeping for this initialization.
|
|
virtual void finishInitialization(SILGenFunction &gen) {}
|
|
|
|
private:
|
|
Initialization(const Initialization &) = delete;
|
|
Initialization(Initialization &&) = delete;
|
|
|
|
virtual void _anchor();
|
|
};
|
|
|
|
/// Abstract base class for single-buffer initializations.
|
|
class SingleBufferInitialization : public Initialization {
|
|
public:
|
|
SingleBufferInitialization()
|
|
: Initialization(Initialization::Kind::SingleBuffer)
|
|
{}
|
|
|
|
ArrayRef<InitializationPtr> getSubInitializations() const override;
|
|
};
|
|
|
|
/// Abstract base class for single-buffer initializations.
|
|
class TemporaryInitialization : public SingleBufferInitialization {
|
|
SILValue Addr;
|
|
CleanupHandle Cleanup;
|
|
public:
|
|
TemporaryInitialization(SILValue addr, CleanupHandle cleanup)
|
|
: Addr(addr), Cleanup(cleanup) {}
|
|
|
|
void finishInitialization(SILGenFunction &gen) override;
|
|
|
|
SILValue getAddressOrNull() const override {
|
|
return Addr;
|
|
}
|
|
|
|
SILValue getAddress() const {
|
|
return Addr;
|
|
}
|
|
|
|
/// Returns the cleanup corresponding to the value of the temporary.
|
|
CleanupHandle getInitializedCleanup() const { return Cleanup; }
|
|
|
|
ManagedValue getManagedAddress() const {
|
|
return ManagedValue(getAddress(), getInitializedCleanup());
|
|
}
|
|
};
|
|
|
|
} // end namespace Lowering
|
|
} // end namespace swift
|
|
|
|
#endif
|