blob: 2418f4b83bee2eb832d5f74063865c016711c225 [file] [log] [blame]
//===--- 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