Files
swift-mirror/include/swift/AST/CaptureInfo.h
Jordan Rose 772a124b63 Compute captures after all bodies have been type-checked, as a separate pass.
We already have the restriction that captures can't be computed until
everything is type-checked, but previously we tried to compute captures
/immediately/ after a closure was type-checked. Unfortunately, we either
type-checked too early (before @noescape was propagated onto multi-statement
closures) or too late (trying to compute autoclosure captures at the point
the autoclosure was introduced).

Now, all closure captures are computed after type-checking, and local
function captures as well. They also more consistently reuse the capture
list of nested closures/functions. Because captures can be computed on
demand, there is now a flag on CaptureInfo for whether we've computed
captures yet. Note that some functions will never have captures computed,
namely those that are not in a local context.

rdar://problem/19956242

Swift SVN r25776
2015-03-05 02:33:37 +00:00

103 lines
2.9 KiB
C++

//===--- CaptureInfo.h - Data Structure for Capture Lists -------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_CAPTURE_INFO_H
#define SWIFT_AST_CAPTURE_INFO_H
#include "swift/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
#include <vector>
namespace llvm {
class raw_ostream;
}
namespace swift {
class ValueDecl;
class FuncDecl;
/// CapturedValue includes both the declaration being captured, along with flags
/// that indicate how it is captured.
class CapturedValue {
llvm::PointerIntPair<ValueDecl*, 2, unsigned> Value;
public:
enum {
/// IsDirect is set when a VarDecl with storage *and* accessors is captured
/// by its storage address. This happens in the accessors for the VarDecl.
IsDirect = 1 << 0,
/// IsNoEscape is set when a vardecl is captured by a noescape closure, and
/// thus has its lifetime guaranteed. It can be closed over by a fixed
/// address if it has storage.
IsNoEscape = 1 << 1
};
CapturedValue(ValueDecl *D, unsigned Flags) : Value(D, Flags) {}
bool isDirect() const { return Value.getInt() & IsDirect; }
bool isNoEscape() const { return Value.getInt() & IsNoEscape; }
ValueDecl *getDecl() const { return Value.getPointer(); }
unsigned getFlags() const { return Value.getInt(); }
bool operator==(CapturedValue RHS) const {
return Value == RHS.Value;
}
bool operator!=(CapturedValue RHS) const {
return Value != RHS.Value;
}
bool operator<(CapturedValue RHS) const {
return Value < RHS.Value;
}
};
/// \brief Stores information about captured variables.
class CaptureInfo {
llvm::PointerIntPair<const CapturedValue *, 1, bool> CapturesAndComputed;
size_t Count = 0;
public:
bool hasBeenComputed() { return CapturesAndComputed.getInt(); }
bool empty() { return Count == 0; }
ArrayRef<CapturedValue> getCaptures() const {
return llvm::makeArrayRef(CapturesAndComputed.getPointer(), Count);
}
void setCaptures(ArrayRef<CapturedValue> C) {
CapturesAndComputed.setPointerAndInt(C.data(), true);
Count = C.size();
}
/// \brief Return a filtered list of the captures for this function,
/// filtering out global variables. This function returns the list that
/// actually needs to be closed over.
///
void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const;
/// \returns true if getLocalCaptures() will return a non-empty list.
bool hasLocalCaptures() const;
void dump() const;
void print(raw_ostream &OS) const;
};
} // namespace swift
#endif // LLVM_SWIFT_AST_CAPTURE_INFO_H