Files
swift-mirror/lib/SILGen/Scope.h
Michael Gottesman 225fd4acfc [silgen] Create Scope::popPreservingValue(ManagedValue).
What this routine does is:

1. "Imprints" a cleanup cloner with the managed value.
2. Forwards the managed value.
3. Pop the scope.
4. Use the imprinted cleanup cloner to recreate the managed value in the scope
outside of the current scope.
2017-03-22 14:55:03 -07:00

127 lines
3.8 KiB
C++

//===--- Scope.h - Declarations for scope RAII objects ----------*- 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 the Scope and FullExpr RAII objects.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILGEN_SCOPE_H
#define SWIFT_SILGEN_SCOPE_H
#include "SILGenFunction.h"
#include "swift/SIL/SILDebugScope.h"
#include "Cleanup.h"
namespace swift {
namespace Lowering {
/// A Scope is a RAII object recording that a scope (e.g. a brace
/// statement) has been entered.
class LLVM_LIBRARY_VISIBILITY Scope {
CleanupManager &cleanups;
CleanupsDepth depth;
CleanupsDepth savedInnermostScope;
CleanupLocation loc;
public:
explicit Scope(CleanupManager &cleanups, CleanupLocation loc)
: cleanups(cleanups), depth(cleanups.getCleanupsDepth()),
savedInnermostScope(cleanups.innermostScope), loc(loc) {
assert(depth.isValid());
cleanups.stack.checkIterator(cleanups.innermostScope);
cleanups.innermostScope = depth;
}
explicit Scope(SILGenFunction &SGF, SILLocation loc)
: Scope(SGF.Cleanups, CleanupLocation::get(loc)) {}
void pop() {
assert(depth.isValid() && "popping a scope twice!");
popImpl();
depth = CleanupsDepth::invalid();
}
~Scope() {
if (depth.isValid())
popImpl();
}
bool isValid() const { return depth.isValid(); }
ManagedValue popPreservingValue(ManagedValue mv) {
// If we have a value, make sure that it is an object. The reason why is
// that we want to make sure that we are not forwarding a cleanup for a
// stack location that will be destroyed by this scope.
assert(!mv.getValue() || mv.getType().isObject());
CleanupCloner cloner(cleanups.SGF, mv);
SILValue value = mv.forward(cleanups.SGF);
pop();
return cloner.clone(value);
}
private:
void popImpl() {
cleanups.stack.checkIterator(depth);
cleanups.stack.checkIterator(cleanups.innermostScope);
assert(cleanups.innermostScope == depth && "popping scopes out of order");
cleanups.innermostScope = savedInnermostScope;
cleanups.endScope(depth, loc);
cleanups.stack.checkIterator(cleanups.innermostScope);
cleanups.popTopDeadCleanups(cleanups.innermostScope);
}
};
/// A FullExpr is a RAII object recording that a full-expression has
/// been entered. A full-expression is essentially a very small scope
/// for the temporaries in an expression, with the added complexity
/// that (eventually, very likely) we have to deal with expressions
/// that are only conditionally evaluated.
class LLVM_LIBRARY_VISIBILITY FullExpr : private Scope {
public:
explicit FullExpr(CleanupManager &cleanups, CleanupLocation loc)
: Scope(cleanups, loc) {}
using Scope::pop;
};
/// A LexicalScope is a Scope that is also exposed to the debug info.
class LLVM_LIBRARY_VISIBILITY LexicalScope : private Scope {
SILGenFunction& SGF;
public:
explicit LexicalScope(SILGenFunction &SGF, CleanupLocation loc)
: Scope(SGF.Cleanups, loc), SGF(SGF) {
SGF.enterDebugScope(loc);
}
using Scope::pop;
~LexicalScope() {
SGF.leaveDebugScope();
}
};
/// A scope that only exists in the debug info.
class LLVM_LIBRARY_VISIBILITY DebugScope {
SILGenFunction &SGF;
public:
explicit DebugScope(SILGenFunction &SGF, CleanupLocation loc) : SGF(SGF) {
SGF.enterDebugScope(loc);
}
~DebugScope() { SGF.leaveDebugScope(); }
};
} // end namespace Lowering
} // end namespace swift
#endif