CACAO
MachineInstruction.hpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/MachineInstruction.hpp - MachineInstruction
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_MACHINEINSTRUCTION
26 #define _JIT_COMPILER2_MACHINEINSTRUCTION
27 
31 
35 
36 MM_MAKE_NAME(MachineInstruction)
37 
38 namespace cacao {
39 
40 // forward declaration
41 class OStream;
42 
43 namespace jit {
44 namespace compiler2 {
45 
46 // forward declaration
47 class MachineMoveInst;
48 class MachinePhiInst;
49 class CodeMemory;
50 class MachineInstruction;
51 class MachineReplacementPointInst;
52 
53 /**
54  * Descriptor of a MachineOperand
55  *
56  * Besides a pointer to the actual MachineOperand meta information like
57  * operand index, etc. are stored.
58  */
59 class MachineOperandDesc : public memory::ManagerMixin<MachineOperandDesc> {
60 private:
62  std::size_t index;
63 public:
66  : parent(parent), index(index), op(NULL) {}
68  MachineOperand *op) : parent(parent), index(index), op(op) {}
70  : parent(parent), index(0), op(op) {}
71  std::size_t get_index() const { return index; }
73 };
74 
75 /**
76  * Proxy to encode explicit and implicit successors.
77  *
78  * The target of an unconditional jump is an explicit successor (i.e. the
79  * target is specified explicitly). The else branch of a conditional jump
80  * (i.e. the following block) is an implicit successor.
81  *
82  * For implicit successors the source block is stored. Whenever the real
83  * successor is requested the block following the source block is returned.
84  * Therefore implicit successors might change if a block is inserted after the
85  * source block.
86  */
87 #if 0
88 class SuccessorProxy : public memory::ManagerMixin<SuccessorProxy> {
89 public:
90  struct Explicit {};
91  struct Implicit {};
92 private:
93  enum Type { ExplTy, ImplTy };
94  MachineBasicBlock *entry;
95  Type type;
96 public:
97  /// Constructor. Construct explicit successor.
98  explicit SuccessorProxy(MachineBasicBlock* MBB, Explicit)
99  : entry(MBB), type(ExplTy) {}
100  /// Constructor. Construct implicit successor.
101  explicit SuccessorProxy(MachineBasicBlock* MBB, Implicit)
102  : entry(MBB), type(ImplTy) {}
103  /// convert to MachineBasicBlock
104  operator MachineBasicBlock*() const;
105 };
106 #endif
107 
108 /**
109  * Superclass for all machine dependent instructions
110  */
111 class MachineInstruction : public memory::ManagerMixin<MachineInstruction> {
112 public:
114  typedef operand_list::iterator operand_iterator;
115  typedef operand_list::const_iterator const_operand_iterator;
117  typedef dummy_operand_list::iterator dummy_operand_iterator;
118  typedef dummy_operand_list::const_iterator const_dummy_operand_iterator;
121  typedef successor_list::iterator successor_iterator;
122  typedef successor_list::const_iterator const_successor_iterator;
123 private:
124  static std::size_t id_counter;
126  std::size_t pos;
127  pos = dummy_operands.size();
128  dummy_operands.push_back(MachineOperandDesc(this,pos));
129  dummy_operands[pos].op = op->dummy;
130 
131  ref_map.insert(std::make_pair(op,pos));
132  }
133 protected:
134  const std::size_t id;
136  /**
137  * dummy_operands is a list of operands embedded in the real operands
138  * of this instruction that need register allocation
139  * (for example indirect addressing on x86)
140  */
145  const char *name;
146  const char *comment;
148 public:
149  #if 0
150  MachineInstruction(const char * name, MachineOperand* result, std::size_t num_operands, MachineOperand* dflt)
151  : id(id_counter++), operands(num_operands,dflt), result(result), name(name) {
152  }
153  #endif
154  MachineInstruction(const char * name, MachineOperand* result, std::size_t num_operands, const char* comment = NULL)
155  : id(id_counter++), operands(), dummy_operands(), ref_map(), result(this, result), name(name), comment(comment), block(NULL) {
156  for (std::size_t i = 0; i < num_operands ; ++i) {
157  operands.push_back(MachineOperandDesc(this,i));
158  }
159  if (result->has_embedded_operands()) {
160  for (MachineOperand::operand_iterator it = result->begin(), e = result->end(); it != e ; ++it) {
161  set_dummy_operand(&(*it));
162  }
163  }
164  }
165 
166  void set_comment(const char* c) { comment = c; }
167  const char* get_comment() const { return comment; }
168 
169  void set_operand(std::size_t i,MachineOperand* op) {
170  assert(i < operands.size());
171  operands[i].op = op;
172  if (op->has_embedded_operands()) {
173  for (MachineOperand::operand_iterator it = op->begin(), e = op->end(); it != e ; ++it) {
174  set_dummy_operand(&(*it));
175  }
176  }
177  }
178 
179  /// has to be called after all operands with embedded operands have been added
181  for (RefMapTy::iterator it = ref_map.begin(), e = ref_map.end(); it != e; ++it) {
182  it->first->real = &dummy_operands[it->second];
183  }
184  ref_map.clear();
185  }
186  virtual void set_block(MachineBasicBlock* MBB) {
187  block = MBB;
188  }
190  return block;
191  }
192 
193  std::size_t op_size() const {
194  return operands.size();
195  }
197  assert(i < operands.size());
198  assert(operands[i].get_index() == i);
199  return operands[i];
200  }
201  const MachineOperandDesc& get(std::size_t i) const {
202  assert(i < operands.size());
203  assert(operands[i].get_index() == i);
204  return operands[i];
205  }
206  MachineOperandDesc& get(std::size_t i) {
207  assert(i < operands.size());
208  assert(operands[i].get_index() == i);
209  return operands[i];
210  }
212  return operands.begin();
213  }
215  return operands.end();
216  }
218  for (operand_iterator i = begin(), e =end(); i != e; ++i) {
219  if (op->aquivalent(*i->op))
220  return i;
221  }
222  return end();
223  }
225  return operands.front();
226  }
228  return operands.back();
229  }
231  return operands.begin();
232  }
234  return operands.end();
235  }
236  std::size_t dummy_op_size() const {
237  return dummy_operands.size();
238  }
239  const MachineOperandDesc& get_dummy(std::size_t i) const {
240  assert(i < dummy_operands.size());
241  assert(dummy_operands[i].get_index() == i);
242  return dummy_operands[i];
243  }
245  assert(i < dummy_operands.size());
246  assert(dummy_operands[i].get_index() == i);
247  return dummy_operands[i];
248  }
250  return dummy_operands.begin();
251  }
253  return dummy_operands.end();
254  }
256  for (dummy_operand_iterator i = dummy_begin(), e =dummy_end(); i != e; ++i) {
257  if (op->aquivalent(*i->op))
258  return i;
259  }
260  return dummy_end();
261  }
263  return dummy_operands.front();
264  }
266  return dummy_operands.back();
267  }
269  return dummy_operands.begin();
270  }
272  return dummy_operands.end();
273  }
275  return successors.begin();
276  }
278  return successors.end();
279  }
281  return successors.begin();
282  }
284  return successors.front();
285  }
287  return successors.back();
288  }
290  return successors.end();
291  }
292  std::size_t successor_size() const {
293  return successors.size();
294  }
295  bool successor_empty() const {
296  return successors.empty();
297  }
298  std::size_t get_id() const {
299  return id;
300  }
301  const char* get_name() const {
302  return name;
303  }
305  return result;
306  }
308  return result;
309  }
311  result = MachineOperandDesc(0,MO);
312  }
313  virtual bool accepts_immediate(std::size_t i, Immediate *imm) const {
314  return false;
315  }
316  virtual bool is_label() const {
317  return false;
318  }
319  virtual bool is_phi() const {
320  return false;
321  }
322  virtual bool is_move() const {
323  return false;
324  }
325  virtual bool is_jump() const {
326  return false;
327  }
328  virtual bool is_end() const {
329  return is_jump();
330  }
331  virtual bool is_call() const {
332  return false;
333  }
334  virtual MachineMoveInst* to_MachineMoveInst() {
335  return NULL;
336  }
337  #if 0
338  virtual MachineLabelInst* to_MachineLabelInst() {
339  return NULL;
340  }
341  #endif
343  return NULL;
344  }
346  return NULL;
347  }
348  /// print instruction
349  OStream& print(OStream &OS) const;
350  /// print successor label
351  virtual OStream& print_successor_label(OStream &OS,std::size_t index) const;
352  /// print operands
353  virtual OStream& print_operands(OStream &OS) const;
354  /// print result
355  virtual OStream& print_result(OStream &OS) const;
356 
357  /// emit machine code
358  virtual void emit(CodeMemory* CM) const;
359  /// link machine code
360  virtual void link(CodeFragment &CF) const;
361 
362  /// destructor
363  virtual ~MachineInstruction() {}
364 };
365 
366 OStream& operator<<(OStream &OS, const MachineInstruction *MI);
367 OStream& operator<<(OStream &OS, const MachineInstruction &MI);
368 
369 OStream& operator<<(OStream &OS, const MachineOperandDesc *MOD);
370 OStream& operator<<(OStream &OS, const MachineOperandDesc &MOD);
371 
372 
373 } // end namespace compiler2
374 } // end namespace jit
375 } // end namespace cacao
376 
377 #endif /* _JIT_COMPILER2_MACHINEINSTRUCTION */
378 
379 
380 /*
381  * These are local overrides for various environment variables in Emacs.
382  * Please do not remove this and leave it at the end of the file, where
383  * Emacs will automagically detect them.
384  * ---------------------------------------------------------------------
385  * Local variables:
386  * mode: c++
387  * indent-tabs-mode: t
388  * c-basic-offset: 4
389  * tab-width: 4
390  * End:
391  * vim:noexpandtab:sw=4:ts=4:
392  */
embedded_operand_list::iterator operand_iterator
std::size_t index
MachineOperandDesc(MachineInstruction *parent, std::size_t index, MachineOperand *op)
virtual MachineReplacementPointInst * to_MachineReplacementPointInst()
dummy_operand_list::const_iterator const_dummy_operand_iterator
MachineInstruction(const char *name, MachineOperand *result, std::size_t num_operands, const char *comment=NULL)
u2 op
Definition: disass.cpp:129
Custom new/delete handler mixin.
Definition: Manager.hpp:43
A basic block of (scheduled) machine instructions.
virtual void set_block(MachineBasicBlock *MBB)
const MachineOperandDesc & get_dummy(std::size_t i) const
operand_list::const_iterator const_operand_iterator
alloc::unordered_map< EmbeddedMachineOperand *, int >::type RefMapTy
#define MM_MAKE_NAME(x)
Definition: memstats.hpp:128
Descriptor of a MachineOperand.
PassInfo::IDTy id
Represents a point in the program, where it is possible to recover the source state to perform on-sta...
void set_operand(std::size_t i, MachineOperand *op)
JNIEnv jclass jobject const char * name
Definition: jvmti.h:312
virtual bool accepts_immediate(std::size_t i, Immediate *imm) const
virtual MachineMoveInst * to_MachineMoveInst()
const_reference front() const
access the first element
std::list< T, Allocator< T > > type
Definition: list.hpp:38
const_dummy_operand_iterator dummy_end() const
void link(basicblock *v, basicblock *w)
Definition: dominator.cpp:178
MachineBasicBlock * successor_front() const
const_reference back() const
access the last element
BeginInst *& block
const_dummy_operand_iterator dummy_begin() const
successor_list::const_iterator const_successor_iterator
MachineOperandDesc(MachineInstruction *parent, std::size_t index)
std::vector< T, Allocator< T > > type
Definition: vector.hpp:38
Simple stream class for formatted output.
Definition: OStream.hpp:141
Type
Types used internally by JITTED code.
Definition: global.hpp:117
operand_iterator find(MachineOperand *op)
MIIterator i
alloc::vector< MachineOperandDesc >::type operand_list
MIIterator pos
alloc::list< MachineBasicBlock * >::type successor_list
OStream & OS
OStream & operator<<(OStream &OS, const std::string &t)
Definition: OStream.hpp:459
MIIterator e
bool aquivalent(const MachineOperand &MO) const
dummy_operand_iterator find_dummy(MachineOperand *op)
Proxy to encode explicit and implicit successors.
dummy_operand_list dummy_operands
dummy_operands is a list of operands embedded in the real operands of this instruction that need regi...
MachineOperandDesc & operator[](std::size_t i)
dummy_operand_list::iterator dummy_operand_iterator
Operands that can be directly used by the machine (register, memory, stackslot)
void finalize_operands()
has to be called after all operands with embedded operands have been added
const MachineOperandDesc & get_result() const
Segment reference.
Definition: Segment.hpp:44
MachineInstruction * get_MachineInstruction() const
MachineOperandDesc & get_dummy(std::size_t i)
alloc::vector< MachineOperandDesc >::type dummy_operand_list
LoopTreeGraph * parent
const_successor_iterator successor_begin() const
const_successor_iterator successor_end() const
MachineOperandDesc(MachineInstruction *parent, MachineOperand *op)
std::unordered_map< Key, T, Hash, KeyEqual, Allocator< std::pair< const Key, T > > > type
void set_dummy_operand(EmbeddedMachineOperand *op)