1 // AsmJit - Machine code generation for C++
2 //
3 //  * Official AsmJit Home Page: https://asmjit.com
4 //  * Official Github Repository: https://github.com/asmjit/asmjit
5 //
6 // Copyright (c) 2008-2020 The AsmJit Authors
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 //    claim that you wrote the original software. If you use this software
18 //    in a product, an acknowledgment in the product documentation would be
19 //    appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not be
21 //    misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source distribution.
23 
24 #ifndef ASMJIT_CORE_RASTACK_P_H_INCLUDED
25 #define ASMJIT_CORE_RASTACK_P_H_INCLUDED
26 
27 #include "../core/api-config.h"
28 #ifndef ASMJIT_NO_COMPILER
29 
30 #include "../core/radefs_p.h"
31 
32 ASMJIT_BEGIN_NAMESPACE
33 
34 //! \cond INTERNAL
35 //! \addtogroup asmjit_ra
36 //! \{
37 
38 // ============================================================================
39 // [asmjit::RAStackSlot]
40 // ============================================================================
41 
42 //! Stack slot.
43 struct RAStackSlot {
44   //! Stack slot flags.
45   //!
46   //! TODO: kFlagStackArg is not used by the current implementation, do we need to keep it?
47   enum Flags : uint32_t {
48     //! Stack slot is register home slot.
49     kFlagRegHome = 0x0001u,
50     //! Stack slot position matches argument passed via stack.
51     kFlagStackArg = 0x0002u
52   };
53 
54   enum ArgIndex : uint32_t {
55     kNoArgIndex = 0xFF
56   };
57 
58   //! Base register used to address the stack.
59   uint8_t _baseRegId;
60   //! Minimum alignment required by the slot.
61   uint8_t _alignment;
62   //! Reserved for future use.
63   uint16_t _flags;
64   //! Size of memory required by the slot.
65   uint32_t _size;
66 
67   //! Usage counter (one unit equals one memory access).
68   uint32_t _useCount;
69   //! Weight of the slot, calculated by \ref RAStackAllocator::calculateStackFrame().
70   uint32_t _weight;
71   //! Stack offset, calculated by \ref RAStackAllocator::calculateStackFrame().
72   int32_t _offset;
73 
74   //! \name Accessors
75   //! \{
76 
baseRegIdRAStackSlot77   inline uint32_t baseRegId() const noexcept { return _baseRegId; }
setBaseRegIdRAStackSlot78   inline void setBaseRegId(uint32_t id) noexcept { _baseRegId = uint8_t(id); }
79 
sizeRAStackSlot80   inline uint32_t size() const noexcept { return _size; }
alignmentRAStackSlot81   inline uint32_t alignment() const noexcept { return _alignment; }
82 
flagsRAStackSlot83   inline uint32_t flags() const noexcept { return _flags; }
hasFlagRAStackSlot84   inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; }
addFlagsRAStackSlot85   inline void addFlags(uint32_t flags) noexcept { _flags = uint16_t(_flags | flags); }
86 
isRegHomeRAStackSlot87   inline bool isRegHome() const noexcept { return hasFlag(kFlagRegHome); }
isStackArgRAStackSlot88   inline bool isStackArg() const noexcept { return hasFlag(kFlagStackArg); }
89 
useCountRAStackSlot90   inline uint32_t useCount() const noexcept { return _useCount; }
91   inline void addUseCount(uint32_t n = 1) noexcept { _useCount += n; }
92 
weightRAStackSlot93   inline uint32_t weight() const noexcept { return _weight; }
setWeightRAStackSlot94   inline void setWeight(uint32_t weight) noexcept { _weight = weight; }
95 
offsetRAStackSlot96   inline int32_t offset() const noexcept { return _offset; }
setOffsetRAStackSlot97   inline void setOffset(int32_t offset) noexcept { _offset = offset; }
98 
99   //! \}
100 };
101 
102 typedef ZoneVector<RAStackSlot*> RAStackSlots;
103 
104 // ============================================================================
105 // [asmjit::RAStackAllocator]
106 // ============================================================================
107 
108 //! Stack allocator.
109 class RAStackAllocator {
110 public:
111   ASMJIT_NONCOPYABLE(RAStackAllocator)
112 
113   enum Size : uint32_t {
114     kSize1     = 0,
115     kSize2     = 1,
116     kSize4     = 2,
117     kSize8     = 3,
118     kSize16    = 4,
119     kSize32    = 5,
120     kSize64    = 6,
121     kSizeCount = 7
122   };
123 
124   //! Allocator used to allocate internal data.
125   ZoneAllocator* _allocator;
126   //! Count of bytes used by all slots.
127   uint32_t _bytesUsed;
128   //! Calculated stack size (can be a bit greater than `_bytesUsed`).
129   uint32_t _stackSize;
130   //! Minimum stack alignment.
131   uint32_t _alignment;
132   //! Stack slots vector.
133   RAStackSlots _slots;
134 
135   //! \name Construction / Destruction
136   //! \{
137 
RAStackAllocator()138   inline RAStackAllocator() noexcept
139     : _allocator(nullptr),
140       _bytesUsed(0),
141       _stackSize(0),
142       _alignment(1),
143       _slots() {}
144 
reset(ZoneAllocator * allocator)145   inline void reset(ZoneAllocator* allocator) noexcept {
146     _allocator = allocator;
147     _bytesUsed = 0;
148     _stackSize = 0;
149     _alignment = 1;
150     _slots.reset();
151   }
152 
153   //! \}
154 
155   //! \name Accessors
156   //! \{
157 
allocator()158   inline ZoneAllocator* allocator() const noexcept { return _allocator; }
159 
bytesUsed()160   inline uint32_t bytesUsed() const noexcept { return _bytesUsed; }
stackSize()161   inline uint32_t stackSize() const noexcept { return _stackSize; }
alignment()162   inline uint32_t alignment() const noexcept { return _alignment; }
163 
slots()164   inline RAStackSlots& slots() noexcept { return _slots; }
slots()165   inline const RAStackSlots& slots() const noexcept { return _slots; }
slotCount()166   inline uint32_t slotCount() const noexcept { return _slots.size(); }
167 
168   //! \}
169 
170   //! \name Utilities
171   //! \{
172 
173   RAStackSlot* newSlot(uint32_t baseRegId, uint32_t size, uint32_t alignment, uint32_t flags = 0) noexcept;
174 
175   Error calculateStackFrame() noexcept;
176   Error adjustSlotOffsets(int32_t offset) noexcept;
177 
178   //! \}
179 };
180 
181 //! \}
182 //! \endcond
183 
184 ASMJIT_END_NAMESPACE
185 
186 #endif // !ASMJIT_NO_COMPILER
187 #endif // ASMJIT_CORE_RASTACK_P_H_INCLUDED
188