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 &current;
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