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