Follow the design guidelines for the AArch64 `CodeBufferCheckScope`.
The implementation of the scopes relies only on the `AssemblerBase` interface.
The AArch32 scopes will be updated in a separate commit.
Change-Id: Ibe0eab35f60da39fe0bcbd60a16bdc65b12e0dd5
diff --git a/src/code-generation-scopes-vixl.h b/src/code-generation-scopes-vixl.h
new file mode 100644
index 0000000..cf04dd0
--- /dev/null
+++ b/src/code-generation-scopes-vixl.h
@@ -0,0 +1,145 @@
+// Copyright 2016, VIXL authors
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of ARM Limited nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#ifndef VIXL_CODE_GENERATION_SCOPES_H_
+#define VIXL_CODE_GENERATION_SCOPES_H_
+
+
+#include "assembler-base-vixl.h"
+
+
+namespace vixl {
+
+// This scope will:
+// - Allow code emission from the specified `Assembler`.
+// - Optionally reserve space in the `CodeBuffer` (if it is managed by VIXL).
+// - Optionally, on destruction, check the size of the generated code.
+// (The size can be either exact or a maximum size.)
+class CodeBufferCheckScope {
+ public:
+ // Tell whether or not the scope needs to ensure the associated CodeBuffer
+ // has enough space for the requested size.
+ enum BufferSpacePolicy {
+ kReserveBufferSpace,
+ kDontReserveBufferSpace,
+
+ // Deprecated, but kept for backward compatibility.
+ kCheck = kReserveBufferSpace,
+ kNoCheck = kDontReserveBufferSpace
+ };
+
+ // Tell whether or not the scope should assert the amount of code emitted
+ // within the scope is consistent with the requested amount.
+ enum SizePolicy {
+ kNoAssert, // Do not check the size of the code emitted.
+ kExactSize, // The code emitted must be exactly size bytes.
+ kMaximumSize // The code emitted must be at most size bytes.
+ };
+
+ // This constructor implicitly calls `Open` to initialise the scope
+ // (`assembler` must not be `NULL`), so it is ready to use immediately after
+ // it has been constructed.
+ CodeBufferCheckScope(internal::AssemblerBase* assembler,
+ size_t size,
+ BufferSpacePolicy check_policy = kReserveBufferSpace,
+ SizePolicy size_policy = kMaximumSize)
+#ifdef VIXL_DEBUG
+ : initialised_(false)
+#endif
+ {
+ Open(assembler, size, check_policy, size_policy);
+ }
+
+ // This constructor does not implicitly initialise the scope. Instead, the
+ // user is required to explicitly call the `Open` function before using the
+ // scope.
+ CodeBufferCheckScope()
+#ifdef VIXL_DEBUG
+ : initialised_(false)
+#endif
+ {
+ // Nothing to do.
+ }
+
+ virtual ~CodeBufferCheckScope() { Close(); }
+
+ // This function performs the actual initialisation work.
+ void Open(internal::AssemblerBase* assembler,
+ size_t size,
+ BufferSpacePolicy check_policy = kReserveBufferSpace,
+ SizePolicy size_policy = kMaximumSize) {
+ VIXL_ASSERT(!initialised_);
+ VIXL_ASSERT(assembler != NULL);
+ if (check_policy == kReserveBufferSpace) {
+ assembler->GetBuffer()->EnsureSpaceFor(size);
+ }
+#ifdef VIXL_DEBUG
+ assembler_ = assembler;
+ limit_ = assembler_->GetSizeOfCodeGenerated() + size;
+ assert_policy_ = size_policy;
+ previous_allow_assembler_ = assembler_->AllowAssembler();
+ assembler_->SetAllowAssembler(true);
+ initialised_ = true;
+#else
+ USE(size_policy);
+#endif
+ }
+
+ // This function performs the cleaning-up work. It must succeed even if the
+ // scope has not been opened. It is safe to call multiple times.
+ void Close() {
+#ifdef VIXL_DEBUG
+ if (!initialised_) {
+ return;
+ }
+ assembler_->SetAllowAssembler(previous_allow_assembler_);
+ switch (assert_policy_) {
+ case kNoAssert:
+ break;
+ case kExactSize:
+ VIXL_ASSERT(assembler_->GetSizeOfCodeGenerated() == limit_);
+ break;
+ case kMaximumSize:
+ VIXL_ASSERT(assembler_->GetSizeOfCodeGenerated() <= limit_);
+ break;
+ default:
+ VIXL_UNREACHABLE();
+ }
+ initialised_ = false;
+#endif
+ }
+
+ protected:
+ internal::AssemblerBase* assembler_;
+ SizePolicy assert_policy_;
+ size_t limit_;
+ bool previous_allow_assembler_;
+ bool initialised_;
+};
+} // namespace vixl
+
+#endif // VIXL_CODE_GENERATION_SCOPES_H_