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_COMPILERDEFS_H_INCLUDED
25 #define ASMJIT_CORE_COMPILERDEFS_H_INCLUDED
26 
27 #include "../core/api-config.h"
28 #include "../core/operand.h"
29 #include "../core/zonestring.h"
30 
31 ASMJIT_BEGIN_NAMESPACE
32 
33 // ============================================================================
34 // [Forward Declarations]
35 // ============================================================================
36 
37 class RAWorkReg;
38 
39 //! \addtogroup asmjit_compiler
40 //! \{
41 
42 // ============================================================================
43 // [asmjit::VirtReg]
44 // ============================================================================
45 
46 //! Virtual register data, managed by \ref BaseCompiler.
47 class VirtReg {
48 public:
49   ASMJIT_NONCOPYABLE(VirtReg)
50 
51   //! Virtual register id.
52   uint32_t _id = 0;
53   //! Virtual register info (signature).
54   RegInfo _info = {};
55   //! Virtual register size (can be smaller than `regInfo._size`).
56   uint32_t _virtSize = 0;
57   //! Virtual register alignment (for spilling).
58   uint8_t _alignment = 0;
59   //! Type-id.
60   uint8_t _typeId = 0;
61   //! Virtual register weight for alloc/spill decisions.
62   uint8_t _weight = 1;
63   //! True if this is a fixed register, never reallocated.
64   uint8_t _isFixed : 1;
65   //! True if the virtual register is only used as a stack (never accessed as register).
66   uint8_t _isStack : 1;
67   uint8_t _reserved : 6;
68 
69   //! Virtual register name (user provided or automatically generated).
70   ZoneString<16> _name {};
71 
72   // -------------------------------------------------------------------------
73   // The following members are used exclusively by RAPass. They are initialized
74   // when the VirtReg is created to NULL pointers and then changed during RAPass
75   // execution. RAPass sets them back to NULL before it returns.
76   // -------------------------------------------------------------------------
77 
78   //! Reference to `RAWorkReg`, used during register allocation.
79   RAWorkReg* _workReg = nullptr;
80 
81   //! \name Construction & Destruction
82   //! \{
83 
VirtReg(uint32_t id,uint32_t signature,uint32_t virtSize,uint32_t alignment,uint32_t typeId)84   inline VirtReg(uint32_t id, uint32_t signature, uint32_t virtSize, uint32_t alignment, uint32_t typeId) noexcept
85     : _id(id),
86       _info { signature },
87       _virtSize(virtSize),
88       _alignment(uint8_t(alignment)),
89       _typeId(uint8_t(typeId)),
90       _isFixed(false),
91       _isStack(false),
92       _reserved(0) {}
93 
94   //! \}
95 
96   //! \name Accessors
97   //! \{
98 
99   //! Returns the virtual register id.
id()100   inline uint32_t id() const noexcept { return _id; }
101 
102   //! Returns the virtual register name.
name()103   inline const char* name() const noexcept { return _name.data(); }
104   //! Returns the size of the virtual register name.
nameSize()105   inline uint32_t nameSize() const noexcept { return _name.size(); }
106 
107   //! Returns a register information that wraps the register signature.
info()108   inline const RegInfo& info() const noexcept { return _info; }
109   //! Returns a virtual register type (maps to the physical register type as well).
type()110   inline uint32_t type() const noexcept { return _info.type(); }
111   //! Returns a virtual register group (maps to the physical register group as well).
group()112   inline uint32_t group() const noexcept { return _info.group(); }
113 
114   //! Returns a real size of the register this virtual register maps to.
115   //!
116   //! For example if this is a 128-bit SIMD register used for a scalar single
117   //! precision floating point value then its virtSize would be 4, however, the
118   //! `regSize` would still say 16 (128-bits), because it's the smallest size
119   //! of that register type.
regSize()120   inline uint32_t regSize() const noexcept { return _info.size(); }
121 
122   //! Returns a register signature of this virtual register.
signature()123   inline uint32_t signature() const noexcept { return _info.signature(); }
124 
125   //! Returns the virtual register size.
126   //!
127   //! The virtual register size describes how many bytes the virtual register
128   //! needs to store its content. It can be smaller than the physical register
129   //! size, see `regSize()`.
virtSize()130   inline uint32_t virtSize() const noexcept { return _virtSize; }
131 
132   //! Returns the virtual register alignment.
alignment()133   inline uint32_t alignment() const noexcept { return _alignment; }
134 
135   //! Returns the virtual register type id, see `Type::Id`.
typeId()136   inline uint32_t typeId() const noexcept { return _typeId; }
137 
138   //! Returns the virtual register weight - the register allocator can use it
139   //! as explicit hint for alloc/spill decisions.
weight()140   inline uint32_t weight() const noexcept { return _weight; }
141   //! Sets the virtual register weight (0 to 255) - the register allocator can
142   //! use it as explicit hint for alloc/spill decisions and initial bin-packing.
setWeight(uint32_t weight)143   inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); }
144 
145   //! Returns whether the virtual register is always allocated to a fixed
146   //! physical register (and never reallocated).
147   //!
148   //! \note This is only used for special purposes and it's mostly internal.
isFixed()149   inline bool isFixed() const noexcept { return bool(_isFixed); }
150 
151   //! Returns whether the virtual register is indeed a stack that only uses
152   //! the virtual register id for making it accessible.
153   //!
154   //! \note It's an error if a stack is accessed as a register.
isStack()155   inline bool isStack() const noexcept { return bool(_isStack); }
156 
hasWorkReg()157   inline bool hasWorkReg() const noexcept { return _workReg != nullptr; }
workReg()158   inline RAWorkReg* workReg() const noexcept { return _workReg; }
setWorkReg(RAWorkReg * workReg)159   inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; }
resetWorkReg()160   inline void resetWorkReg() noexcept { _workReg = nullptr; }
161 
162   //! \}
163 };
164 
165 //! \}
166 
167 ASMJIT_END_NAMESPACE
168 
169 #endif // ASMJIT_CORE_COMPILERDEFS_H_INCLUDED
170 
171