11cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// Copyright 2017, VIXL authors 21cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// All rights reserved. 31cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 41cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// Redistribution and use in source and binary forms, with or without 51cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// modification, are permitted provided that the following conditions are met: 61cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 71cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// * Redistributions of source code must retain the above copyright notice, 81cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// this list of conditions and the following disclaimer. 91cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// * Redistributions in binary form must reproduce the above copyright notice, 101cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// this list of conditions and the following disclaimer in the documentation 111cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// and/or other materials provided with the distribution. 121cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// * Neither the name of ARM Limited nor the names of its contributors may be 131cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// used to endorse or promote products derived from this software without 141cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// specific prior written permission. 151cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 161cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 171cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 181cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 191cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 201cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 211cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 221cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 231cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 251cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 261cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 271cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#ifndef VIXL_POOL_MANAGER_H_ 281cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#define VIXL_POOL_MANAGER_H_ 291cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 301cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include <stdint.h> 311cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 321cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include <cstddef> 331cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include <limits> 341cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include <map> 351cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include <vector> 361cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 371cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include "globals-vixl.h" 381cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include "macro-assembler-interface.h" 391cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#include "utils-vixl.h" 401cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 411cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelinamespace vixl { 421cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 431cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveliclass TestPoolManager; 441cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 451cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// There are four classes declared in this header file: 468b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// PoolManager, PoolObject, ForwardReference and LocationBase. 471cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 481cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// The PoolManager manages both literal and veneer pools, and is designed to be 491cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// shared between AArch32 and AArch64. A pool is represented as an abstract 501cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// collection of references to objects. The manager does not need to know 511cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// architecture-specific details about literals and veneers; the actual 521cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// emission of the pool objects is delegated. 531cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 548b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// Literal and Label will derive from LocationBase. The MacroAssembler will 558b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// create these objects as instructions that reference pool objects are 568b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// encountered, and ask the PoolManager to track them. The PoolManager will 578b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// create an internal PoolObject object for each object derived from 588b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// LocationBase. Some of these PoolObject objects will be deleted when placed 598b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// (e.g. the ones corresponding to Literals), whereas others will be updated 608b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// with a new range when placed (e.g. Veneers) and deleted when Bind() is 618b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// called on the PoolManager with their corresponding object as a parameter. 621cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 631cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// A ForwardReference represents a reference to a PoolObject that will be 641cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// placed later in the instruction stream. Each ForwardReference may only refer 651cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// to one PoolObject, but many ForwardReferences may refer to the same 661cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// object. 671cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 681cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// A PoolObject represents an object that has not yet been placed. The final 698b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// location of a PoolObject (and hence the LocationBase object to which it 701cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// corresponds) is constrained mostly by the instructions that refer to it, but 711cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// PoolObjects can also have inherent constraints, such as alignment. 721cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 738b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// LocationBase objects, unlike PoolObject objects, can be used outside of the 741cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// pool manager (e.g. as manually placed literals, which may still have 751cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// forward references that need to be resolved). 761cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// 778b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// At the moment, each LocationBase will have at most one PoolObject that keeps 781cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// the relevant information for placing this object in the pool. When that 791cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// object is placed, all forward references of the object are resolved. For 801cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// that reason, we do not need to keep track of the ForwardReference objects in 811cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// the PoolObject. 821cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 831cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// T is an integral type used for representing locations. For a 32-bit 841cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// architecture it will typically be int32_t, whereas for a 64-bit 851cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// architecture it will be int64_t. 861cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelitemplate <typename T> 871cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveliclass ForwardReference; 881cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelitemplate <typename T> 891cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveliclass PoolObject; 901cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelitemplate <typename T> 911cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveliclass PoolManager; 921cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 931cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// Represents an object that has a size and alignment, and either has a known 948b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// location or has not been placed yet. An object of a subclass of LocationBase 951cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// will typically keep track of a number of ForwardReferences when it has not 968b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// yet been placed, but LocationBase does not assume or implement that 978b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// functionality. LocationBase provides virtual methods for emitting the 988b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// object, updating all the forward references, and giving the PoolManager 998b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// information on the lifetime of this object and the corresponding PoolObject. 1001cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelitemplate <typename T> 1018b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveliclass LocationBase { 1021cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli public: 1038b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // The size of a LocationBase object is restricted to 4KB, in order to avoid 1041cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // situations where the size of the pool becomes larger than the range of 1051cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // an unconditional branch. This cannot happen without having large objects, 1061cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // as typically the range of an unconditional branch is the larger range 1071cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // an instruction supports. 1081cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // TODO: This would ideally be an architecture-specific value, perhaps 1091cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // another template parameter. 1101cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli static const int kMaxObjectSize = 4 * KBytes; 1111cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1128b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // By default, LocationBase objects are aligned naturally to their size. 1138b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli LocationBase(uint32_t type, int size) 1141cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli : pool_object_size_(size), 1151cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli pool_object_alignment_(size), 1161cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli pool_object_type_(type), 1171cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli is_bound_(false), 1181cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli location_(0) { 1191cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(size > 0); 1201cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(size <= kMaxObjectSize); 1211cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(IsPowerOf2(size)); 1221cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 1231cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1241cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Allow alignment to be specified, as long as it is smaller than the size. 1258b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli LocationBase(uint32_t type, int size, int alignment) 1261cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli : pool_object_size_(size), 1271cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli pool_object_alignment_(alignment), 1281cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli pool_object_type_(type), 1291cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli is_bound_(false), 1301cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli location_(0) { 1311cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(size > 0); 1321cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(size <= kMaxObjectSize); 1331cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(IsPowerOf2(alignment)); 1341cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(alignment <= size); 1351cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 1361cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1371cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Constructor for locations that are already bound. 1388b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli explicit LocationBase(T location) 1391cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli : pool_object_size_(-1), 1401cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli pool_object_alignment_(-1), 1411cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli pool_object_type_(0), 1421cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli is_bound_(true), 1431cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli location_(location) {} 1441cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1458b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli virtual ~LocationBase() 1468b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli VIXL_THROW_IN_NEGATIVE_TESTING_MODE(std::runtime_error) {} 1471cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1481cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The PoolManager should assume ownership of some objects, and delete them 1491cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // after they have been placed. This can happen for example for literals that 1501cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // are created internally to the MacroAssembler and the user doesn't get a 1511cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // handle to. By default, the PoolManager will not do this. 1521cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual bool ShouldBeDeletedOnPlacementByPoolManager() const { return false; } 1531cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The PoolManager should assume ownership of some objects, and delete them 1541cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // when it is destroyed. By default, the PoolManager will not do this. 1551cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual bool ShouldBeDeletedOnPoolManagerDestruction() const { return false; } 1561cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1571cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Emit the PoolObject. Derived classes will implement this method to emit 1581cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // the necessary data and/or code (for example, to emit a literal or a 1591cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // veneer). This should not add padding, as it is added explicitly by the pool 1601cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // manager. 1611cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual void EmitPoolObject(MacroAssemblerInterface* masm) = 0; 1621cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1631cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Resolve the references to this object. Will encode the necessary offset 1641cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // in the instruction corresponding to each reference and then delete it. 1651cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // TODO: An alternative here would be to provide a ResolveReference() 1668b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // method that only asks the LocationBase to resolve a specific reference 1678b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // (thus allowing the pool manager to resolve some of the references only). 1688b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // This would mean we need to have some kind of API to get all the references 1698b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // to a LabelObject. 1701cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual void ResolveReferences(internal::AssemblerBase* assembler) = 0; 1711cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1728b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // Returns true when the PoolObject corresponding to this LocationBase object 1731cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // needs to be removed from the pool once placed, and false if it needs to 1741cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // be updated instead (in which case UpdatePoolObject will be called). 1751cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual bool ShouldDeletePoolObjectOnPlacement() const { return true; } 1761cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1771cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Update the PoolObject after placing it, if necessary. This will happen for 1781cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // example in the case of a placed veneer, where we need to use a new updated 1791cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // range and a new reference (from the newly added branch instruction). 1801cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // By default, this does nothing, to avoid forcing objects that will not need 1811cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // this to have an empty implementation. 1821cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual void UpdatePoolObject(PoolObject<T>*) {} 1831cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1841cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Implement heuristics for emitting this object. If a margin is to be used 1851cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // as a hint during pool emission, we will try not to emit the object if we 1861cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // are further away from the maximum reachable location by more than the 1871cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // margin. 1881cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual bool UsePoolObjectEmissionMargin() const { return false; } 1891cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual T GetPoolObjectEmissionMargin() const { 1901cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(UsePoolObjectEmissionMargin() == false); 1911cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli return 0; 1921cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 1931cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1941cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int GetPoolObjectSizeInBytes() const { return pool_object_size_; } 1951cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int GetPoolObjectAlignment() const { return pool_object_alignment_; } 1961cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli uint32_t GetPoolObjectType() const { return pool_object_type_; } 1971cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 1981cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli bool IsBound() const { return is_bound_; } 1991cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T GetLocation() const { return location_; } 2001cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2011cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // This function can be called multiple times before the object is marked as 2021cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // bound with MarkBound() below. This is because some objects (e.g. the ones 2031cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // used to represent labels) can have veneers; every time we place a veneer 2041cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // we need to keep track of the location in order to resolve the references 2051cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // to the object. Reusing the location_ field for this is convenient. 2061cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void SetLocation(internal::AssemblerBase* assembler, T location) { 2071cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(!is_bound_); 2081cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli location_ = location; 2091cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli ResolveReferences(assembler); 2101cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2111cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2121cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void MarkBound() { 2131cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(!is_bound_); 2141cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli is_bound_ = true; 2151cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2161cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2171cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The following two functions are used when an object is bound by a call to 2181cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // PoolManager<T>::Bind(). 2191cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual int GetMaxAlignment() const { 2201cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(!ShouldDeletePoolObjectOnPlacement()); 2211cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli return 1; 2221cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2231cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli virtual T GetMinLocation() const { 2241cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(!ShouldDeletePoolObjectOnPlacement()); 2251cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli return 0; 2261cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2271cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2281cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli private: 2291cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The size of the corresponding PoolObject, in bytes. 2301cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int pool_object_size_; 2311cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The alignment of the corresponding PoolObject; this must be a power of two. 2321cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int pool_object_alignment_; 2331cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2341cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Different derived classes should have different type values. This can be 2351cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // used internally by the PoolManager for grouping of objects. 2361cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli uint32_t pool_object_type_; 2371cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Has the object been bound to a location yet? 2381cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli bool is_bound_; 2391cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2401cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli protected: 2411cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // See comment on SetLocation() for the use of this field. 2421cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T location_; 2431cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli}; 2441cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2451cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelitemplate <typename T> 2461cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveliclass PoolObject { 2471cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli public: 2481cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // By default, PoolObjects have no inherent position constraints. 2498b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli explicit PoolObject(LocationBase<T>* parent) 2501cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli : label_base_(parent), 2511cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli min_location_(0), 2521cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli max_location_(std::numeric_limits<T>::max()), 2531cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli alignment_(parent->GetPoolObjectAlignment()), 2541cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli skip_until_location_hint_(0), 2551cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli type_(parent->GetPoolObjectType()) { 2561cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(IsPowerOf2(alignment_)); 2571cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli UpdateLocationHint(); 2581cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2591cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2601cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Reset the minimum and maximum location and the alignment of the object. 2618b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // This function is public in order to allow the LocationBase corresponding to 2621cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // this PoolObject to update the PoolObject when placed, e.g. in the case of 2631cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // veneers. The size and type of the object cannot be modified. 2641cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void Update(T min, T max, int alignment) { 2651cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // We don't use RestrictRange here as the new range is independent of the 2661cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // old range (and the maximum location is typically larger). 2671cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli min_location_ = min; 2681cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli max_location_ = max; 2691cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli RestrictAlignment(alignment); 2701cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli UpdateLocationHint(); 2711cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2721cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2731cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli private: 2741cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void RestrictRange(T min, T max) { 2751cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(min <= max_location_); 2761cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(max >= min_location_); 2771cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli min_location_ = std::max(min_location_, min); 2781cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli max_location_ = std::min(max_location_, max); 2791cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli UpdateLocationHint(); 2801cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2811cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2821cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void RestrictAlignment(int alignment) { 2831cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(IsPowerOf2(alignment)); 2841cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(IsPowerOf2(alignment_)); 2851cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli alignment_ = std::max(alignment_, alignment); 2861cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2871cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2881cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void UpdateLocationHint() { 2891cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli if (label_base_->UsePoolObjectEmissionMargin()) { 2901cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli skip_until_location_hint_ = 2911cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli max_location_ - label_base_->GetPoolObjectEmissionMargin(); 2921cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2931cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 2941cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2958b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // The LocationBase that this pool object represents. 2968b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli LocationBase<T>* label_base_; 2971cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 2981cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Hard, precise location constraints for the start location of the object. 2991cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // They are both inclusive, that is the start location of the object can be 3001cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // at any location between min_location_ and max_location_, themselves 3011cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // included. 3021cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T min_location_; 3031cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T max_location_; 3041cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3051cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The alignment must be a power of two. 3061cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int alignment_; 3071cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3081cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Avoid generating this object until skip_until_location_hint_. This 3091cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // supports cases where placing the object in the pool has an inherent cost 3101cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // that could be avoided in some other way. Veneers are a typical example; we 3111cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // would prefer to branch directly (over a pool) rather than use veneers, so 3121cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // this value can be set using some heuristic to leave them in the pool. 3131cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // This value is only a hint, which will be ignored if it has to in order to 3141cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // meet the hard constraints we have. 3151cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T skip_until_location_hint_; 3161cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3171cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Used only to group objects of similar type together. The PoolManager does 3181cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // not know what the types represent. 3191cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli uint32_t type_; 3201cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3211cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli friend class PoolManager<T>; 3221cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli}; 3231cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3241cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// Class that represents a forward reference. It is the responsibility of 3258b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// LocationBase objects to keep track of forward references and patch them when 3268b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli// an object is placed - this class is only used by the PoolManager in order to 3271cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli// restrict the requirements on PoolObjects it is tracking. 3281cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelitemplate <typename T> 3291cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveliclass ForwardReference { 3301cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli public: 3311cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli ForwardReference(T location, 3321cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int size, 3331cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T min_object_location, 3341cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T max_object_location, 3351cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int object_alignment = 1) 3361cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli : location_(location), 3371cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli size_(size), 3381cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli object_alignment_(object_alignment), 3391cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli min_object_location_(min_object_location), 3401cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli max_object_location_(max_object_location) { 3411cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli VIXL_ASSERT(AlignDown(max_object_location, object_alignment) >= 3421cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli min_object_location); 3431cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 3441cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3451cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli bool LocationIsEncodable(T location) const { 3461cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli return location >= min_object_location_ && 3471cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli location <= max_object_location_ && 3481cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli IsAligned(location, object_alignment_); 3491cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 3501cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3511cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T GetLocation() const { return location_; } 3521cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T GetMinLocation() const { return min_object_location_; } 3531cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T GetMaxLocation() const { return max_object_location_; } 3541cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int GetAlignment() const { return object_alignment_; } 3551cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3568b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // Needed for InvalSet. 3578b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli void SetLocationToInvalidateOnly(T location) { location_ = location; } 3588b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli 3591cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli private: 3601cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The location of the thing that contains the reference. For example, this 3611cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // can be the location of the branch or load instruction. 3621cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T location_; 3631cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3641cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The size of the instruction that makes the reference, in bytes. 3651cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int size_; 3661cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3671cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The alignment that the object must satisfy for this reference - must be a 3681cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // power of two. 3691cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int object_alignment_; 3701cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3711cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Specify the possible locations where the object could be stored. AArch32's 3721cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // PC offset, and T32's PC alignment calculations should be applied by the 3731cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Assembler, not here. The PoolManager deals only with simple locationes. 3741cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Including min_object_adddress_ is necessary to handle AArch32 some 3751cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // instructions which have a minimum offset of 0, but also have the implicit 3761cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // PC offset. 3771cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Note that this structure cannot handle sparse ranges, such as A32's ADR, 3781cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // but doing so is costly and probably not useful in practice. The min and 3791cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // and max object location both refer to the beginning of the object, are 3801cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // inclusive and are not affected by the object size. E.g. if 3811cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // max_object_location_ is equal to X, we can place the object at location X 3821cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // regardless of its size. 3831cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T min_object_location_; 3841cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T max_object_location_; 3851cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3861cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli friend class PoolManager<T>; 3871cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli}; 3881cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3891cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 3901cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouvelitemplate <typename T> 3911cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveliclass PoolManager { 3921cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli public: 3931cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli PoolManager(int header_size, int alignment, int buffer_alignment) 3941cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli : header_size_(header_size), 3951cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli alignment_(alignment), 3961cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli buffer_alignment_(buffer_alignment), 3971cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli checkpoint_(std::numeric_limits<T>::max()), 3981cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli max_pool_size_(0), 3991cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli monitor_(0) {} 4001cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4011cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli ~PoolManager(); 4021cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4031cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Check if we will need to emit the pool at location 'pc', when planning to 4041cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // generate a certain number of bytes. This optionally takes a 4051cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // ForwardReference we are about to generate, in which case the size of the 4061cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // reference must be included in 'num_bytes'. 4071cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli bool MustEmit(T pc, 4081cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int num_bytes = 0, 4091cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli ForwardReference<T>* reference = NULL, 4108b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli LocationBase<T>* object = NULL) const; 4111cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4121cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli enum EmitOption { kBranchRequired, kNoBranchRequired }; 4131cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4141cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Emit the pool at location 'pc', using 'masm' as the macroassembler. 4151cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The branch over the header can be optionally omitted using 'option'. 4161cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Returns the new PC after pool emission. 4171cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // This expects a number of bytes that are about to be emitted, to be taken 4181cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // into account in heuristics for pool object emission. 4191cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // This also optionally takes a forward reference and an object as 4201cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // parameters, to be used in the case where emission of the pool is triggered 4211cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // by adding a new reference to the pool that does not fit. The pool manager 4221cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // will need this information in order to apply its heuristics correctly. 4231cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T Emit(MacroAssemblerInterface* masm, 4241cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T pc, 4251cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int num_bytes = 0, 4261cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli ForwardReference<T>* new_reference = NULL, 4278b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli LocationBase<T>* new_object = NULL, 4281cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli EmitOption option = kBranchRequired); 4291cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4301cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Add 'reference' to 'object'. Should not be preceded by a call to MustEmit() 4311cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // that returned true, unless Emit() has been successfully afterwards. 4321cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void AddObjectReference(const ForwardReference<T>* reference, 4338b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli LocationBase<T>* object); 4341cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4358b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // This is to notify the pool that a LocationBase has been bound to a location 4361cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // and does not need to be tracked anymore. 4371cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // This will happen, for example, for Labels, which are manually bound by the 4381cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // user. 4391cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // This can potentially add some padding bytes in order to meet the object 4401cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // requirements, and will return the new location. 4418b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli T Bind(MacroAssemblerInterface* masm, LocationBase<T>* object, T location); 4421cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4431cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Functions for blocking and releasing the pools. 4441cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void Block() { monitor_++; } 4451cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void Release(T pc); 4461cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli bool IsBlocked() const { return monitor_ != 0; } 4471cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4481cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli private: 4491cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli typedef typename std::vector<PoolObject<T> >::iterator objects_iter; 4501cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli typedef 4511cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli typename std::vector<PoolObject<T> >::const_iterator const_objects_iter; 4521cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4538b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli PoolObject<T>* GetObjectIfTracked(LocationBase<T>* label) { 4541cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli return const_cast<PoolObject<T>*>( 4551cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli static_cast<const PoolManager<T>*>(this)->GetObjectIfTracked(label)); 4561cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 4571cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4588b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli const PoolObject<T>* GetObjectIfTracked(LocationBase<T>* label) const { 4591cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli for (const_objects_iter iter = objects_.begin(); iter != objects_.end(); 4601cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli ++iter) { 4611cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli const PoolObject<T>& current = *iter; 4621cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli if (current.label_base_ == label) return ¤t; 4631cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 4641cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli return NULL; 4651cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli } 4661cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4671cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Helper function for calculating the checkpoint. 4681cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli enum SortOption { kSortRequired, kNoSortRequired }; 4691cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void RecalculateCheckpoint(SortOption sort_option = kSortRequired); 4701cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4711cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Comparison function for using std::sort() on objects_. PoolObject A is 4721cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // ordered before PoolObject B when A should be emitted before B. The 4731cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // comparison depends on the max_location_, size_, alignment_ and 4741cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // min_location_. 4751cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli static bool PoolObjectLessThan(const PoolObject<T>& a, 4761cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli const PoolObject<T>& b); 4771cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4781cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Helper function used in the checkpoint calculation. 'checkpoint' is the 4791cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // current checkpoint, which is modified to take 'object' into account. The 4801cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // new checkpoint is returned. 4811cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli static T UpdateCheckpointForObject(T checkpoint, const PoolObject<T>* object); 4821cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4831cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Helper function to add a new object into a sorted objects_ array. 4841cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void Insert(const PoolObject<T>& new_object); 4851cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4861cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Helper functions to remove an object from objects_ and delete the 4878b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli // corresponding LocationBase object, if necessary. This will be called 4881cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // either after placing the object, or when Bind() is called. 4891cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void RemoveAndDelete(PoolObject<T>* object); 4901cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli objects_iter RemoveAndDelete(objects_iter iter); 4911cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 4921cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Helper function to check if we should skip emitting an object. 4931cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli bool ShouldSkipObject(PoolObject<T>* pool_object, 4941cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T pc, 4951cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int num_bytes, 4961cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli ForwardReference<T>* new_reference, 4978b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli LocationBase<T>* new_object, 4981cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli PoolObject<T>* existing_object) const; 4991cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5001cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Used only for debugging. 5011cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli void DumpCurrentState(T pc) const; 5021cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5031cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Methods used for testing only, via the test friend classes. 5041cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli bool PoolIsEmptyForTest() const { return objects_.empty(); } 5051cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T GetCheckpointForTest() const { return checkpoint_; } 5061cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int GetPoolSizeForTest() const; 5071cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5081cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The objects we are tracking references to. The objects_ vector is sorted 5091cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // at all times between calls to the public members of the PoolManager. It 5101cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // is sorted every time we add, delete or update a PoolObject. 5111cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // TODO: Consider a more efficient data structure here, to allow us to delete 5121cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // elements as we emit them. 5131cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli std::vector<PoolObject<T> > objects_; 5141cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5151cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Objects to be deleted on pool destruction. 5168b57c86886020cf0a5331823be4789ee558764e2Georgia Kouveli std::vector<LocationBase<T>*> delete_on_destruction_; 5171cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5181cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The header_size_ and alignment_ values are hardcoded for each instance of 5191cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // PoolManager. The PoolManager does not know how to emit the header, and 5201cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // relies on the EmitPoolHeader and EndPool methods of the 5211cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // MacroAssemblerInterface for that. It will also emit padding if necessary, 5221cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // both for the header and at the end of the pool, according to alignment_, 5231cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // and using the EmitNopBytes and EmitPaddingBytes method of the 5241cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // MacroAssemblerInterface. 5251cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5261cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The size of the header, in bytes. 5271cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int header_size_; 5281cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The alignment of the header - must be a power of two. 5291cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int alignment_; 5301cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The alignment of the buffer - we cannot guarantee any object alignment 5311cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // larger than this alignment. When a buffer is grown, this alignment has 5321cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // to be guaranteed. 5331cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // TODO: Consider extending this to describe the guaranteed alignment as the 5341cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // modulo of a known number. 5351cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int buffer_alignment_; 5361cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5371cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // The current checkpoint. This is the latest location at which the pool 5381cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // *must* be emitted. This should not be visible outside the pool manager 5391cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // and should only be updated in RecalculateCheckpoint. 5401cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T checkpoint_; 5411cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5421cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Maximum size of the pool, assuming we need the maximum possible padding 5431cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // for each object and for the header. It is only updated in 5441cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // RecalculateCheckpoint. 5451cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli T max_pool_size_; 5461cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5471cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli // Indicates whether the emission of this pool is blocked. 5481cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli int monitor_; 5491cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5501cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli friend class vixl::TestPoolManager; 5511cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli}; 5521cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5531cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5541cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli} // namespace vixl 5551cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli 5561cb7144de5478fd860f6d64fad4207730d2e139bGeorgia Kouveli#endif // VIXL_POOL_MANAGER_H_ 557