1b8021494Sopenharmony_ci// Copyright 2017, VIXL authors
2b8021494Sopenharmony_ci// All rights reserved.
3b8021494Sopenharmony_ci//
4b8021494Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
5b8021494Sopenharmony_ci// modification, are permitted provided that the following conditions are met:
6b8021494Sopenharmony_ci//
7b8021494Sopenharmony_ci//   * Redistributions of source code must retain the above copyright notice,
8b8021494Sopenharmony_ci//     this list of conditions and the following disclaimer.
9b8021494Sopenharmony_ci//   * Redistributions in binary form must reproduce the above copyright notice,
10b8021494Sopenharmony_ci//     this list of conditions and the following disclaimer in the documentation
11b8021494Sopenharmony_ci//     and/or other materials provided with the distribution.
12b8021494Sopenharmony_ci//   * Neither the name of ARM Limited nor the names of its contributors may be
13b8021494Sopenharmony_ci//     used to endorse or promote products derived from this software without
14b8021494Sopenharmony_ci//     specific prior written permission.
15b8021494Sopenharmony_ci//
16b8021494Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17b8021494Sopenharmony_ci// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18b8021494Sopenharmony_ci// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19b8021494Sopenharmony_ci// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20b8021494Sopenharmony_ci// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21b8021494Sopenharmony_ci// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22b8021494Sopenharmony_ci// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23b8021494Sopenharmony_ci// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24b8021494Sopenharmony_ci// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25b8021494Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b8021494Sopenharmony_ci
27b8021494Sopenharmony_ci#ifndef VIXL_AARCH32_LABEL_AARCH32_H_
28b8021494Sopenharmony_ci#define VIXL_AARCH32_LABEL_AARCH32_H_
29b8021494Sopenharmony_ci
30b8021494Sopenharmony_ciextern "C" {
31b8021494Sopenharmony_ci#include <stdint.h>
32b8021494Sopenharmony_ci}
33b8021494Sopenharmony_ci
34b8021494Sopenharmony_ci#include <algorithm>
35b8021494Sopenharmony_ci#include <cstddef>
36b8021494Sopenharmony_ci#include <iomanip>
37b8021494Sopenharmony_ci#include <list>
38b8021494Sopenharmony_ci
39b8021494Sopenharmony_ci#include "invalset-vixl.h"
40b8021494Sopenharmony_ci#include "pool-manager.h"
41b8021494Sopenharmony_ci#include "utils-vixl.h"
42b8021494Sopenharmony_ci
43b8021494Sopenharmony_ci#include "constants-aarch32.h"
44b8021494Sopenharmony_ci#include "instructions-aarch32.h"
45b8021494Sopenharmony_ci
46b8021494Sopenharmony_cinamespace vixl {
47b8021494Sopenharmony_ci
48b8021494Sopenharmony_cinamespace aarch32 {
49b8021494Sopenharmony_ci
50b8021494Sopenharmony_ciclass MacroAssembler;
51b8021494Sopenharmony_ci
52b8021494Sopenharmony_ciclass Location : public LocationBase<int32_t> {
53b8021494Sopenharmony_ci  friend class Assembler;
54b8021494Sopenharmony_ci  friend class MacroAssembler;
55b8021494Sopenharmony_ci
56b8021494Sopenharmony_ci public:
57b8021494Sopenharmony_ci  // Unbound location that can be used with the assembler bind() method and
58b8021494Sopenharmony_ci  // with the assembler methods for generating instructions, but will never
59b8021494Sopenharmony_ci  // be handled by the pool manager.
60b8021494Sopenharmony_ci#ifndef PANDA_BUILD
61b8021494Sopenharmony_ci  Location()
62b8021494Sopenharmony_ci      : LocationBase<int32_t>(kRawLocation, 1 /* placeholder size*/),
63b8021494Sopenharmony_ci        referenced_(false) {}
64b8021494Sopenharmony_ci#else
65b8021494Sopenharmony_ci  Location() = delete;
66b8021494Sopenharmony_ci  Location(AllocatorWrapper allocator)
67b8021494Sopenharmony_ci    : LocationBase<int32_t>(kRawLocation, 1 /* dummy size*/),
68b8021494Sopenharmony_ci      referenced_(false),
69b8021494Sopenharmony_ci      forward_(allocator) {}
70b8021494Sopenharmony_ci#endif
71b8021494Sopenharmony_ci
72b8021494Sopenharmony_ci  typedef int32_t Offset;
73b8021494Sopenharmony_ci
74b8021494Sopenharmony_ci  ~Location() VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION {
75b8021494Sopenharmony_ci    // Codegen may create empty labels
76b8021494Sopenharmony_ci#if defined(VIXL_DEBUG) && !defined(PANDA_BUILD)
77b8021494Sopenharmony_ci    if (IsReferenced() && !IsBound()) {
78b8021494Sopenharmony_ci      VIXL_ABORT_WITH_MSG("Location, label or literal used but not bound.\n");
79b8021494Sopenharmony_ci    }
80b8021494Sopenharmony_ci#endif
81b8021494Sopenharmony_ci  }
82b8021494Sopenharmony_ci
83b8021494Sopenharmony_ci  bool IsReferenced() const { return referenced_; }
84b8021494Sopenharmony_ci
85b8021494Sopenharmony_ci private:
86b8021494Sopenharmony_ci  class EmitOperator {
87b8021494Sopenharmony_ci   public:
88b8021494Sopenharmony_ci    explicit EmitOperator(InstructionSet isa) : isa_(isa) {
89b8021494Sopenharmony_ci#if defined(VIXL_INCLUDE_TARGET_A32_ONLY)
90b8021494Sopenharmony_ci      USE(isa_);
91b8021494Sopenharmony_ci      VIXL_ASSERT(isa == A32);
92b8021494Sopenharmony_ci#elif defined(VIXL_INCLUDE_TARGET_T32_ONLY)
93b8021494Sopenharmony_ci      USE(isa_);
94b8021494Sopenharmony_ci      VIXL_ASSERT(isa == T32);
95b8021494Sopenharmony_ci#endif
96b8021494Sopenharmony_ci    }
97b8021494Sopenharmony_ci    virtual ~EmitOperator() {}
98b8021494Sopenharmony_ci    virtual uint32_t Encode(uint32_t /*instr*/,
99b8021494Sopenharmony_ci                            Location::Offset /*pc*/,
100b8021494Sopenharmony_ci                            const Location* /*label*/) const {
101b8021494Sopenharmony_ci      return 0;
102b8021494Sopenharmony_ci    }
103b8021494Sopenharmony_ci#if defined(VIXL_INCLUDE_TARGET_A32_ONLY)
104b8021494Sopenharmony_ci    bool IsUsingT32() const { return false; }
105b8021494Sopenharmony_ci#elif defined(VIXL_INCLUDE_TARGET_T32_ONLY)
106b8021494Sopenharmony_ci    bool IsUsingT32() const { return true; }
107b8021494Sopenharmony_ci#else
108b8021494Sopenharmony_ci    bool IsUsingT32() const { return isa_ == T32; }
109b8021494Sopenharmony_ci#endif
110b8021494Sopenharmony_ci
111b8021494Sopenharmony_ci   private:
112b8021494Sopenharmony_ci    InstructionSet isa_;
113b8021494Sopenharmony_ci  };
114b8021494Sopenharmony_ci
115b8021494Sopenharmony_ci protected:
116b8021494Sopenharmony_ci  class ForwardRef : public ForwardReference<int32_t> {
117b8021494Sopenharmony_ci   public:
118b8021494Sopenharmony_ci    // Default constructor for InvalSet.
119b8021494Sopenharmony_ci    ForwardRef() : ForwardReference<int32_t>(0, 0, 0, 0, 1), op_(NULL) {}
120b8021494Sopenharmony_ci
121b8021494Sopenharmony_ci    ForwardRef(const Location::EmitOperator* op,
122b8021494Sopenharmony_ci               int32_t location,
123b8021494Sopenharmony_ci               int size,
124b8021494Sopenharmony_ci               int32_t min_object_location,
125b8021494Sopenharmony_ci               int32_t max_object_location,
126b8021494Sopenharmony_ci               int object_alignment = 1)
127b8021494Sopenharmony_ci        : ForwardReference<int32_t>(location,
128b8021494Sopenharmony_ci                                    size,
129b8021494Sopenharmony_ci                                    min_object_location,
130b8021494Sopenharmony_ci                                    max_object_location,
131b8021494Sopenharmony_ci                                    object_alignment),
132b8021494Sopenharmony_ci          op_(op) {}
133b8021494Sopenharmony_ci
134b8021494Sopenharmony_ci    const Location::EmitOperator* op() const { return op_; }
135b8021494Sopenharmony_ci
136b8021494Sopenharmony_ci    // We must provide comparison operators to work with InvalSet.
137b8021494Sopenharmony_ci    bool operator==(const ForwardRef& other) const {
138b8021494Sopenharmony_ci      return GetLocation() == other.GetLocation();
139b8021494Sopenharmony_ci    }
140b8021494Sopenharmony_ci    bool operator<(const ForwardRef& other) const {
141b8021494Sopenharmony_ci      return GetLocation() < other.GetLocation();
142b8021494Sopenharmony_ci    }
143b8021494Sopenharmony_ci    bool operator<=(const ForwardRef& other) const {
144b8021494Sopenharmony_ci      return GetLocation() <= other.GetLocation();
145b8021494Sopenharmony_ci    }
146b8021494Sopenharmony_ci    bool operator>(const ForwardRef& other) const {
147b8021494Sopenharmony_ci      return GetLocation() > other.GetLocation();
148b8021494Sopenharmony_ci    }
149b8021494Sopenharmony_ci
150b8021494Sopenharmony_ci   private:
151b8021494Sopenharmony_ci    const Location::EmitOperator* op_;
152b8021494Sopenharmony_ci  };
153b8021494Sopenharmony_ci
154b8021494Sopenharmony_ci  static const int kNPreallocatedElements = 4;
155b8021494Sopenharmony_ci  // The following parameters will not affect ForwardRefList in practice, as we
156b8021494Sopenharmony_ci  // resolve all references at once and clear the list, so we do not need to
157b8021494Sopenharmony_ci  // remove individual elements by invalidating them.
158b8021494Sopenharmony_ci  static const int32_t kInvalidLinkKey = INT32_MAX;
159b8021494Sopenharmony_ci  static const size_t kReclaimFrom = 512;
160b8021494Sopenharmony_ci  static const size_t kReclaimFactor = 2;
161b8021494Sopenharmony_ci
162b8021494Sopenharmony_ci  typedef InvalSet<ForwardRef,
163b8021494Sopenharmony_ci                   kNPreallocatedElements,
164b8021494Sopenharmony_ci                   int32_t,
165b8021494Sopenharmony_ci                   kInvalidLinkKey,
166b8021494Sopenharmony_ci                   kReclaimFrom,
167b8021494Sopenharmony_ci                   kReclaimFactor>
168b8021494Sopenharmony_ci      ForwardRefListBase;
169b8021494Sopenharmony_ci  typedef InvalSetIterator<ForwardRefListBase> ForwardRefListIteratorBase;
170b8021494Sopenharmony_ci
171b8021494Sopenharmony_ci  class ForwardRefList : public ForwardRefListBase {
172b8021494Sopenharmony_ci   public:
173b8021494Sopenharmony_ci#ifndef PANDA_BUILD
174b8021494Sopenharmony_ci    ForwardRefList() : ForwardRefListBase() {}
175b8021494Sopenharmony_ci#else
176b8021494Sopenharmony_ci    ForwardRefList() = delete;
177b8021494Sopenharmony_ci    ForwardRefList(AllocatorWrapper allocator) : ForwardRefListBase(allocator) {}
178b8021494Sopenharmony_ci#endif
179b8021494Sopenharmony_ci    using ForwardRefListBase::Back;
180b8021494Sopenharmony_ci    using ForwardRefListBase::Front;
181b8021494Sopenharmony_ci  };
182b8021494Sopenharmony_ci
183b8021494Sopenharmony_ci  class ForwardRefListIterator : public ForwardRefListIteratorBase {
184b8021494Sopenharmony_ci   public:
185b8021494Sopenharmony_ci    explicit ForwardRefListIterator(Location* location)
186b8021494Sopenharmony_ci        : ForwardRefListIteratorBase(&location->forward_) {}
187b8021494Sopenharmony_ci
188b8021494Sopenharmony_ci    // TODO: Remove these and use the STL-like interface instead. We'll need a
189b8021494Sopenharmony_ci    // const_iterator implemented for this.
190b8021494Sopenharmony_ci    using ForwardRefListIteratorBase::Advance;
191b8021494Sopenharmony_ci    using ForwardRefListIteratorBase::Current;
192b8021494Sopenharmony_ci  };
193b8021494Sopenharmony_ci
194b8021494Sopenharmony_ci  // For InvalSet::GetKey() and InvalSet::SetKey().
195b8021494Sopenharmony_ci  friend class InvalSet<ForwardRef,
196b8021494Sopenharmony_ci                        kNPreallocatedElements,
197b8021494Sopenharmony_ci                        int32_t,
198b8021494Sopenharmony_ci                        kInvalidLinkKey,
199b8021494Sopenharmony_ci                        kReclaimFrom,
200b8021494Sopenharmony_ci                        kReclaimFactor>;
201b8021494Sopenharmony_ci
202b8021494Sopenharmony_ci private:
203b8021494Sopenharmony_ci  virtual void ResolveReferences(internal::AssemblerBase* assembler)
204b8021494Sopenharmony_ci      VIXL_OVERRIDE;
205b8021494Sopenharmony_ci
206b8021494Sopenharmony_ci  void SetReferenced() { referenced_ = true; }
207b8021494Sopenharmony_ci
208b8021494Sopenharmony_ci  bool HasForwardReferences() const { return !forward_.empty(); }
209b8021494Sopenharmony_ci
210b8021494Sopenharmony_ci  ForwardRef GetLastForwardReference() const {
211b8021494Sopenharmony_ci    VIXL_ASSERT(HasForwardReferences());
212b8021494Sopenharmony_ci    return forward_.Back();
213b8021494Sopenharmony_ci  }
214b8021494Sopenharmony_ci
215b8021494Sopenharmony_ci  // Add forward reference to this object. Called from the assembler.
216b8021494Sopenharmony_ci  void AddForwardRef(int32_t instr_location,
217b8021494Sopenharmony_ci                     const EmitOperator& op,
218b8021494Sopenharmony_ci                     const ReferenceInfo* info);
219b8021494Sopenharmony_ci
220b8021494Sopenharmony_ci  // Check if we need to add padding when binding this object, in order to
221b8021494Sopenharmony_ci  // meet the minimum location requirement.
222b8021494Sopenharmony_ci  bool Needs16BitPadding(int location) const;
223b8021494Sopenharmony_ci
224b8021494Sopenharmony_ci  void EncodeLocationFor(internal::AssemblerBase* assembler,
225b8021494Sopenharmony_ci                         int32_t from,
226b8021494Sopenharmony_ci                         const Location::EmitOperator* encoder);
227b8021494Sopenharmony_ci
228b8021494Sopenharmony_ci  // True if the label has been used at least once.
229b8021494Sopenharmony_ci  bool referenced_;
230b8021494Sopenharmony_ci
231b8021494Sopenharmony_ci protected:
232b8021494Sopenharmony_ci  // Types passed to LocationBase. Must be distinct for unbound Locations (not
233b8021494Sopenharmony_ci  // relevant for bound locations, as they don't have a corresponding
234b8021494Sopenharmony_ci  // PoolObject).
235b8021494Sopenharmony_ci  static const int kRawLocation = 0;  // Will not be used by the pool manager.
236b8021494Sopenharmony_ci  static const int kVeneerType = 1;
237b8021494Sopenharmony_ci  static const int kLiteralType = 2;
238b8021494Sopenharmony_ci
239b8021494Sopenharmony_ci  // Contains the references to the unbound label
240b8021494Sopenharmony_ci  ForwardRefList forward_;
241b8021494Sopenharmony_ci
242b8021494Sopenharmony_ci#ifndef PANDA_BUILD
243b8021494Sopenharmony_ci  // To be used only by derived classes.
244b8021494Sopenharmony_ci  Location(uint32_t type, int size, int alignment)
245b8021494Sopenharmony_ci      : LocationBase<int32_t>(type, size, alignment), referenced_(false) {}
246b8021494Sopenharmony_ci#else
247b8021494Sopenharmony_ci  Location(AllocatorWrapper allocator, uint32_t type, int size, int alignment)
248b8021494Sopenharmony_ci      : LocationBase<int32_t>(type, size, alignment), referenced_(false), forward_(allocator){}
249b8021494Sopenharmony_ci#endif
250b8021494Sopenharmony_ci
251b8021494Sopenharmony_ci#ifndef PANDA_BUILD
252b8021494Sopenharmony_ci  // To be used only by derived classes.
253b8021494Sopenharmony_ci  explicit Location(Offset location)
254b8021494Sopenharmony_ci      : LocationBase<int32_t>(location), referenced_(false) {}
255b8021494Sopenharmony_ci#else
256b8021494Sopenharmony_ci  explicit Location(Offset location) = delete;
257b8021494Sopenharmony_ci  Location(AllocatorWrapper allocator, Offset location)
258b8021494Sopenharmony_ci    : LocationBase<int32_t>(location), referenced_(false), forward_(allocator) {}
259b8021494Sopenharmony_ci#endif
260b8021494Sopenharmony_ci
261b8021494Sopenharmony_ci  virtual int GetMaxAlignment() const VIXL_OVERRIDE;
262b8021494Sopenharmony_ci  virtual int GetMinLocation() const VIXL_OVERRIDE;
263b8021494Sopenharmony_ci
264b8021494Sopenharmony_ci private:
265b8021494Sopenharmony_ci  // Included to make the class concrete, however should never be called.
266b8021494Sopenharmony_ci  virtual void EmitPoolObject(MacroAssemblerInterface* masm) VIXL_OVERRIDE {
267b8021494Sopenharmony_ci    USE(masm);
268b8021494Sopenharmony_ci    VIXL_UNREACHABLE();
269b8021494Sopenharmony_ci  }
270b8021494Sopenharmony_ci};
271b8021494Sopenharmony_ci
272b8021494Sopenharmony_ciclass Label : public Location {
273b8021494Sopenharmony_ci  static const int kVeneerSize = 4;
274b8021494Sopenharmony_ci  // Use an alignment of 1 for all architectures. Even though we can bind an
275b8021494Sopenharmony_ci  // unused label, because of the way the MacroAssembler works we can always be
276b8021494Sopenharmony_ci  // sure to have the correct buffer alignment for the instruction set we are
277b8021494Sopenharmony_ci  // using, so we do not need to enforce additional alignment requirements
278b8021494Sopenharmony_ci  // here.
279b8021494Sopenharmony_ci  // TODO: Consider modifying the interface of the pool manager to pass an
280b8021494Sopenharmony_ci  // optional additional alignment to Bind() in order to handle cases where the
281b8021494Sopenharmony_ci  // buffer could be unaligned.
282b8021494Sopenharmony_ci  static const int kVeneerAlignment = 1;
283b8021494Sopenharmony_ci
284b8021494Sopenharmony_ci public:
285b8021494Sopenharmony_ci#ifndef PANDA_BUILD
286b8021494Sopenharmony_ci  Label() : Location(kVeneerType, kVeneerSize, kVeneerAlignment) {}
287b8021494Sopenharmony_ci  explicit Label(Offset location) : Location(location) {}
288b8021494Sopenharmony_ci#else
289b8021494Sopenharmony_ci  Label() = delete;
290b8021494Sopenharmony_ci  Label(AllocatorWrapper allocator) : Location(allocator, kVeneerType, kVeneerSize, kVeneerAlignment) {}
291b8021494Sopenharmony_ci  explicit Label(Offset location) = delete;
292b8021494Sopenharmony_ci  explicit Label(AllocatorWrapper allocator, Offset location) : Location(allocator, location) {}
293b8021494Sopenharmony_ci#endif
294b8021494Sopenharmony_ci
295b8021494Sopenharmony_ci private:
296b8021494Sopenharmony_ci  virtual bool ShouldBeDeletedOnPlacementByPoolManager() const VIXL_OVERRIDE {
297b8021494Sopenharmony_ci    return false;
298b8021494Sopenharmony_ci  }
299b8021494Sopenharmony_ci  virtual bool ShouldDeletePoolObjectOnPlacement() const VIXL_OVERRIDE {
300b8021494Sopenharmony_ci    return false;
301b8021494Sopenharmony_ci  }
302b8021494Sopenharmony_ci
303b8021494Sopenharmony_ci  virtual void UpdatePoolObject(PoolObject<int32_t>* object) VIXL_OVERRIDE;
304b8021494Sopenharmony_ci  virtual void EmitPoolObject(MacroAssemblerInterface* masm) VIXL_OVERRIDE;
305b8021494Sopenharmony_ci
306b8021494Sopenharmony_ci  virtual bool UsePoolObjectEmissionMargin() const VIXL_OVERRIDE {
307b8021494Sopenharmony_ci    return true;
308b8021494Sopenharmony_ci  }
309b8021494Sopenharmony_ci  virtual int32_t GetPoolObjectEmissionMargin() const VIXL_OVERRIDE {
310b8021494Sopenharmony_ci    VIXL_ASSERT(UsePoolObjectEmissionMargin() == true);
311b8021494Sopenharmony_ci    return 1 * KBytes;
312b8021494Sopenharmony_ci  }
313b8021494Sopenharmony_ci};
314b8021494Sopenharmony_ci
315b8021494Sopenharmony_ciclass RawLiteral : public Location {
316b8021494Sopenharmony_ci  // Some load instructions require alignment to 4 bytes. Since we do
317b8021494Sopenharmony_ci  // not know what instructions will reference a literal after we place
318b8021494Sopenharmony_ci  // it, we enforce a 4 byte alignment for literals that are 4 bytes or
319b8021494Sopenharmony_ci  // larger.
320b8021494Sopenharmony_ci  static const int kLiteralAlignment = 4;
321b8021494Sopenharmony_ci
322b8021494Sopenharmony_ci public:
323b8021494Sopenharmony_ci  enum PlacementPolicy { kPlacedWhenUsed, kManuallyPlaced };
324b8021494Sopenharmony_ci
325b8021494Sopenharmony_ci  enum DeletionPolicy {
326b8021494Sopenharmony_ci    kDeletedOnPlacementByPool,
327b8021494Sopenharmony_ci    kDeletedOnPoolDestruction,
328b8021494Sopenharmony_ci    kManuallyDeleted
329b8021494Sopenharmony_ci  };
330b8021494Sopenharmony_ci
331b8021494Sopenharmony_ci#ifndef PANDA_BUILD
332b8021494Sopenharmony_ci  RawLiteral(const void* addr,
333b8021494Sopenharmony_ci             int size,
334b8021494Sopenharmony_ci             PlacementPolicy placement_policy = kPlacedWhenUsed,
335b8021494Sopenharmony_ci             DeletionPolicy deletion_policy = kManuallyDeleted)
336b8021494Sopenharmony_ci      : Location(kLiteralType,
337b8021494Sopenharmony_ci                 size,
338b8021494Sopenharmony_ci                 (size < kLiteralAlignment) ? size : kLiteralAlignment),
339b8021494Sopenharmony_ci        addr_(addr),
340b8021494Sopenharmony_ci        manually_placed_(placement_policy == kManuallyPlaced),
341b8021494Sopenharmony_ci        deletion_policy_(deletion_policy) {
342b8021494Sopenharmony_ci    // We can't have manually placed literals that are not manually deleted.
343b8021494Sopenharmony_ci    VIXL_ASSERT(!IsManuallyPlaced() ||
344b8021494Sopenharmony_ci                (GetDeletionPolicy() == kManuallyDeleted));
345b8021494Sopenharmony_ci  }
346b8021494Sopenharmony_ci  RawLiteral(const void* addr, int size, DeletionPolicy deletion_policy)
347b8021494Sopenharmony_ci      : Location(kLiteralType,
348b8021494Sopenharmony_ci                 size,
349b8021494Sopenharmony_ci                 (size < kLiteralAlignment) ? size : kLiteralAlignment),
350b8021494Sopenharmony_ci        addr_(addr),
351b8021494Sopenharmony_ci        manually_placed_(false),
352b8021494Sopenharmony_ci        deletion_policy_(deletion_policy) {}
353b8021494Sopenharmony_ci#else
354b8021494Sopenharmony_ciRawLiteral(const void* addr,
355b8021494Sopenharmony_ci           int size,
356b8021494Sopenharmony_ci           PlacementPolicy placement_policy = kPlacedWhenUsed,
357b8021494Sopenharmony_ci           DeletionPolicy deletion_policy = kManuallyDeleted) = delete;
358b8021494Sopenharmony_ciRawLiteral(AllocatorWrapper allocator, const void* addr,
359b8021494Sopenharmony_ci           int size,
360b8021494Sopenharmony_ci           PlacementPolicy placement_policy = kPlacedWhenUsed,
361b8021494Sopenharmony_ci           DeletionPolicy deletion_policy = kManuallyDeleted)
362b8021494Sopenharmony_ci    : Location(allocator, kLiteralType,
363b8021494Sopenharmony_ci               size,
364b8021494Sopenharmony_ci               (size < kLiteralAlignment) ? size : kLiteralAlignment),
365b8021494Sopenharmony_ci      addr_(addr),
366b8021494Sopenharmony_ci      manually_placed_(placement_policy == kManuallyPlaced),
367b8021494Sopenharmony_ci      deletion_policy_(deletion_policy) {
368b8021494Sopenharmony_ci  // We can't have manually placed literals that are not manually deleted.
369b8021494Sopenharmony_ci  VIXL_ASSERT(!IsManuallyPlaced() ||
370b8021494Sopenharmony_ci              (GetDeletionPolicy() == kManuallyDeleted));
371b8021494Sopenharmony_ci}
372b8021494Sopenharmony_ciRawLiteral(const void* addr, int size, DeletionPolicy deletion_policy) = delete;
373b8021494Sopenharmony_ci
374b8021494Sopenharmony_ciRawLiteral(AllocatorWrapper allocator, const void* addr, int size, DeletionPolicy deletion_policy)
375b8021494Sopenharmony_ci    : Location(allocator, kLiteralType,
376b8021494Sopenharmony_ci               size,
377b8021494Sopenharmony_ci               (size < kLiteralAlignment) ? size : kLiteralAlignment),
378b8021494Sopenharmony_ci      addr_(addr),
379b8021494Sopenharmony_ci      manually_placed_(false),
380b8021494Sopenharmony_ci      deletion_policy_(deletion_policy) {}
381b8021494Sopenharmony_ci
382b8021494Sopenharmony_ci#endif
383b8021494Sopenharmony_ci  const void* GetDataAddress() const { return addr_; }
384b8021494Sopenharmony_ci  int GetSize() const { return GetPoolObjectSizeInBytes(); }
385b8021494Sopenharmony_ci
386b8021494Sopenharmony_ci  bool IsManuallyPlaced() const { return manually_placed_; }
387b8021494Sopenharmony_ci
388b8021494Sopenharmony_ci private:
389b8021494Sopenharmony_ci  DeletionPolicy GetDeletionPolicy() const { return deletion_policy_; }
390b8021494Sopenharmony_ci
391b8021494Sopenharmony_ci  virtual bool ShouldBeDeletedOnPlacementByPoolManager() const VIXL_OVERRIDE {
392b8021494Sopenharmony_ci    return GetDeletionPolicy() == kDeletedOnPlacementByPool;
393b8021494Sopenharmony_ci  }
394b8021494Sopenharmony_ci  virtual bool ShouldBeDeletedOnPoolManagerDestruction() const VIXL_OVERRIDE {
395b8021494Sopenharmony_ci    return GetDeletionPolicy() == kDeletedOnPoolDestruction;
396b8021494Sopenharmony_ci  }
397b8021494Sopenharmony_ci  virtual void EmitPoolObject(MacroAssemblerInterface* masm) VIXL_OVERRIDE;
398b8021494Sopenharmony_ci
399b8021494Sopenharmony_ci  // Data address before it's moved into the code buffer.
400b8021494Sopenharmony_ci  const void* const addr_;
401b8021494Sopenharmony_ci  // When this flag is true, the label will be placed manually.
402b8021494Sopenharmony_ci  bool manually_placed_;
403b8021494Sopenharmony_ci  // When is the literal to be removed from the memory
404b8021494Sopenharmony_ci  // Can be delete'd when:
405b8021494Sopenharmony_ci  //   moved into the code buffer: kDeletedOnPlacementByPool
406b8021494Sopenharmony_ci  //   the pool is delete'd: kDeletedOnPoolDestruction
407b8021494Sopenharmony_ci  //   or left to the application: kManuallyDeleted.
408b8021494Sopenharmony_ci  DeletionPolicy deletion_policy_;
409b8021494Sopenharmony_ci
410b8021494Sopenharmony_ci  friend class MacroAssembler;
411b8021494Sopenharmony_ci};
412b8021494Sopenharmony_ci
413b8021494Sopenharmony_citemplate <typename T>
414b8021494Sopenharmony_ciclass Literal : public RawLiteral {
415b8021494Sopenharmony_ci public:
416b8021494Sopenharmony_ci#ifndef PANDA_BUILD
417b8021494Sopenharmony_ci  explicit Literal(const T& value,
418b8021494Sopenharmony_ci                   PlacementPolicy placement_policy = kPlacedWhenUsed,
419b8021494Sopenharmony_ci                   DeletionPolicy deletion_policy = kManuallyDeleted)
420b8021494Sopenharmony_ci      : RawLiteral(&value_, sizeof(T), placement_policy, deletion_policy),
421b8021494Sopenharmony_ci        value_(value) {}
422b8021494Sopenharmony_ci  explicit Literal(const T& value, DeletionPolicy deletion_policy)
423b8021494Sopenharmony_ci      : RawLiteral(&value_, sizeof(T), deletion_policy), value_(value) {}
424b8021494Sopenharmony_ci#else
425b8021494Sopenharmony_ciexplicit Literal(const T& ,
426b8021494Sopenharmony_ci                 PlacementPolicy placement_policy = kPlacedWhenUsed,
427b8021494Sopenharmony_ci                 DeletionPolicy deletion_policy = kManuallyDeleted) = delete;
428b8021494Sopenharmony_ciexplicit Literal(const T& value, DeletionPolicy deletion_policy) = delete;
429b8021494Sopenharmony_ciexplicit Literal(AllocatorWrapper allocator, const T& value,
430b8021494Sopenharmony_ci                 PlacementPolicy placement_policy = kPlacedWhenUsed,
431b8021494Sopenharmony_ci                 DeletionPolicy deletion_policy = kManuallyDeleted)
432b8021494Sopenharmony_ci    : RawLiteral(allocator, &value_, sizeof(T), placement_policy, deletion_policy),
433b8021494Sopenharmony_ci      value_(value) {}
434b8021494Sopenharmony_ciexplicit Literal(AllocatorWrapper allocator, const T& value, DeletionPolicy deletion_policy)
435b8021494Sopenharmony_ci    : RawLiteral(allocator, &value_, sizeof(T), deletion_policy), value_(value) {}
436b8021494Sopenharmony_ci
437b8021494Sopenharmony_ci#endif
438b8021494Sopenharmony_ci  void UpdateValue(const T& value, CodeBuffer* buffer) {
439b8021494Sopenharmony_ci    value_ = value;
440b8021494Sopenharmony_ci    if (IsBound()) {
441b8021494Sopenharmony_ci      buffer->UpdateData(GetLocation(), GetDataAddress(), GetSize());
442b8021494Sopenharmony_ci    }
443b8021494Sopenharmony_ci  }
444b8021494Sopenharmony_ci
445b8021494Sopenharmony_ci private:
446b8021494Sopenharmony_ci  T value_;
447b8021494Sopenharmony_ci};
448b8021494Sopenharmony_ci
449b8021494Sopenharmony_ciclass StringLiteral : public RawLiteral {
450b8021494Sopenharmony_ci public:
451b8021494Sopenharmony_ci#ifndef PANDA_BUILD
452b8021494Sopenharmony_ci  explicit StringLiteral(const char* str,
453b8021494Sopenharmony_ci                         PlacementPolicy placement_policy = kPlacedWhenUsed,
454b8021494Sopenharmony_ci                         DeletionPolicy deletion_policy = kManuallyDeleted)
455b8021494Sopenharmony_ci      : RawLiteral(str,
456b8021494Sopenharmony_ci                   static_cast<int>(strlen(str) + 1),
457b8021494Sopenharmony_ci                   placement_policy,
458b8021494Sopenharmony_ci                   deletion_policy) {
459b8021494Sopenharmony_ci    VIXL_ASSERT((strlen(str) + 1) <= kMaxObjectSize);
460b8021494Sopenharmony_ci  }
461b8021494Sopenharmony_ci  explicit StringLiteral(const char* str, DeletionPolicy deletion_policy)
462b8021494Sopenharmony_ci      : RawLiteral(str, static_cast<int>(strlen(str) + 1), deletion_policy) {
463b8021494Sopenharmony_ci    VIXL_ASSERT((strlen(str) + 1) <= kMaxObjectSize);
464b8021494Sopenharmony_ci  }
465b8021494Sopenharmony_ci#else
466b8021494Sopenharmony_ciexplicit StringLiteral(const char* str,
467b8021494Sopenharmony_ci                       PlacementPolicy placement_policy = kPlacedWhenUsed,
468b8021494Sopenharmony_ci                       DeletionPolicy deletion_policy = kManuallyDeleted) = delete;
469b8021494Sopenharmony_ciStringLiteral(AllocatorWrapper allocator, const char* str,
470b8021494Sopenharmony_ci                       PlacementPolicy placement_policy = kPlacedWhenUsed,
471b8021494Sopenharmony_ci                       DeletionPolicy deletion_policy = kManuallyDeleted)
472b8021494Sopenharmony_ci    : RawLiteral(allocator, str,
473b8021494Sopenharmony_ci                 static_cast<int>(strlen(str) + 1),
474b8021494Sopenharmony_ci                 placement_policy,
475b8021494Sopenharmony_ci                 deletion_policy) {
476b8021494Sopenharmony_ci  VIXL_ASSERT((strlen(str) + 1) <= kMaxObjectSize);
477b8021494Sopenharmony_ci}
478b8021494Sopenharmony_ciexplicit StringLiteral(const char* str, DeletionPolicy deletion_policy) = delete;
479b8021494Sopenharmony_ciexplicit StringLiteral(AllocatorWrapper allocator, const char* str, DeletionPolicy deletion_policy)
480b8021494Sopenharmony_ci    : RawLiteral(allocator, str, static_cast<int>(strlen(str) + 1), deletion_policy) {
481b8021494Sopenharmony_ci  VIXL_ASSERT((strlen(str) + 1) <= kMaxObjectSize);
482b8021494Sopenharmony_ci}
483b8021494Sopenharmony_ci#endif
484b8021494Sopenharmony_ci};
485b8021494Sopenharmony_ci
486b8021494Sopenharmony_ci}  // namespace aarch32
487b8021494Sopenharmony_ci
488b8021494Sopenharmony_ci
489b8021494Sopenharmony_ci// Required InvalSet template specialisations.
490b8021494Sopenharmony_ci#define INVAL_SET_TEMPLATE_PARAMETERS                                       \
491b8021494Sopenharmony_ci  aarch32::Location::ForwardRef, aarch32::Location::kNPreallocatedElements, \
492b8021494Sopenharmony_ci      int32_t, aarch32::Location::kInvalidLinkKey,                          \
493b8021494Sopenharmony_ci      aarch32::Location::kReclaimFrom, aarch32::Location::kReclaimFactor
494b8021494Sopenharmony_citemplate <>
495b8021494Sopenharmony_ciinline int32_t InvalSet<INVAL_SET_TEMPLATE_PARAMETERS>::GetKey(
496b8021494Sopenharmony_ci    const aarch32::Location::ForwardRef& element) {
497b8021494Sopenharmony_ci  return element.GetLocation();
498b8021494Sopenharmony_ci}
499b8021494Sopenharmony_citemplate <>
500b8021494Sopenharmony_ciinline void InvalSet<INVAL_SET_TEMPLATE_PARAMETERS>::SetKey(
501b8021494Sopenharmony_ci    aarch32::Location::ForwardRef* element, int32_t key) {
502b8021494Sopenharmony_ci  element->SetLocationToInvalidateOnly(key);
503b8021494Sopenharmony_ci}
504b8021494Sopenharmony_ci#undef INVAL_SET_TEMPLATE_PARAMETERS
505b8021494Sopenharmony_ci
506b8021494Sopenharmony_ci}  // namespace vixl
507b8021494Sopenharmony_ci
508b8021494Sopenharmony_ci#endif  // VIXL_AARCH32_LABEL_AARCH32_H_
509