19dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// Copyright 2016, VIXL authors 29dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// All rights reserved. 39dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// 49dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// Redistribution and use in source and binary forms, with or without 59dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// modification, are permitted provided that the following conditions are met: 69dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// 79dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// * Redistributions of source code must retain the above copyright notice, 89dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// this list of conditions and the following disclaimer. 99dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// * Redistributions in binary form must reproduce the above copyright notice, 109dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// this list of conditions and the following disclaimer in the documentation 119dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// and/or other materials provided with the distribution. 129dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// * Neither the name of ARM Limited nor the names of its contributors may be 139dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// used to endorse or promote products derived from this software without 149dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// specific prior written permission. 159dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// 169dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 179dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 189dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 199dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 209dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 219dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 229dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 239dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 249dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 259dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 269dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 279dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 289dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#ifndef VIXL_CODE_GENERATION_SCOPES_H_ 299dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#define VIXL_CODE_GENERATION_SCOPES_H_ 309dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 319dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 329dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#include "assembler-base-vixl.h" 33c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames#include "macro-assembler-interface.h" 349dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 359dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 369dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Ramesnamespace vixl { 379dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 389dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// This scope will: 399dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// - Allow code emission from the specified `Assembler`. 409dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// - Optionally reserve space in the `CodeBuffer` (if it is managed by VIXL). 419dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// - Optionally, on destruction, check the size of the generated code. 429dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames// (The size can be either exact or a maximum size.) 439dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Ramesclass CodeBufferCheckScope { 449dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames public: 459dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // Tell whether or not the scope needs to ensure the associated CodeBuffer 469dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // has enough space for the requested size. 479dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames enum BufferSpacePolicy { 489dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames kReserveBufferSpace, 499dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames kDontReserveBufferSpace, 509dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 519dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // Deprecated, but kept for backward compatibility. 529dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames kCheck = kReserveBufferSpace, 539dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames kNoCheck = kDontReserveBufferSpace 549dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames }; 559dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 569dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // Tell whether or not the scope should assert the amount of code emitted 579dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // within the scope is consistent with the requested amount. 589dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames enum SizePolicy { 599dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames kNoAssert, // Do not check the size of the code emitted. 609dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames kExactSize, // The code emitted must be exactly size bytes. 619dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames kMaximumSize // The code emitted must be at most size bytes. 629dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames }; 639dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 649dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // This constructor implicitly calls `Open` to initialise the scope 659dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // (`assembler` must not be `NULL`), so it is ready to use immediately after 669dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // it has been constructed. 679dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames CodeBufferCheckScope(internal::AssemblerBase* assembler, 689dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames size_t size, 699dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames BufferSpacePolicy check_policy = kReserveBufferSpace, 709dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames SizePolicy size_policy = kMaximumSize) 71c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames : assembler_(NULL), initialised_(false) { 729dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames Open(assembler, size, check_policy, size_policy); 739dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames } 749dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 759dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // This constructor does not implicitly initialise the scope. Instead, the 769dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // user is required to explicitly call the `Open` function before using the 779dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // scope. 78c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames CodeBufferCheckScope() : assembler_(NULL), initialised_(false) { 799dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // Nothing to do. 809dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames } 819dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 829dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames virtual ~CodeBufferCheckScope() { Close(); } 839dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 849dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // This function performs the actual initialisation work. 859dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames void Open(internal::AssemblerBase* assembler, 869dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames size_t size, 879dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames BufferSpacePolicy check_policy = kReserveBufferSpace, 889dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames SizePolicy size_policy = kMaximumSize) { 899dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames VIXL_ASSERT(!initialised_); 909dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames VIXL_ASSERT(assembler != NULL); 91c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames assembler_ = assembler; 929dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames if (check_policy == kReserveBufferSpace) { 939dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames assembler->GetBuffer()->EnsureSpaceFor(size); 949dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames } 959dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#ifdef VIXL_DEBUG 969dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames limit_ = assembler_->GetSizeOfCodeGenerated() + size; 979dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames assert_policy_ = size_policy; 989dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames previous_allow_assembler_ = assembler_->AllowAssembler(); 999dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames assembler_->SetAllowAssembler(true); 1009dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#else 1019dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames USE(size_policy); 1029dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#endif 103c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames initialised_ = true; 1049dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames } 1059dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 1069dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // This function performs the cleaning-up work. It must succeed even if the 1079dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames // scope has not been opened. It is safe to call multiple times. 1089dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames void Close() { 1099dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#ifdef VIXL_DEBUG 1109dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames if (!initialised_) { 1119dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames return; 1129dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames } 1139dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames assembler_->SetAllowAssembler(previous_allow_assembler_); 1149dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames switch (assert_policy_) { 1159dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames case kNoAssert: 1169dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames break; 1179dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames case kExactSize: 1189dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames VIXL_ASSERT(assembler_->GetSizeOfCodeGenerated() == limit_); 1199dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames break; 1209dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames case kMaximumSize: 1219dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames VIXL_ASSERT(assembler_->GetSizeOfCodeGenerated() <= limit_); 1229dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames break; 1239dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames default: 1249dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames VIXL_UNREACHABLE(); 1259dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames } 1269dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#endif 127c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames initialised_ = false; 1289dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames } 1299dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 1309dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames protected: 1319dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames internal::AssemblerBase* assembler_; 1329dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames SizePolicy assert_policy_; 1339dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames size_t limit_; 1349dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames bool previous_allow_assembler_; 1359dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames bool initialised_; 1369dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames}; 137c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 138c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 139c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// This scope will: 140c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// - Do the same as `CodeBufferCheckSCope`, but: 141c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// - If managed by VIXL, always reserve space in the `CodeBuffer`. 142c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// - Always check the size (exact or maximum) of the generated code on 143c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// destruction. 144c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// - Emit pools if the specified size would push them out of range. 145c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// - Block pools emission for the duration of the scope. 146c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// This scope allows the `Assembler` and `MacroAssembler` to be freely and 147c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames// safely mixed for its duration. 148c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Ramesclass EmissionCheckScope : public CodeBufferCheckScope { 149c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames public: 150c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // This constructor implicitly calls `Open` (when `masm` is not `NULL`) to 151c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // initialise the scope, so it is ready to use immediately after it has been 152c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // constructed. 153c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames EmissionCheckScope(MacroAssemblerInterface* masm, 154c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames size_t size, 155c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames SizePolicy size_policy = kMaximumSize) { 156c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames Open(masm, size, size_policy); 157c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 158c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 159c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // This constructor does not implicitly initialise the scope. Instead, the 160c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // user is required to explicitly call the `Open` function before using the 161c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // scope. 162c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames EmissionCheckScope() {} 163c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 164c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames virtual ~EmissionCheckScope() { Close(); } 165c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 166d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois enum PoolPolicy { 167d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois // Do not forbid pool emission inside the scope. Pools will not be emitted 168d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois // on `Open` either. 169d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois kIgnorePools, 170d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois // Force pools to be generated on `Open` if necessary and block their 171d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois // emission inside the scope. 172d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois kBlockPools, 173d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois // Deprecated, but kept for backward compatibility. 174d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois kCheckPools = kBlockPools 175d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois }; 176c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 177c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames void Open(MacroAssemblerInterface* masm, 178c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames size_t size, 179c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames SizePolicy size_policy = kMaximumSize) { 180d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois Open(masm, size, size_policy, kBlockPools); 181c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 182c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 183c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames void Close() { 184c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames if (!initialised_) { 185c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames return; 186c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 187c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames if (masm_ == NULL) { 188c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // Nothing to do. 189c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames return; 190c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 1916ee0978e4e0462cdaa4c92591e9a36fdeaef704dPierre Langlois // Perform the opposite of `Open`, which is: 1926ee0978e4e0462cdaa4c92591e9a36fdeaef704dPierre Langlois // - Check the code generation limit was not exceeded. 1936ee0978e4e0462cdaa4c92591e9a36fdeaef704dPierre Langlois // - Release the pools. 1946ee0978e4e0462cdaa4c92591e9a36fdeaef704dPierre Langlois CodeBufferCheckScope::Close(); 195d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois if (pool_policy_ == kBlockPools) { 196c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames masm_->ReleasePools(); 197c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 198c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames VIXL_ASSERT(!initialised_); 199c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 200c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 201c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames protected: 202c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames void Open(MacroAssemblerInterface* masm, 203c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames size_t size, 204c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames SizePolicy size_policy, 205c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames PoolPolicy pool_policy) { 206c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames if (masm == NULL) { 207c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // Nothing to do. 208c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // We may reach this point in a context of conditional code generation. 209c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // See `aarch64::MacroAssembler::MoveImmediateHelper()` for an example. 210c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames return; 211c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 212c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames masm_ = masm; 213c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames pool_policy_ = pool_policy; 214d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois if (pool_policy_ == kBlockPools) { 215c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // To avoid duplicating the work to check that enough space is available 216c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // in the buffer, do not use the more generic `EnsureEmitFor()`. It is 217c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // done below when opening `CodeBufferCheckScope`. 218c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames masm->EnsureEmitPoolsFor(size); 219c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames masm->BlockPools(); 220c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 221c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // The buffer should be checked *after* we emit the pools. 2228d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames CodeBufferCheckScope::Open(masm->AsAssemblerBase(), 223c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames size, 224c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames kReserveBufferSpace, 225c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames size_policy); 226c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames VIXL_ASSERT(initialised_); 227c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 228c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 229c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // This constructor should only be used from code that is *currently 230c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames // generating* the pools, to avoid an infinite loop. 231c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames EmissionCheckScope(MacroAssemblerInterface* masm, 232c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames size_t size, 233c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames SizePolicy size_policy, 234c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames PoolPolicy pool_policy) { 235c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames Open(masm, size, size_policy, pool_policy); 236c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames } 237c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 238c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames MacroAssemblerInterface* masm_; 239c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames PoolPolicy pool_policy_; 240c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames}; 241c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 24207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// Use this scope when you need a one-to-one mapping between methods and 24307d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// instructions. This scope will: 24407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// - Do the same as `EmissionCheckScope`. 24507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// - Block access to the MacroAssemblerInterface (using run-time assertions). 24607d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Ramesclass ExactAssemblyScope : public EmissionCheckScope { 24707d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames public: 24807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // This constructor implicitly calls `Open` (when `masm` is not `NULL`) to 24907d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // initialise the scope, so it is ready to use immediately after it has been 25007d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // constructed. 25107d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames ExactAssemblyScope(MacroAssemblerInterface* masm, 25207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames size_t size, 25345262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois SizePolicy size_policy = kExactSize) { 25445262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois Open(masm, size, size_policy); 25507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames } 25607d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames 25707d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // This constructor does not implicitly initialise the scope. Instead, the 25807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // user is required to explicitly call the `Open` function before using the 25907d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // scope. 26007d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames ExactAssemblyScope() {} 26107d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames 26245262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois virtual ~ExactAssemblyScope() { Close(); } 26345262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois 26445262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois void Open(MacroAssemblerInterface* masm, 26545262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois size_t size, 26645262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois SizePolicy size_policy = kExactSize) { 26745262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois Open(masm, size, size_policy, kBlockPools); 26845262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois } 26945262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois 27045262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois void Close() { 27145262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois if (!initialised_) { 27245262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois return; 27345262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois } 27445262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois if (masm_ == NULL) { 27545262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois // Nothing to do. 27645262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois return; 27745262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois } 27807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames#ifdef VIXL_DEBUG 279c521a8b486f0da6a9d7bb7940766a2eca542cd98Scott Wakeling masm_->SetAllowMacroInstructions(previous_allow_macro_assembler_); 28045262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois#else 28145262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois USE(previous_allow_macro_assembler_); 28207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames#endif 28345262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois EmissionCheckScope::Close(); 28407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames } 28507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames 28607d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames protected: 28707d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // This protected constructor allows overriding the pool policy. It is 28807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // available to allow this scope to be used in code that handles generation 28907d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames // of pools. 29007d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames ExactAssemblyScope(MacroAssemblerInterface* masm, 29107d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames size_t size, 29207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames SizePolicy assert_policy, 29345262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois PoolPolicy pool_policy) { 29445262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois Open(masm, size, assert_policy, pool_policy); 29545262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois } 29645262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois 29745262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois void Open(MacroAssemblerInterface* masm, 29845262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois size_t size, 29945262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois SizePolicy size_policy, 30045262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois PoolPolicy pool_policy) { 30145262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois VIXL_ASSERT(size_policy != kNoAssert); 30245262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois if (masm == NULL) { 30345262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois // Nothing to do. 30445262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois return; 30545262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois } 30645262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois // Rely on EmissionCheckScope::Open to initialise `masm_` and 30745262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois // `pool_policy_`. 30845262d6ba1f736aaebfa6f7ef50a3e83cd4e5e70Pierre Langlois EmissionCheckScope::Open(masm, size, size_policy, pool_policy); 30907d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames#ifdef VIXL_DEBUG 31007d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames previous_allow_macro_assembler_ = masm->AllowMacroInstructions(); 31107d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames masm->SetAllowMacroInstructions(false); 31207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames#endif 31307d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames } 31407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames 31507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames private: 31607d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames bool previous_allow_macro_assembler_; 31707d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames}; 31807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames 319c0b25f28106fbbbf8880e0b259de1a639ea1e73fAlexandre Rames 3209dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames} // namespace vixl 3219dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames 3229dd6fa37dbb79f62177aebd04d7e945ce1dc3108Alexandre Rames#endif // VIXL_CODE_GENERATION_SCOPES_H_ 323