aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto/machnode.hpp
blob: 5f8757c9adf9881833b0d1f1d3c9d2c928d70826 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
/*
 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_VM_OPTO_MACHNODE_HPP
#define SHARE_VM_OPTO_MACHNODE_HPP

#include "opto/callnode.hpp"
#include "opto/matcher.hpp"
#include "opto/multnode.hpp"
#include "opto/node.hpp"
#include "opto/regmask.hpp"

class BiasedLockingCounters;
class BufferBlob;
class CodeBuffer;
class JVMState;
class MachCallDynamicJavaNode;
class MachCallJavaNode;
class MachCallLeafNode;
class MachCallNode;
class MachCallRuntimeNode;
class MachCallStaticJavaNode;
class MachEpilogNode;
class MachIfNode;
class MachNullCheckNode;
class MachOper;
class MachProjNode;
class MachPrologNode;
class MachReturnNode;
class MachSafePointNode;
class MachSpillCopyNode;
class Matcher;
class PhaseRegAlloc;
class RegMask;
class RTMLockingCounters;
class State;

//---------------------------MachOper------------------------------------------
class MachOper : public ResourceObj {
public:
  // Allocate right next to the MachNodes in the same arena
  void *operator new( size_t x, Compile* C ) throw() { return C->node_arena()->Amalloc_D(x); }

  // Opcode
  virtual uint opcode() const = 0;

  // Number of input edges.
  // Generally at least 1
  virtual uint num_edges() const { return 1; }
  // Array of Register masks
  virtual const RegMask *in_RegMask(int index) const;

  // Methods to output the encoding of the operand

  // Negate conditional branches.  Error for non-branch Nodes
  virtual void negate();

  // Return the value requested
  // result register lookup, corresponding to int_format
  virtual int  reg(PhaseRegAlloc *ra_, const Node *node)   const;
  // input register lookup, corresponding to ext_format
  virtual int  reg(PhaseRegAlloc *ra_, const Node *node, int idx)   const;

  // helpers for MacroAssembler generation from ADLC
  Register  as_Register(PhaseRegAlloc *ra_, const Node *node)   const {
    return ::as_Register(reg(ra_, node));
  }
  Register  as_Register(PhaseRegAlloc *ra_, const Node *node, int idx)   const {
    return ::as_Register(reg(ra_, node, idx));
  }
  FloatRegister  as_FloatRegister(PhaseRegAlloc *ra_, const Node *node)   const {
    return ::as_FloatRegister(reg(ra_, node));
  }
  FloatRegister  as_FloatRegister(PhaseRegAlloc *ra_, const Node *node, int idx)   const {
    return ::as_FloatRegister(reg(ra_, node, idx));
  }

#if defined(IA32) || defined(AMD64)
  XMMRegister  as_XMMRegister(PhaseRegAlloc *ra_, const Node *node)   const {
    return ::as_XMMRegister(reg(ra_, node));
  }
  XMMRegister  as_XMMRegister(PhaseRegAlloc *ra_, const Node *node, int idx)   const {
    return ::as_XMMRegister(reg(ra_, node, idx));
  }
#endif
  // CondRegister reg converter
#if defined(PPC64)
  ConditionRegister as_ConditionRegister(PhaseRegAlloc *ra_, const Node *node) const {
    return ::as_ConditionRegister(reg(ra_, node));
  }
  ConditionRegister as_ConditionRegister(PhaseRegAlloc *ra_, const Node *node, int idx) const {
    return ::as_ConditionRegister(reg(ra_, node, idx));
  }
#endif

  virtual intptr_t  constant() const;
  virtual relocInfo::relocType constant_reloc() const;
  virtual jdouble constantD() const;
  virtual jfloat  constantF() const;
  virtual jlong   constantL() const;
  virtual TypeOopPtr *oop() const;
  virtual int  ccode() const;
  // A zero, default, indicates this value is not needed.
  // May need to lookup the base register, as done in int_ and ext_format
  virtual int  base (PhaseRegAlloc *ra_, const Node *node, int idx) const;
  virtual int  index(PhaseRegAlloc *ra_, const Node *node, int idx) const;
  virtual int  scale() const;
  // Parameters needed to support MEMORY_INTERFACE access to stackSlot
  virtual int  disp (PhaseRegAlloc *ra_, const Node *node, int idx) const;
  // Check for PC-Relative displacement
  virtual relocInfo::relocType disp_reloc() const;
  virtual int  constant_disp() const;   // usu. 0, may return Type::OffsetBot
  virtual int  base_position()  const;  // base edge position, or -1
  virtual int  index_position() const;  // index edge position, or -1

  // Access the TypeKlassPtr of operands with a base==RegI and disp==RegP
  // Only returns non-null value for i486.ad's indOffset32X
  virtual const TypePtr *disp_as_type() const { return NULL; }

  // Return the label
  virtual Label *label() const;

  // Return the method's address
  virtual intptr_t  method() const;

  // Hash and compare over operands are currently identical
  virtual uint  hash() const;
  virtual uint  cmp( const MachOper &oper ) const;

  // Virtual clone, since I do not know how big the MachOper is.
  virtual MachOper *clone(Compile* C) const = 0;

  // Return ideal Type from simple operands.  Fail for complex operands.
  virtual const Type *type() const;

  // Set an integer offset if we have one, or error otherwise
  virtual void set_con( jint c0 ) { ShouldNotReachHere();  }

#ifndef PRODUCT
  // Return name of operand
  virtual const char    *Name() const { return "???";}

  // Methods to output the text version of the operand
  virtual void int_format(PhaseRegAlloc *,const MachNode *node, outputStream *st) const = 0;
  virtual void ext_format(PhaseRegAlloc *,const MachNode *node,int idx, outputStream *st) const=0;

  virtual void dump_spec(outputStream *st) const; // Print per-operand info

  // Check whether o is a valid oper.
  static bool notAnOper(const MachOper *o) {
    if (o == NULL)                   return true;
    if (((intptr_t)o & 1) != 0)      return true;
    if (*(address*)o == badAddress)  return true;  // kill by Node::destruct
    return false;
  }
#endif // !PRODUCT
};

//------------------------------MachNode---------------------------------------
// Base type for all machine specific nodes.  All node classes generated by the
// ADLC inherit from this class.
class MachNode : public Node {
public:
  MachNode() : Node((uint)0), _num_opnds(0), _opnds(NULL) {
    init_class_id(Class_Mach);
  }
  // Required boilerplate
  virtual uint size_of() const { return sizeof(MachNode); }
  virtual int  Opcode() const;          // Always equal to MachNode
  virtual uint rule() const = 0;        // Machine-specific opcode
  // Number of inputs which come before the first operand.
  // Generally at least 1, to skip the Control input
  virtual uint oper_input_base() const { return 1; }
  // Position of constant base node in node's inputs. -1 if
  // no constant base node input.
  virtual uint mach_constant_base_node_input() const { return (uint)-1; }

  // Copy inputs and operands to new node of instruction.
  // Called from cisc_version() and short_branch_version().
  // !!!! The method's body is defined in ad_<arch>.cpp file.
  void fill_new_machnode(MachNode *n, Compile* C) const;

  // Return an equivalent instruction using memory for cisc_operand position
  virtual MachNode *cisc_version(int offset, Compile* C);
  // Modify this instruction's register mask to use stack version for cisc_operand
  virtual void use_cisc_RegMask();

  // Support for short branches
  bool may_be_short_branch() const { return (flags() & Flag_may_be_short_branch) != 0; }

  // Avoid back to back some instructions on some CPUs.
  enum AvoidBackToBackFlag { AVOID_NONE = 0,
                             AVOID_BEFORE = Flag_avoid_back_to_back_before,
                             AVOID_AFTER = Flag_avoid_back_to_back_after,
                             AVOID_BEFORE_AND_AFTER = AVOID_BEFORE | AVOID_AFTER };

  bool avoid_back_to_back(AvoidBackToBackFlag flag_value) const {
    return (flags() & flag_value) == flag_value;
  }

  // instruction implemented with a call
  bool has_call() const { return (flags() & Flag_has_call) != 0; }

  // First index in _in[] corresponding to operand, or -1 if there is none
  int  operand_index(uint operand) const;
  int  operand_index(const MachOper *oper) const;

  // Register class input is expected in
  virtual const RegMask &in_RegMask(uint) const;

  // cisc-spillable instructions redefine for use by in_RegMask
  virtual const RegMask *cisc_RegMask() const { return NULL; }

  // If this instruction is a 2-address instruction, then return the
  // index of the input which must match the output.  Not nessecary
  // for instructions which bind the input and output register to the
  // same singleton regiser (e.g., Intel IDIV which binds AX to be
  // both an input and an output).  It is nessecary when the input and
  // output have choices - but they must use the same choice.
  virtual uint two_adr( ) const { return 0; }

  // Array of complex operand pointers.  Each corresponds to zero or
  // more leafs.  Must be set by MachNode constructor to point to an
  // internal array of MachOpers.  The MachOper array is sized by
  // specific MachNodes described in the ADL.
  uint _num_opnds;
  MachOper **_opnds;
  uint  num_opnds() const { return _num_opnds; }

  // Emit bytes into cbuf
  virtual void  emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  // Expand node after register allocation.
  // Node is replaced by several nodes in the postalloc expand phase.
  // Corresponding methods are generated for nodes if they specify
  // postalloc_expand. See block.cpp for more documentation.
  virtual bool requires_postalloc_expand() const { return false; }
  virtual void postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_);
  // Size of instruction in bytes
  virtual uint  size(PhaseRegAlloc *ra_) const;
  // Helper function that computes size by emitting code
  virtual uint  emit_size(PhaseRegAlloc *ra_) const;

  // Return the alignment required (in units of relocInfo::addr_unit())
  // for this instruction (must be a power of 2)
  virtual int   alignment_required() const { return 1; }

  // Return the padding (in bytes) to be emitted before this
  // instruction to properly align it.
  virtual int   compute_padding(int current_offset) const { return 0; }

  // Return number of relocatable values contained in this instruction
  virtual int   reloc() const { return 0; }

  // Return number of words used for double constants in this instruction
  virtual int   ins_num_consts() const { return 0; }

  // Hash and compare over operands.  Used to do GVN on machine Nodes.
  virtual uint  hash() const;
  virtual uint  cmp( const Node &n ) const;

  // Expand method for MachNode, replaces nodes representing pseudo
  // instructions with a set of nodes which represent real machine
  // instructions and compute the same value.
  virtual MachNode *Expand( State *, Node_List &proj_list, Node* mem ) { return this; }

  // Bottom_type call; value comes from operand0
  virtual const class Type *bottom_type() const { return _opnds[0]->type(); }
  virtual uint ideal_reg() const { const Type *t = _opnds[0]->type(); return t == TypeInt::CC ? Op_RegFlags : t->ideal_reg(); }

  // If this is a memory op, return the base pointer and fixed offset.
  // If there are no such, return NULL.  If there are multiple addresses
  // or the address is indeterminate (rare cases) then return (Node*)-1,
  // which serves as node bottom.
  // If the offset is not statically determined, set it to Type::OffsetBot.
  // This method is free to ignore stack slots if that helps.
  #define TYPE_PTR_SENTINAL  ((const TypePtr*)-1)
  // Passing TYPE_PTR_SENTINAL as adr_type asks for computation of the adr_type if possible
  const Node* get_base_and_disp(intptr_t &offset, const TypePtr* &adr_type) const;

  // Helper for get_base_and_disp: find the base and index input nodes.
  // Returns the MachOper as determined by memory_operand(), for use, if
  // needed by the caller. If (MachOper *)-1 is returned, base and index
  // are set to NodeSentinel. If (MachOper *) NULL is returned, base and
  // index are set to NULL.
  const MachOper* memory_inputs(Node* &base, Node* &index) const;

  // Helper for memory_inputs:  Which operand carries the necessary info?
  // By default, returns NULL, which means there is no such operand.
  // If it returns (MachOper*)-1, this means there are multiple memories.
  virtual const MachOper* memory_operand() const { return NULL; }

  // Call "get_base_and_disp" to decide which category of memory is used here.
  virtual const class TypePtr *adr_type() const;

  // Apply peephole rule(s) to this instruction
  virtual MachNode *peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C );

  // Top-level ideal Opcode matched
  virtual int ideal_Opcode()     const { return Op_Node; }

  // Adds the label for the case
  virtual void add_case_label( int switch_val, Label* blockLabel);

  // Set the absolute address for methods
  virtual void method_set( intptr_t addr );

  // Should we clone rather than spill this instruction?
  bool rematerialize() const;

  // Get the pipeline info
  static const Pipeline *pipeline_class();
  virtual const Pipeline *pipeline() const;

  // Returns true if this node is a check that can be implemented with a trap.
  virtual bool is_TrapBasedCheckNode() const { return false; }

#ifndef PRODUCT
  virtual const char *Name() const = 0; // Machine-specific name
  virtual void dump_spec(outputStream *st) const; // Print per-node info
  void         dump_format(PhaseRegAlloc *ra, outputStream *st) const; // access to virtual
#endif
};

//------------------------------MachIdealNode----------------------------
// Machine specific versions of nodes that must be defined by user.
// These are not converted by matcher from ideal nodes to machine nodes
// but are inserted into the code by the compiler.
class MachIdealNode : public MachNode {
public:
  MachIdealNode( ) {}

  // Define the following defaults for non-matched machine nodes
  virtual uint oper_input_base() const { return 0; }
  virtual uint rule()            const { return 9999999; }
  virtual const class Type *bottom_type() const { return _opnds == NULL ? Type::CONTROL : MachNode::bottom_type(); }
};

//------------------------------MachTypeNode----------------------------
// Machine Nodes that need to retain a known Type.
class MachTypeNode : public MachNode {
  virtual uint size_of() const { return sizeof(*this); } // Size is bigger
public:
  MachTypeNode( ) {}
  const Type *_bottom_type;

  virtual const class Type *bottom_type() const { return _bottom_type; }
#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
#endif
};

//------------------------------MachBreakpointNode----------------------------
// Machine breakpoint or interrupt Node
class MachBreakpointNode : public MachIdealNode {
public:
  MachBreakpointNode( ) {}
  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual uint size(PhaseRegAlloc *ra_) const;

#ifndef PRODUCT
  virtual const char *Name() const { return "Breakpoint"; }
  virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif
};

//------------------------------MachConstantBaseNode--------------------------
// Machine node that represents the base address of the constant table.
class MachConstantBaseNode : public MachIdealNode {
public:
  static const RegMask& _out_RegMask;  // We need the out_RegMask statically in MachConstantNode::in_RegMask().

public:
  MachConstantBaseNode() : MachIdealNode() {
    init_class_id(Class_MachConstantBase);
  }
  virtual const class Type* bottom_type() const { return TypeRawPtr::NOTNULL; }
  virtual uint ideal_reg() const { return Op_RegP; }
  virtual uint oper_input_base() const { return 1; }

  virtual bool requires_postalloc_expand() const;
  virtual void postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_);

  virtual void emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const;
  virtual uint size(PhaseRegAlloc* ra_) const;
  virtual bool pinned() const { return UseRDPCForConstantTableBase; }

  static const RegMask& static_out_RegMask() { return _out_RegMask; }
  virtual const RegMask& out_RegMask() const { return static_out_RegMask(); }

#ifndef PRODUCT
  virtual const char* Name() const { return "MachConstantBaseNode"; }
  virtual void format(PhaseRegAlloc*, outputStream* st) const;
#endif
};

//------------------------------MachConstantNode-------------------------------
// Machine node that holds a constant which is stored in the constant table.
class MachConstantNode : public MachTypeNode {
protected:
  Compile::Constant _constant;  // This node's constant.

public:
  MachConstantNode() : MachTypeNode() {
    init_class_id(Class_MachConstant);
  }

  virtual void eval_constant(Compile* C) {
#ifdef ASSERT
    tty->print("missing MachConstantNode eval_constant function: ");
    dump();
#endif
    ShouldNotCallThis();
  }

  virtual const RegMask &in_RegMask(uint idx) const {
    if (idx == mach_constant_base_node_input())
      return MachConstantBaseNode::static_out_RegMask();
    return MachNode::in_RegMask(idx);
  }

  // Input edge of MachConstantBaseNode.
  virtual uint mach_constant_base_node_input() const { return req() - 1; }

  int  constant_offset();
  int  constant_offset() const { return ((MachConstantNode*) this)->constant_offset(); }
  // Unchecked version to avoid assertions in debug output.
  int  constant_offset_unchecked() const;
};

//------------------------------MachUEPNode-----------------------------------
// Machine Unvalidated Entry Point Node
class MachUEPNode : public MachIdealNode {
public:
  MachUEPNode( ) {}
  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual uint size(PhaseRegAlloc *ra_) const;

#ifndef PRODUCT
  virtual const char *Name() const { return "Unvalidated-Entry-Point"; }
  virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif
};

//------------------------------MachPrologNode--------------------------------
// Machine function Prolog Node
class MachPrologNode : public MachIdealNode {
public:
  MachPrologNode( ) {}
  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual uint size(PhaseRegAlloc *ra_) const;
  virtual int reloc() const;

#ifndef PRODUCT
  virtual const char *Name() const { return "Prolog"; }
  virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif
};

//------------------------------MachEpilogNode--------------------------------
// Machine function Epilog Node
class MachEpilogNode : public MachIdealNode {
public:
  MachEpilogNode(bool do_poll = false) : _do_polling(do_poll) {}
  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual uint size(PhaseRegAlloc *ra_) const;
  virtual int reloc() const;
  virtual const Pipeline *pipeline() const;

private:
  bool _do_polling;

public:
  bool do_polling() const { return _do_polling; }

  // Offset of safepoint from the beginning of the node
  int safepoint_offset() const;

#ifndef PRODUCT
  virtual const char *Name() const { return "Epilog"; }
  virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif
};

//------------------------------MachNopNode-----------------------------------
// Machine function Nop Node
class MachNopNode : public MachIdealNode {
private:
  int _count;
public:
  MachNopNode( ) : _count(1) {}
  MachNopNode( int count ) : _count(count) {}
  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual uint size(PhaseRegAlloc *ra_) const;

  virtual const class Type *bottom_type() const { return Type::CONTROL; }

  virtual int ideal_Opcode() const { return Op_Con; } // bogus; see output.cpp
  virtual const Pipeline *pipeline() const;
#ifndef PRODUCT
  virtual const char *Name() const { return "Nop"; }
  virtual void format( PhaseRegAlloc *, outputStream *st ) const;
  virtual void dump_spec(outputStream *st) const { } // No per-operand info
#endif
};

//------------------------------MachSpillCopyNode------------------------------
// Machine SpillCopy Node.  Copies 1 or 2 words from any location to any
// location (stack or register).
class MachSpillCopyNode : public MachIdealNode {
  const RegMask *_in;           // RegMask for input
  const RegMask *_out;          // RegMask for output
  const Type *_type;
public:
  MachSpillCopyNode( Node *n, const RegMask &in, const RegMask &out ) :
    MachIdealNode(), _in(&in), _out(&out), _type(n->bottom_type()) {
    init_class_id(Class_MachSpillCopy);
    init_flags(Flag_is_Copy);
    add_req(NULL);
    add_req(n);
  }
  virtual uint size_of() const { return sizeof(*this); }
  void set_out_RegMask(const RegMask &out) { _out = &out; }
  void set_in_RegMask(const RegMask &in) { _in = &in; }
  virtual const RegMask &out_RegMask() const { return *_out; }
  virtual const RegMask &in_RegMask(uint) const { return *_in; }
  virtual const class Type *bottom_type() const { return _type; }
  virtual uint ideal_reg() const { return _type->ideal_reg(); }
  virtual uint oper_input_base() const { return 1; }
  uint implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const;

  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual uint size(PhaseRegAlloc *ra_) const;

#ifndef PRODUCT
  virtual const char *Name() const { return "MachSpillCopy"; }
  virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif
};

// MachMergeNode is similar to a PhiNode in a sense it merges multiple values,
// however it doesn't have a control input and is more like a MergeMem.
// It is inserted after the register allocation is done to ensure that nodes use single
// definition of a multidef lrg in a block.
class MachMergeNode : public MachIdealNode {
public:
  MachMergeNode(Node *n1) {
    init_class_id(Class_MachMerge);
    add_req(NULL);
    add_req(n1);
  }
  virtual const RegMask &out_RegMask() const { return in(1)->out_RegMask(); }
  virtual const RegMask &in_RegMask(uint idx) const { return in(1)->in_RegMask(idx); }
  virtual const class Type *bottom_type() const { return in(1)->bottom_type(); }
  virtual uint ideal_reg() const { return bottom_type()->ideal_reg(); }
  virtual uint oper_input_base() const { return 1; }
  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
  virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
#ifndef PRODUCT
  virtual const char *Name() const { return "MachMerge"; }
#endif
};

//------------------------------MachBranchNode--------------------------------
// Abstract machine branch Node
class MachBranchNode : public MachIdealNode {
public:
  MachBranchNode() : MachIdealNode() {
    init_class_id(Class_MachBranch);
  }
  virtual void label_set(Label* label, uint block_num) = 0;
  virtual void save_label(Label** label, uint* block_num) = 0;

  // Support for short branches
  virtual MachNode *short_branch_version(Compile* C) { return NULL; }

  virtual bool pinned() const { return true; };
};

//------------------------------MachNullChkNode--------------------------------
// Machine-dependent null-pointer-check Node.  Points a real MachNode that is
// also some kind of memory op.  Turns the indicated MachNode into a
// conditional branch with good latency on the ptr-not-null path and awful
// latency on the pointer-is-null path.

class MachNullCheckNode : public MachBranchNode {
public:
  const uint _vidx;             // Index of memop being tested
  MachNullCheckNode( Node *ctrl, Node *memop, uint vidx ) : MachBranchNode(), _vidx(vidx) {
    init_class_id(Class_MachNullCheck);
    add_req(ctrl);
    add_req(memop);
  }
  virtual uint size_of() const { return sizeof(*this); }

  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual void label_set(Label* label, uint block_num);
  virtual void save_label(Label** label, uint* block_num);
  virtual void negate() { }
  virtual const class Type *bottom_type() const { return TypeTuple::IFBOTH; }
  virtual uint ideal_reg() const { return NotAMachineReg; }
  virtual const RegMask &in_RegMask(uint) const;
  virtual const RegMask &out_RegMask() const { return RegMask::Empty; }
#ifndef PRODUCT
  virtual const char *Name() const { return "NullCheck"; }
  virtual void format( PhaseRegAlloc *, outputStream *st ) const;
#endif
};

//------------------------------MachProjNode----------------------------------
// Machine-dependent Ideal projections (how is that for an oxymoron).  Really
// just MachNodes made by the Ideal world that replicate simple projections
// but with machine-dependent input & output register masks.  Generally
// produced as part of calling conventions.  Normally I make MachNodes as part
// of the Matcher process, but the Matcher is ill suited to issues involving
// frame handling, so frame handling is all done in the Ideal world with
// occasional callbacks to the machine model for important info.
class MachProjNode : public ProjNode {
public:
  MachProjNode( Node *multi, uint con, const RegMask &out, uint ideal_reg ) : ProjNode(multi,con), _rout(out), _ideal_reg(ideal_reg) {
    init_class_id(Class_MachProj);
  }
  RegMask _rout;
  const uint  _ideal_reg;
  enum projType {
    unmatched_proj = 0,         // Projs for Control, I/O, memory not matched
    fat_proj       = 999        // Projs killing many regs, defined by _rout
  };
  virtual int   Opcode() const;
  virtual const Type *bottom_type() const;
  virtual const TypePtr *adr_type() const;
  virtual const RegMask &in_RegMask(uint) const { return RegMask::Empty; }
  virtual const RegMask &out_RegMask() const { return _rout; }
  virtual uint  ideal_reg() const { return _ideal_reg; }
  // Need size_of() for virtual ProjNode::clone()
  virtual uint  size_of() const { return sizeof(MachProjNode); }
#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
#endif
};

//------------------------------MachIfNode-------------------------------------
// Machine-specific versions of IfNodes
class MachIfNode : public MachBranchNode {
  virtual uint size_of() const { return sizeof(*this); } // Size is bigger
public:
  float _prob;                  // Probability branch goes either way
  float _fcnt;                  // Frequency counter
  MachIfNode() : MachBranchNode() {
    init_class_id(Class_MachIf);
  }
  // Negate conditional branches.
  virtual void negate() = 0;
#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
#endif
};

//------------------------------MachGotoNode-----------------------------------
// Machine-specific versions of GotoNodes
class MachGotoNode : public MachBranchNode {
public:
  MachGotoNode() : MachBranchNode() {
    init_class_id(Class_MachGoto);
  }
};

//------------------------------MachFastLockNode-------------------------------------
// Machine-specific versions of FastLockNodes
class MachFastLockNode : public MachNode {
  virtual uint size_of() const { return sizeof(*this); } // Size is bigger
public:
  BiasedLockingCounters*        _counters;
  RTMLockingCounters*       _rtm_counters; // RTM lock counters for inflated locks
  RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks
  MachFastLockNode() : MachNode() {}
};

//------------------------------MachReturnNode--------------------------------
// Machine-specific versions of subroutine returns
class MachReturnNode : public MachNode {
  virtual uint size_of() const; // Size is bigger
public:
  RegMask *_in_rms;             // Input register masks, set during allocation
  ReallocMark _nesting;         // assertion check for reallocations
  const TypePtr* _adr_type;     // memory effects of call or return
  MachReturnNode() : MachNode() {
    init_class_id(Class_MachReturn);
    _adr_type = TypePtr::BOTTOM; // the default: all of memory
  }

  void set_adr_type(const TypePtr* atp) { _adr_type = atp; }

  virtual const RegMask &in_RegMask(uint) const;
  virtual bool pinned() const { return true; };
  virtual const TypePtr *adr_type() const;
};

//------------------------------MachSafePointNode-----------------------------
// Machine-specific versions of safepoints
class MachSafePointNode : public MachReturnNode {
public:
  OopMap*         _oop_map;     // Array of OopMap info (8-bit char) for GC
  JVMState*       _jvms;        // Pointer to list of JVM State Objects
  uint            _jvmadj;      // Extra delta to jvms indexes (mach. args)
  OopMap*         oop_map() const { return _oop_map; }
  void            set_oop_map(OopMap* om) { _oop_map = om; }

  MachSafePointNode() : MachReturnNode(), _oop_map(NULL), _jvms(NULL), _jvmadj(0) {
    init_class_id(Class_MachSafePoint);
  }

  virtual JVMState* jvms() const { return _jvms; }
  void set_jvms(JVMState* s) {
    _jvms = s;
  }
  virtual const Type    *bottom_type() const;

  virtual const RegMask &in_RegMask(uint) const;

  // Functionality from old debug nodes
  Node *returnadr() const { return in(TypeFunc::ReturnAdr); }
  Node *frameptr () const { return in(TypeFunc::FramePtr); }

  Node *local(const JVMState* jvms, uint idx) const {
    assert(verify_jvms(jvms), "jvms must match");
    return in(_jvmadj + jvms->locoff() + idx);
  }
  Node *stack(const JVMState* jvms, uint idx) const {
    assert(verify_jvms(jvms), "jvms must match");
    return in(_jvmadj + jvms->stkoff() + idx);
 }
  Node *monitor_obj(const JVMState* jvms, uint idx) const {
    assert(verify_jvms(jvms), "jvms must match");
    return in(_jvmadj + jvms->monitor_obj_offset(idx));
  }
  Node *monitor_box(const JVMState* jvms, uint idx) const {
    assert(verify_jvms(jvms), "jvms must match");
    return in(_jvmadj + jvms->monitor_box_offset(idx));
  }
  void  set_local(const JVMState* jvms, uint idx, Node *c) {
    assert(verify_jvms(jvms), "jvms must match");
    set_req(_jvmadj + jvms->locoff() + idx, c);
  }
  void  set_stack(const JVMState* jvms, uint idx, Node *c) {
    assert(verify_jvms(jvms), "jvms must match");
    set_req(_jvmadj + jvms->stkoff() + idx, c);
  }
  void  set_monitor(const JVMState* jvms, uint idx, Node *c) {
    assert(verify_jvms(jvms), "jvms must match");
    set_req(_jvmadj + jvms->monoff() + idx, c);
  }
};

//------------------------------MachCallNode----------------------------------
// Machine-specific versions of subroutine calls
class MachCallNode : public MachSafePointNode {
protected:
  virtual uint hash() const { return NO_HASH; }  // CFG nodes do not hash
  virtual uint cmp( const Node &n ) const;
  virtual uint size_of() const = 0; // Size is bigger
public:
  const TypeFunc *_tf;        // Function type
  address      _entry_point;  // Address of the method being called
  float        _cnt;          // Estimate of number of times called
  uint         _argsize;      // Size of argument block on stack

  const TypeFunc* tf()        const { return _tf; }
  const address entry_point() const { return _entry_point; }
  const float   cnt()         const { return _cnt; }
  uint argsize()              const { return _argsize; }

  void set_tf(const TypeFunc* tf) { _tf = tf; }
  void set_entry_point(address p) { _entry_point = p; }
  void set_cnt(float c)           { _cnt = c; }
  void set_argsize(int s)         { _argsize = s; }

  MachCallNode() : MachSafePointNode() {
    init_class_id(Class_MachCall);
  }

  virtual const Type *bottom_type() const;
  virtual bool  pinned() const { return false; }
  virtual const Type *Value( PhaseTransform *phase ) const;
  virtual const RegMask &in_RegMask(uint) const;
  virtual int ret_addr_offset() { return 0; }

  bool returns_long() const { return tf()->return_type() == T_LONG; }
  bool return_value_is_used() const;

  // Similar to cousin class CallNode::returns_pointer
  bool returns_pointer() const;

#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
#endif
};

//------------------------------MachCallJavaNode------------------------------
// "Base" class for machine-specific versions of subroutine calls
class MachCallJavaNode : public MachCallNode {
protected:
  virtual uint cmp( const Node &n ) const;
  virtual uint size_of() const; // Size is bigger
public:
  ciMethod* _method;             // Method being direct called
  int        _bci;               // Byte Code index of call byte code
  bool       _optimized_virtual; // Tells if node is a static call or an optimized virtual
  bool       _method_handle_invoke;   // Tells if the call has to preserve SP
  MachCallJavaNode() : MachCallNode() {
    init_class_id(Class_MachCallJava);
  }

  virtual const RegMask &in_RegMask(uint) const;

#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
#endif
};

//------------------------------MachCallStaticJavaNode------------------------
// Machine-specific versions of monomorphic subroutine calls
class MachCallStaticJavaNode : public MachCallJavaNode {
  virtual uint cmp( const Node &n ) const;
  virtual uint size_of() const; // Size is bigger
public:
  const char *_name;            // Runtime wrapper name
  MachCallStaticJavaNode() : MachCallJavaNode() {
    init_class_id(Class_MachCallStaticJava);
  }

  // If this is an uncommon trap, return the request code, else zero.
  int uncommon_trap_request() const;

  virtual int ret_addr_offset();
#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
  void dump_trap_args(outputStream *st) const;
#endif
};

//------------------------------MachCallDynamicJavaNode------------------------
// Machine-specific versions of possibly megamorphic subroutine calls
class MachCallDynamicJavaNode : public MachCallJavaNode {
public:
  int _vtable_index;
  MachCallDynamicJavaNode() : MachCallJavaNode() {
    init_class_id(Class_MachCallDynamicJava);
    DEBUG_ONLY(_vtable_index = -99);  // throw an assert if uninitialized
  }
  virtual int ret_addr_offset();
#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
#endif
};

//------------------------------MachCallRuntimeNode----------------------------
// Machine-specific versions of subroutine calls
class MachCallRuntimeNode : public MachCallNode {
  virtual uint cmp( const Node &n ) const;
  virtual uint size_of() const; // Size is bigger
public:
  const char *_name;            // Printable name, if _method is NULL
  MachCallRuntimeNode() : MachCallNode() {
    init_class_id(Class_MachCallRuntime);
  }
  virtual int ret_addr_offset();
#ifndef PRODUCT
  virtual void dump_spec(outputStream *st) const;
#endif
};

class MachCallLeafNode: public MachCallRuntimeNode {
public:
  MachCallLeafNode() : MachCallRuntimeNode() {
    init_class_id(Class_MachCallLeaf);
  }
};

//------------------------------MachHaltNode-----------------------------------
// Machine-specific versions of halt nodes
class MachHaltNode : public MachReturnNode {
public:
  virtual JVMState* jvms() const;
};


//------------------------------MachTempNode-----------------------------------
// Node used by the adlc to construct inputs to represent temporary registers
class MachTempNode : public MachNode {
private:
  MachOper *_opnd_array[1];

public:
  virtual const RegMask &out_RegMask() const { return *_opnds[0]->in_RegMask(0); }
  virtual uint rule() const { return 9999999; }
  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {}

  MachTempNode(MachOper* oper) {
    init_class_id(Class_MachTemp);
    _num_opnds = 1;
    _opnds = _opnd_array;
    add_req(NULL);
    _opnds[0] = oper;
  }
  virtual uint size_of() const { return sizeof(MachTempNode); }

#ifndef PRODUCT
  virtual void format(PhaseRegAlloc *, outputStream *st ) const {}
  virtual const char *Name() const { return "MachTemp";}
#endif
};



//------------------------------labelOper--------------------------------------
// Machine-independent version of label operand
class labelOper : public MachOper {
private:
  virtual uint           num_edges() const { return 0; }
public:
  // Supported for fixed size branches
  Label* _label;                // Label for branch(es)

  uint _block_num;

  labelOper() : _block_num(0), _label(0) {}

  labelOper(Label* label, uint block_num) : _label(label), _block_num(block_num) {}

  labelOper(labelOper* l) : _label(l->_label) , _block_num(l->_block_num) {}

  virtual MachOper *clone(Compile* C) const;

  virtual Label *label() const { assert(_label != NULL, "need Label"); return _label; }

  virtual uint           opcode() const;

  virtual uint           hash()   const;
  virtual uint           cmp( const MachOper &oper ) const;
#ifndef PRODUCT
  virtual const char    *Name()   const { return "Label";}

  virtual void int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const;
  virtual void ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const { int_format( ra, node, st ); }
#endif
};


//------------------------------methodOper--------------------------------------
// Machine-independent version of method operand
class methodOper : public MachOper {
private:
  virtual uint           num_edges() const { return 0; }
public:
  intptr_t _method;             // Address of method
  methodOper() :   _method(0) {}
  methodOper(intptr_t method) : _method(method)  {}

  virtual MachOper *clone(Compile* C) const;

  virtual intptr_t method() const { return _method; }

  virtual uint           opcode() const;

  virtual uint           hash()   const;
  virtual uint           cmp( const MachOper &oper ) const;
#ifndef PRODUCT
  virtual const char    *Name()   const { return "Method";}

  virtual void int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const;
  virtual void ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const { int_format( ra, node, st ); }
#endif
};

#endif // SHARE_VM_OPTO_MACHNODE_HPP