CACAO
MachineOperand.hpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/MachineOperand.hpp - MachineOperand
2 
3  Copyright (C) 2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 #ifndef _JIT_COMPILER2_MACHINEOPERAND
26 #define _JIT_COMPILER2_MACHINEOPERAND
27 
29 #include "toolbox/OStream.hpp"
30 #include "vm/types.hpp"
31 #include "future/unordered_set.hpp" // for cacao::hash()
32 
36 #include <cassert>
37 
38 MM_MAKE_NAME(MachineOperand)
39 
40 namespace cacao {
41 
42 // forward declarations
43 class OStream;
44 
45 namespace jit {
46 namespace compiler2 {
47 
48 class StackSlotManager;
49 
50 class VoidOperand;
51 class Register;
52 class StackSlot;
53 class ManagedStackSlot;
54 class Immediate;
55 class Address;
56 class CONSTInst;
57 
58 class MachineOperandDesc;
59 class MachineOperand;
60 
61 class EmbeddedMachineOperand : public memory::ManagerMixin<EmbeddedMachineOperand> {
62 public:
65 
66  explicit EmbeddedMachineOperand (MachineOperand *op) : dummy(op), real(NULL) {}
67 };
68 
69 /**
70  * Operands that can be directly used by the machine (register, memory, stackslot)
71  */
72 class MachineOperand : public memory::ManagerMixin<MachineOperand> {
73 public:
74  enum OperandID {
81  VoidOperandID
82  };
83  typedef const void* IdentifyTy;
84  typedef std::size_t IdentifyOffsetTy;
85  typedef std::size_t IdentifySizeTy;
87  typedef embedded_operand_list::iterator operand_iterator;
88  typedef embedded_operand_list::const_iterator const_operand_iterator;
89 private:
90  static std::size_t id_counter;
91  std::size_t id;
94 protected:
95  /**
96  * TODO describe
97  */
99  virtual IdentifyTy id_base() const { return static_cast<IdentifyTy>(this); }
100  virtual IdentifyOffsetTy id_offset() const { return 0; }
101  virtual IdentifySizeTy id_size() const { return 1; }
102 public:
103  std::size_t get_id() const { return id; }
104 
105  explicit MachineOperand(OperandID op_id, Type::TypeID type)
106  : id(id_counter++), op_id(op_id), type(type), embedded_operands() {}
107 
108  OperandID get_OperandID() const { return op_id; }
109  Type::TypeID get_type() const { return type; }
110 
111  virtual const char* get_name() const = 0;
112 
113  virtual ~MachineOperand() {}
114  virtual MachineOperand* to_MachineOperand() { return this; }
115  virtual VoidOperand* to_VoidOperand() { return 0; }
116  virtual Register* to_Register() { return 0; }
117  virtual StackSlot* to_StackSlot() { return 0; }
118  virtual ManagedStackSlot* to_ManagedStackSlot() { return 0; }
119  virtual Immediate* to_Immediate() { return 0; }
120  virtual Address* to_Address() { return 0; }
121 
122  bool is_MachineOperand() const { return op_id == MachineOperandID; }
123  bool is_VoidOperand() const { return op_id == VoidOperandID; }
124  bool is_Register() const { return op_id == RegisterID; }
125  bool is_StackSlot() const { return op_id == StackSlotID; }
126  bool is_ManagedStackSlot() const { return op_id == ManagedStackSlotID; }
127  bool is_Immediate() const { return op_id == ImmediateID; }
128  bool is_Address() const { return op_id == AddressID; }
129 
130  bool is_stackslot() const { return is_StackSlot() || is_ManagedStackSlot(); }
131 
132  /**
133  */
134  bool aquivalence_less(const MachineOperand& MO) const {
135  if (id_base() != MO.id_base()) {
136  return id_base() < MO.id_base();
137  }
138  return id_offset()+id_size() <= MO.id_offset();
139  }
140  bool aquivalent(const MachineOperand& MO) const {
141  return !(aquivalence_less(MO) || MO.aquivalence_less(*this));
142  }
143 
144  /**
145  * True if operand is virtual and must be assigned
146  * during register allocation
147  */
148  virtual bool is_virtual() const { return false; }
149  /**
150  * Return true if operand is processed during register allocation.
151  * This implies is_virtual().
152  *
153  * @see is_virtual()
154  */
155  virtual bool needs_allocation() const { return is_virtual(); }
156  bool has_embedded_operands() { return op_size() != 0; }
157  std::size_t op_size() const {
158  return embedded_operands.size();
159  }
161  assert(i < embedded_operands.size());
162  return embedded_operands[i];
163  }
164  const EmbeddedMachineOperand &get(std::size_t i) const {
165  assert(i < embedded_operands.size());
166  return embedded_operands[i];
167  }
168  EmbeddedMachineOperand &get(std::size_t i) {
169  assert(i < embedded_operands.size());
170  return embedded_operands[i];
171  }
173  return embedded_operands.begin();
174  }
176  return embedded_operands.end();
177  }
179  for (operand_iterator i = begin(), e =end(); i != e; ++i) {
180  if (op->aquivalent(*i->dummy))
181  return i;
182  }
183  return end();
184  }
186  return embedded_operands.front();
187  }
189  return embedded_operands.back();
190  }
192  return embedded_operands.begin();
193  }
195  return embedded_operands.end();
196  }
197 
198  virtual OStream& print(OStream &OS) const {
199  return OS << get_name() /* << " (" << get_type() << ")" */;
200  }
201 };
202 
203 class VoidOperand : public MachineOperand {
204 public:
205  VoidOperand() : MachineOperand(VoidOperandID, Type::VoidTypeID) {}
206  virtual const char* get_name() const {
207  return "VoidOperand";
208  }
209  virtual VoidOperand* to_VoidOperand() { return this; }
210 };
211 
212 class UnassignedReg;
213 class VirtualRegister;
214 class MachineRegister;
215 class MachineAddress;
216 
217 class Register : public MachineOperand {
218 public:
219  Register(Type::TypeID type) : MachineOperand(RegisterID, type) {}
220  virtual const char* get_name() const {
221  return "Register";
222  }
223  virtual bool needs_allocation() const { return true; }
224  virtual Register* to_Register() { return this; }
225  virtual UnassignedReg* to_UnassignedReg() { return 0; }
226  virtual VirtualRegister* to_VirtualRegister() { return 0; }
227  virtual MachineRegister* to_MachineRegister() { return 0; }
228  virtual ~Register() {}
229 };
230 
231 
232 class UnassignedReg : public Register {
233 public:
235  virtual const char* get_name() const {
236  return "UnassignedReg";
237  }
238  virtual UnassignedReg* to_UnassignedReg() { return this; }
239 };
240 
241 class VirtualRegister : public Register {
242 private:
243  static unsigned vreg_counter;
244  const unsigned vreg;
245 public:
247  vreg(vreg_counter++) {}
248 
249  virtual VirtualRegister* to_VirtualRegister() { return this; }
250  virtual const char* get_name() const {
251  return "vreg";
252  }
253  virtual OStream& print(OStream &OS) const {
254  return MachineOperand::print(OS) << get_id();
255  }
256  virtual bool is_virtual() const { return true; }
257  unsigned get_id() const { return vreg; }
258 };
259 
260 class StackSlot : public MachineOperand {
261 private:
262  int index; ///< index of the stackslot
263 public:
264  /**
265  * @param index index of the stackslot
266  */
268  : MachineOperand(StackSlotID, type), index(index) {}
269  virtual StackSlot* to_StackSlot() { return this; }
270  int get_index() const { return index; }
271  virtual const char* get_name() const {
272  return "StackSlot";
273  }
274  virtual OStream& print(OStream &OS) const {
275  return MachineOperand::print(OS) << get_index();
276  }
277 };
278 
280 private:
282  unsigned id;
284  : MachineOperand(ManagedStackSlotID,type), parent(SSM), id(id) {}
285 public:
286  /**
287  * FIXME this should be managed
288  */
289  virtual StackSlot* to_StackSlot();
290  virtual ManagedStackSlot* to_ManagedStackSlot() { return this; }
291  virtual const char* get_name() const {
292  return "ManagedStackSlot";
293  }
294  //virtual bool is_virtual() const { return true; }
295  unsigned get_id() const { return id; }
296  virtual OStream& print(OStream &OS) const {
297  return MachineOperand::print(OS) << get_id();
298  }
299  friend class StackSlotManager;
300 };
301 
302 class Immediate : public MachineOperand {
303 private:
304  typedef union {
305  int32_t i;
306  int64_t l;
307  float f;
308  double d;
309  void *anyptr;
310  java_handle_t *stringconst; /* for ACONST with string */
311  classref_or_classinfo c; /* for ACONST with class */
312  } val_operand_t;
314 public:
317  : MachineOperand(ImmediateID, type) {
318  value.i = val;
319  }
321  : MachineOperand(ImmediateID, type) {
322  value.l = val;
323  }
324  Immediate(float val, Type::FloatType type)
325  : MachineOperand(ImmediateID, type) {
326  value.f = val;
327  }
328  Immediate(double val, Type::DoubleType type)
329  : MachineOperand(ImmediateID, type) {
330  value.d = val;
331  }
332  virtual Immediate* to_Immediate() { return this; }
333  virtual const char* get_name() const {
334  return "Immediate";
335  }
336  template<typename T>
337  T get_value() const;
338 
339  double get_Int() const {
340  assert(get_type() == Type::IntTypeID);
341  return value.i;
342  }
343  double get_Long() const {
344  assert(get_type() == Type::LongTypeID);
345  return value.l;
346  }
347  double get_Float() const {
348  assert(get_type() == Type::FloatTypeID);
349  return value.f;
350  }
351  double get_Double() const {
352  assert(get_type() == Type::DoubleTypeID);
353  return value.d;
354  }
355 };
356 
357 class Address : public MachineOperand {
358 public:
359  /**
360  * @todo ReturnAddressTypeID is not correct
361  */
362  Address() : MachineOperand(AddressID, Type::ReturnAddressTypeID) {}
363  virtual Address* to_Address() { return this; }
364  virtual MachineAddress* to_MachineAddress() = 0;
365  virtual const char* get_name() const {
366  return "Address";
367  }
368 };
369 
370 #if 0
371 class MachineOperandType {
372 public:
373  enum TYPE {
374  NONE = 0,
375  REGISTER_VALUE = 1<<0, ///< register with a value
376  REGISTER_MEM = 1<<1, ///< register with a memory address
377  IMMEDIATE = 1<<2, ///< immediate value
378  ABSOLUTE_ADDR = 1<<3, ///< absolute code address
379  PIC_ADDR = 1<<4, ///< absolute code address (position independent code).
380  ///< The absolute value might changes but offsets are still valid.
381  PC_REL_ADDR = 1<<5, ///< code address offset
382  ALL = REGISTER_VALUE | REGISTER_MEM | IMMEDIATE | ABSOLUTE_ADDR | PIC_ADDR | PC_REL_ADDR
383  };
384 private:
385  unsigned type;
386 public:
387  /// default constructor
388  MachineOperandType() {
389  type = NONE;
390  }
391  MachineOperandType(unsigned t) {
392  set_type(t);
393  }
394  /// copy constructor
395  MachineOperandType(const MachineOperandType &MO) {
396  type = MO.type;
397  }
398  /// copy assignment operator
399  MachineOperandType& operator=(const MachineOperandType &rhs) {
400  type = rhs.type;
401  return *this;
402  }
403  bool takes(const TYPE t) const {
404  return (type & t);
405  }
406  unsigned get_type() const {
407  return type;
408  }
409  void set_type(unsigned t) {
410  assert( t <= ALL);
411  type = t;
412  }
413 };
414 #endif
415 
416 extern VoidOperand NoOperand;
417 #if 0
418 OStream& operator<<(OStream &OS, const MachineOperandType &MO);
419 #endif
421  return MO.print(OS);
422 }
424  if (!MO) {
425  return OS << "(MachineOperand) NULL";
426  }
427  return OS << *MO;
428 }
429 
430 struct MachineOperandComp : public std::binary_function<MachineOperand*,MachineOperand*,bool> {
431  bool operator()(MachineOperand* lhs, MachineOperand *rhs) const {
432  return lhs->aquivalence_less(*rhs);
433  }
434 };
435 
437 
438 
439 } // end namespace compiler2
440 } // end namespace jit
441 
442 template<>
445  return v->get_id();
446  }
447 };
448 
449 
450 } // end namespace cacao
451 
452 namespace std {
453 
454 template<>
455 struct less<cacao::jit::compiler2::MachineOperand*> {
458  return lhs->get_id() < rhs->get_id();
459  }
460 };
461 
462 #if 0
463 template<>
464 struct equal_to<cacao::jit::compiler2::MachineOperand*> {
465  bool operator()(cacao::jit::compiler2::MachineOperand *lhs,
467  return lhs->aquivalent(*rhs);
468  }
469 };
470 #endif
471 
472 } // end namespace standard
473 
474 #endif /* _JIT_COMPILER2_MACHINEOPERAND */
475 
476 
477 /*
478  * These are local overrides for various environment variables in Emacs.
479  * Please do not remove this and leave it at the end of the file, where
480  * Emacs will automagically detect them.
481  * ---------------------------------------------------------------------
482  * Local variables:
483  * mode: c++
484  * indent-tabs-mode: t
485  * c-basic-offset: 4
486  * tab-width: 4
487  * End:
488  * vim:noexpandtab:sw=4:ts=4:
489  */
EmbeddedMachineOperand & operator[](std::size_t i)
embedded_operand_list::iterator operand_iterator
std::size_t index
virtual const char * get_name() const
virtual const char * get_name() const
virtual OStream & print(OStream &OS) const
virtual IdentifyTy id_base() const
virtual ManagedStackSlot * to_ManagedStackSlot()
virtual OStream & print(OStream &OS) const
u2 op
Definition: disass.cpp:129
Custom new/delete handler mixin.
Definition: Manager.hpp:43
const_operand_iterator end() const
bool aquivalence_less(const MachineOperand &MO) const
#define MM_MAKE_NAME(x)
Definition: memstats.hpp:127
Immediate(s8 val, Type::LongType type)
virtual ManagedStackSlot * to_ManagedStackSlot()
Immediate(float val, Type::FloatType type)
Descriptor of a MachineOperand.
PassInfo::IDTy id
bool operator()(cacao::jit::compiler2::MachineOperand *lhs, cacao::jit::compiler2::MachineOperand *rhs) const
Immediate(double val, Type::DoubleType type)
virtual VoidOperand * to_VoidOperand()
virtual UnassignedReg * to_UnassignedReg()
int64_t s8
Definition: types.hpp:48
virtual VirtualRegister * to_VirtualRegister()
virtual OStream & print(OStream &OS) const
virtual const char * get_name() const
alloc::vector< EmbeddedMachineOperand >::type embedded_operand_list
virtual Register * to_Register()
std::list< T, Allocator< T > > type
Definition: list.hpp:38
operand_iterator find(MachineOperand *op)
virtual bool is_virtual() const
True if operand is virtual and must be assigned during register allocation.
MachineOperand(OperandID op_id, Type::TypeID type)
std::vector< T, Allocator< T > > type
Definition: vector.hpp:38
Simple stream class for formatted output.
Definition: OStream.hpp:141
virtual VirtualRegister * to_VirtualRegister()
virtual const char * get_name() const
virtual bool is_virtual() const
True if operand is virtual and must be assigned during register allocation.
virtual VoidOperand * to_VoidOperand()
MIIterator i
virtual MachineRegister * to_MachineRegister()
virtual Immediate * to_Immediate()
alloc::list< MachineOperand * >::type OperandFile
int32_t s4
Definition: types.hpp:45
embedded_operand_list::const_iterator const_operand_iterator
StackSlot(int index, Type::TypeID type)
OStream & OS
std::size_t operator()(cacao::jit::compiler2::MachineOperand *v) const
OStream & operator<<(OStream &OS, const std::string &t)
Definition: OStream.hpp:459
virtual bool needs_allocation() const
Return true if operand is processed during register allocation.
MIIterator e
bool aquivalent(const MachineOperand &MO) const
#define I(value)
Definition: codegen.c:279
virtual const char * get_name() const
virtual const char * get_name() const
virtual const char * get_name() const
Operands that can be directly used by the machine (register, memory, stackslot)
virtual StackSlot * to_StackSlot()
virtual IdentifyOffsetTy id_offset() const
bool operator()(MachineOperand *lhs, MachineOperand *rhs) const
Immediate(s4 val, Type::IntType type)
embedded_operand_list embedded_operands
TODO describe.
int index
index of the stackslot
const_operand_iterator begin() const
virtual bool needs_allocation() const
Return true if operand is processed during register allocation.
virtual IdentifySizeTy id_size() const
LoopTreeGraph * parent
virtual MachineOperand * to_MachineOperand()
virtual OStream & print(OStream &OS) const
EmbeddedMachineOperand & front()
virtual const char * get_name() const
virtual UnassignedReg * to_UnassignedReg()
ManagedStackSlot(StackSlotManager *SSM, unsigned id, Type::TypeID type)