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 
52 /**
53  * Descriptor of a MachineOperand
54  *
55  * Besides a pointer to the actual MachineOperand meta information like
56  * operand index, etc. are stored.
57  */
58 class MachineOperandDesc : public memory::ManagerMixin<MachineOperandDesc> {
59 private:
61  std::size_t index;
62 public:
65  : parent(parent), index(index), op(NULL) {}
67  MachineOperand *op) : parent(parent), index(index), op(op) {}
69  : parent(parent), index(0), op(op) {}
70  std::size_t get_index() const { return index; }
72 };
73 
74 /**
75  * Proxy to encode explicit and implicit successors.
76  *
77  * The target of an unconditional jump is an explicit successor (i.e. the
78  * target is specified explicitly). The else branch of a conditional jump
79  * (i.e. the following block) is an implicit successor.
80  *
81  * For implicit successors the source block is stored. Whenever the real
82  * successor is requested the block following the source block is returned.
83  * Therefore implicit successors might change if a block is inserted after the
84  * source block.
85  */
86 #if 0
87 class SuccessorProxy : public memory::ManagerMixin<SuccessorProxy> {
88 public:
89  struct Explicit {};
90  struct Implicit {};
91 private:
92  enum Type { ExplTy, ImplTy };
93  MachineBasicBlock *entry;
94  Type type;
95 public:
96  /// Constructor. Construct explicit successor.
97  explicit SuccessorProxy(MachineBasicBlock* MBB, Explicit)
98  : entry(MBB), type(ExplTy) {}
99  /// Constructor. Construct implicit successor.
100  explicit SuccessorProxy(MachineBasicBlock* MBB, Implicit)
101  : entry(MBB), type(ImplTy) {}
102  /// convert to MachineBasicBlock
103  operator MachineBasicBlock*() const;
104 };
105 #endif
106 
107 /**
108  * Superclass for all machine dependent instructions
109  */
110 class MachineInstruction : public memory::ManagerMixin<MachineInstruction> {
111 public:
113  typedef operand_list::iterator operand_iterator;
114  typedef operand_list::const_iterator const_operand_iterator;
116  typedef dummy_operand_list::iterator dummy_operand_iterator;
117  typedef dummy_operand_list::const_iterator const_dummy_operand_iterator;
120  typedef successor_list::iterator successor_iterator;
121  typedef successor_list::const_iterator const_successor_iterator;
122 private:
123  static std::size_t id_counter;
125  std::size_t pos;
126  pos = dummy_operands.size();
127  dummy_operands.push_back(MachineOperandDesc(this,pos));
128  dummy_operands[pos].op = op->dummy;
129 
130  ref_map.insert(std::make_pair(op,pos));
131  }
132 protected:
133  const std::size_t id;
135  /**
136  * dummy_operands is a list of operands embedded in the real operands
137  * of this instruction that need register allocation
138  * (for example indirect addressing on x86)
139  */
144  const char *name;
145  const char *comment;
147 public:
148  #if 0
149  MachineInstruction(const char * name, MachineOperand* result, std::size_t num_operands, MachineOperand* dflt)
150  : id(id_counter++), operands(num_operands,dflt), result(result), name(name) {
151  }
152  #endif
153  MachineInstruction(const char * name, MachineOperand* result, std::size_t num_operands, const char* comment = NULL)
154  : id(id_counter++), operands(), dummy_operands(), ref_map(), result(this, result), name(name), comment(comment), block(NULL) {
155  for (std::size_t i = 0; i < num_operands ; ++i) {
156  operands.push_back(MachineOperandDesc(this,i));
157  }
158  if (result->has_embedded_operands()) {
159  for (MachineOperand::operand_iterator it = result->begin(), e = result->end(); it != e ; ++it) {
160  set_dummy_operand(&(*it));
161  }
162  }
163  }
164 
165  void set_comment(const char* c) { comment = c; }
166  const char* get_comment() const { return comment; }
167 
168  void set_operand(std::size_t i,MachineOperand* op) {
169  assert(i < operands.size());
170  operands[i].op = op;
171  if (op->has_embedded_operands()) {
172  for (MachineOperand::operand_iterator it = op->begin(), e = op->end(); it != e ; ++it) {
173  set_dummy_operand(&(*it));
174  }
175  }
176  }
177 
178  /// has to be called after all operands with embedded operands have been added
180  for (RefMapTy::iterator it = ref_map.begin(), e = ref_map.end(); it != e; ++it) {
181  it->first->real = &dummy_operands[it->second];
182  }
183  ref_map.clear();
184  }
185  virtual void set_block(MachineBasicBlock* MBB) {
186  block = MBB;
187  }
189  return block;
190  }
191 
192  std::size_t op_size() const {
193  return operands.size();
194  }
196  assert(i < operands.size());
197  assert(operands[i].get_index() == i);
198  return operands[i];
199  }
200  const MachineOperandDesc& get(std::size_t i) const {
201  assert(i < operands.size());
202  assert(operands[i].get_index() == i);
203  return operands[i];
204  }
205  MachineOperandDesc& get(std::size_t i) {
206  assert(i < operands.size());
207  assert(operands[i].get_index() == i);
208  return operands[i];
209  }
211  return operands.begin();
212  }
214  return operands.end();
215  }
217  for (operand_iterator i = begin(), e =end(); i != e; ++i) {
218  if (op->aquivalent(*i->op))
219  return i;
220  }
221  return end();
222  }
224  return operands.front();
225  }
227  return operands.back();
228  }
230  return operands.begin();
231  }
233  return operands.end();
234  }
235  std::size_t dummy_op_size() const {
236  return dummy_operands.size();
237  }
238  const MachineOperandDesc& get_dummy(std::size_t i) const {
239  assert(i < dummy_operands.size());
240  assert(dummy_operands[i].get_index() == i);
241  return dummy_operands[i];
242  }
244  assert(i < dummy_operands.size());
245  assert(dummy_operands[i].get_index() == i);
246  return dummy_operands[i];
247  }
249  return dummy_operands.begin();
250  }
252  return dummy_operands.end();
253  }
255  for (dummy_operand_iterator i = dummy_begin(), e =dummy_end(); i != e; ++i) {
256  if (op->aquivalent(*i->op))
257  return i;
258  }
259  return dummy_end();
260  }
262  return dummy_operands.front();
263  }
265  return dummy_operands.back();
266  }
268  return dummy_operands.begin();
269  }
271  return dummy_operands.end();
272  }
274  return successors.begin();
275  }
277  return successors.end();
278  }
280  return successors.begin();
281  }
283  return successors.front();
284  }
286  return successors.back();
287  }
289  return successors.end();
290  }
291  std::size_t successor_size() const {
292  return successors.size();
293  }
294  bool successor_empty() const {
295  return successors.empty();
296  }
297  std::size_t get_id() const {
298  return id;
299  }
300  const char* get_name() const {
301  return name;
302  }
304  return result;
305  }
307  return result;
308  }
310  result = MachineOperandDesc(0,MO);
311  }
312  virtual bool accepts_immediate(std::size_t i, Immediate *imm) const {
313  return false;
314  }
315  virtual bool is_label() const {
316  return false;
317  }
318  virtual bool is_phi() const {
319  return false;
320  }
321  virtual bool is_move() const {
322  return false;
323  }
324  virtual bool is_jump() const {
325  return false;
326  }
327  virtual bool is_end() const {
328  return is_jump();
329  }
330  virtual MachineMoveInst* to_MachineMoveInst() {
331  return NULL;
332  }
333  #if 0
334  virtual MachineLabelInst* to_MachineLabelInst() {
335  return NULL;
336  }
337  #endif
339  return NULL;
340  }
341  /// print instruction
342  OStream& print(OStream &OS) const;
343  /// print successor label
344  virtual OStream& print_successor_label(OStream &OS,std::size_t index) const;
345  /// print operands
346  virtual OStream& print_operands(OStream &OS) const;
347  /// print result
348  virtual OStream& print_result(OStream &OS) const;
349 
350  /// emit machine code
351  virtual void emit(CodeMemory* CM) const;
352  /// link machine code
353  virtual void link(CodeFragment &CF) const;
354 
355  /// destructor
356  virtual ~MachineInstruction() {}
357 };
358 
359 OStream& operator<<(OStream &OS, const MachineInstruction *MI);
360 OStream& operator<<(OStream &OS, const MachineInstruction &MI);
361 
362 OStream& operator<<(OStream &OS, const MachineOperandDesc *MOD);
363 OStream& operator<<(OStream &OS, const MachineOperandDesc &MOD);
364 
365 
366 } // end namespace compiler2
367 } // end namespace jit
368 } // end namespace cacao
369 
370 #endif /* _JIT_COMPILER2_MACHINEINSTRUCTION */
371 
372 
373 /*
374  * These are local overrides for various environment variables in Emacs.
375  * Please do not remove this and leave it at the end of the file, where
376  * Emacs will automagically detect them.
377  * ---------------------------------------------------------------------
378  * Local variables:
379  * mode: c++
380  * indent-tabs-mode: t
381  * c-basic-offset: 4
382  * tab-width: 4
383  * End:
384  * vim:noexpandtab:sw=4:ts=4:
385  */
embedded_operand_list::iterator operand_iterator
std::size_t index
MachineOperandDesc(MachineInstruction *parent, std::size_t index, MachineOperand *op)
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:127
Descriptor of a MachineOperand.
PassInfo::IDTy id
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
_Base::iterator iterator
const_successor_iterator successor_begin() const
const_successor_iterator successor_end() const
MachineOperandDesc(MachineInstruction *parent, MachineOperand *op)
void set_dummy_operand(EmbeddedMachineOperand *op)