aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/adlc/forms.hpp
blob: 073ca4c810d03af7be39d60e177bebbc3565eaec (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
/*
 * Copyright (c) 1997, 2013, 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_ADLC_FORMS_HPP
#define SHARE_VM_ADLC_FORMS_HPP

// FORMS.HPP - ADL Parser Generic and Utility Forms Classes

#define TRUE 1
#define FALSE 0

// DEFINITIONS OF LEGAL ATTRIBUTE TYPES
#define INS_ATTR 0
#define OP_ATTR  1

// DEFINITIONS OF LEGAL CONSTRAINT TYPES

// Class List
class Form;
class InstructForm;
class MachNodeForm;
class OperandForm;
class OpClassForm;
class AttributeForm;
class RegisterForm;
class PipelineForm;
class SourceForm;
class EncodeForm;
class Component;
class Constraint;
class Predicate;
class MatchRule;
class Attribute;
class Effect;
class ExpandRule;
class RewriteRule;
class ConstructRule;
class FormatRule;
class Peephole;
class EncClass;
class Interface;
class RegInterface;
class ConstInterface;
class MemInterface;
class CondInterface;
class Opcode;
class InsEncode;
class RegDef;
class RegClass;
class CodeSnippetRegClass;
class ConditionalRegClass;
class AllocClass;
class ResourceForm;
class PipeClassForm;
class PeepMatch;
class PeepConstraint;
class PeepReplace;
class MatchList;

class ArchDesc;

//------------------------------FormDict---------------------------------------
// Dictionary containing Forms, and objects derived from forms
class FormDict {
private:
  Dict         _form;              // map names, char*, to their Form* or NULL

  // Disable public use of constructor, copy-ctor, operator =, operator ==
  FormDict( );
  FormDict &operator =( const FormDict & );
  // == compares two dictionaries; they must have the same keys (their keys
  // must match using CmpKey) and they must have the same values (pointer
  // comparison).  If so 1 is returned, if not 0 is returned.
  bool operator ==(const FormDict &d) const; // Compare dictionaries for equal

public:
  // cmp is a key comparision routine.  hash is a routine to hash a key.
  // FormDict( CmpKey cmp, Hash hash );
  FormDict( CmpKey cmp, Hash hash, Arena *arena );
  FormDict( const FormDict & fd );    // Deep-copy guts
  ~FormDict();

  // Return # of key-value pairs in dict
  int Size(void) const;

  // Insert inserts the given key-value pair into the dictionary.  The prior
  // value of the key is returned; NULL if the key was not previously defined.
  const Form  *Insert(const char *name, Form *form); // A new key-value

  // Find finds the value of a given key; or NULL if not found.
  // The dictionary is NOT changed.
  const Form  *operator [](const char *name) const;  // Do a lookup

  void dump();
};

// ***** Master Class for ADL Parser Forms *****
//------------------------------Form-------------------------------------------
class Form {
public:
  static Arena  *arena;            // arena used by forms
private:
  static Arena  *generate_arena(); // allocate arena used by forms

protected:
  int   _ftype;                    // Indicator for derived class type

public:
  // Public Data
  Form *_next;                     // Next pointer for form lists
  int   _linenum;                  // Line number for debugging

  // Dynamic type check for common forms.
  virtual OpClassForm   *is_opclass()     const;
  virtual OperandForm   *is_operand()     const;
  virtual InstructForm  *is_instruction() const;
  virtual MachNodeForm  *is_machnode()    const;
  virtual AttributeForm *is_attribute()   const;
  virtual Effect        *is_effect()      const;
  virtual ResourceForm  *is_resource()    const;
  virtual PipeClassForm *is_pipeclass()   const;

  // Check if this form is an operand usable for cisc-spilling
  virtual bool           is_cisc_reg(FormDict &globals) const { return false; }
  virtual bool           is_cisc_mem(FormDict &globals) const { return false; }

  // Public Methods
  Form(int formType=0, int line=0)
    : _next(NULL), _linenum(line), _ftype(formType) { };
  virtual ~Form() {};

  virtual bool ideal_only() const {
    assert(0,"Check of ideal status on non-instruction/operand form.\n");
    return FALSE;
  }

  // Check constraints after parsing
  virtual bool verify()    { return true; }

  virtual void dump()      { output(stderr); }    // Debug printer
  // Write info to output files
  virtual void output(FILE *fp)    { fprintf(fp,"Form Output"); }

public:
  // ADLC types, match the last character on ideal operands and instructions
  enum DataType {
    none        =  0,  // Not a simple type
    idealI      =  1,  // Integer type
    idealP      =  2,  // Pointer types, oop(s)
    idealL      =  3,  // Long    type
    idealF      =  4,  // Float   type
    idealD      =  5,  // Double  type
    idealB      =  6,  // Byte    type
    idealC      =  7,  // Char    type
    idealS      =  8,  // String  type
    idealN      =  9,  // Narrow oop types
    idealNKlass = 10,  // Narrow klass types
    idealV      = 11   // Vector  type
  };
  // Convert ideal name to a DataType, return DataType::none if not a 'ConX'
  Form::DataType  ideal_to_const_type(const char *ideal_type_name) const;
  // Convert ideal name to a DataType, return DataType::none if not a 'sRegX
  Form::DataType  ideal_to_sReg_type(const char *name) const;
  // Convert ideal name to a DataType, return DataType::none if not a 'RegX
  Form::DataType  ideal_to_Reg_type(const char *name) const;

  // Convert ideal name to a DataType, return DataType::none if not a 'LoadX
  Form::DataType is_load_from_memory(const char *opType) const;
  // Convert ideal name to a DataType, return DataType::none if not a 'StoreX
  Form::DataType is_store_to_memory(const char *opType)  const;

  // ADLC call types, matched with ideal world
  enum CallType {
    invalid_type  =  0,  // invalid call type
    JAVA_STATIC   =  1,  // monomorphic entry
    JAVA_DYNAMIC  =  2,  // possibly megamorphic, inline cache call
    JAVA_COMPILED =  3,  // callee will be compiled java
    JAVA_INTERP   =  4,  // callee will be executed by interpreter
    JAVA_NATIVE   =  5,  // native entrypoint
    JAVA_RUNTIME  =  6,  // runtime entrypoint
    JAVA_LEAF     =  7   // calling leaf
  };

  // Interface types for operands and operand classes
  enum InterfaceType {
    no_interface          =  0,  // unknown or inconsistent interface type
    constant_interface    =  1,  // interface to constants
    register_interface    =  2,  // interface to registers
    memory_interface      =  3,  // interface to memory
    conditional_interface =  4   // interface for condition codes
  };
  virtual Form::InterfaceType interface_type(FormDict &globals) const;

  enum CiscSpillInfo {
    Not_cisc_spillable   =  AdlcVMDeps::Not_cisc_spillable,
    Maybe_cisc_spillable =   0,
    Is_cisc_spillable    =   1
    // ...
  };

  // LEGAL FORM TYPES
  enum {
    INS,
    OPER,
    OPCLASS,
    SRC,
    ADEF,
    REG,
    PIPE,
    CNST,
    PRED,
    ATTR,
    MAT,
    ENC,
    FOR,
    EXP,
    REW,
    EFF,
    RDEF,
    RCL,
    ACL,
    RES,
    PCL,
    PDEF,
    REGL,
    RESL,
    STAL,
    COMP,
    PEEP,
    RESO
  };

};

//------------------------------FormList---------------------------------------
class FormList {
private:
  Form *_root;
  Form *_tail;
  Form *_cur;
  int   _justReset;                // Set immediately after reset
  Form *_cur2;                     // Nested iterator
  int   _justReset2;

public:
  void addForm(Form * entry) {
    if (_tail==NULL) { _root = _tail = _cur = entry;}
    else { _tail->_next = entry; _tail = entry;}
  };
  Form * current() { return _cur; };
  Form * iter()    { if (_justReset) _justReset = 0;
                     else if (_cur)  _cur = _cur->_next;
                     return _cur;};
  void   reset()   { if (_root) {_cur = _root; _justReset = 1;} };

  // Second iterator, state is internal
  Form * current2(){ return _cur2; };
  Form * iter2()   { if (_justReset2) _justReset2 = 0;
                    else if (_cur2)  _cur2 = _cur2->_next;
                    return _cur2;};
  void   reset2()  { if (_root) {_cur2 = _root; _justReset2 = 1;} };

  int  count() {
    int  count = 0; reset();
    for( Form *cur; (cur =  iter()) != NULL; ) { ++count; };
    return count;
  }

  void dump() {
    reset();
    Form *cur;
    for(; (cur =  iter()) != NULL; ) {
      cur->dump();
    };
  }

  bool verify() {
    bool verified = true;

    reset();
    Form *cur;
    for(; (cur =  iter()) != NULL; ) {
      if ( ! cur->verify() ) verified = false;
    };

    return verified;
  }

  void output(FILE* fp) {
    reset();
    Form *cur;
    for( ; (cur =  iter()) != NULL; ) {
      cur->output(fp);
    };
  }

  FormList() { _justReset = 1; _justReset2 = 1; _root = NULL; _tail = NULL; _cur = NULL; _cur2 = NULL;};
  ~FormList();
};

//------------------------------NameList---------------------------------------
// Extendable list of pointers, <char *>
class NameList {
  friend class PreserveIter;

private:
  int                _cur;         // Insert next entry here; count of entries
  int                _max;         // Number of spaces allocated
  const char       **_names;       // Array of names

protected:
  int                _iter;        // position during iteration
  bool               _justReset;   // Set immediately after reset


public:
  static const char *_signal;      // reserved user-defined string
  static const char *_signal2;      // reserved user-defined string
  static const char *_signal3;      // reserved user-defined string
  enum               { Not_in_list = -1 };

  void  addName(const char *name);
  void  add_signal();
  void  clear();                   // Remove all entries

  int   count() const;

  void  reset();                   // Reset iteration
  const char *iter();              // after reset(), first element : else next
  const char *current();           // return current element in iteration.
  const char *peek(int skip = 1);  // returns element + skip in iteration if there is one

  bool  current_is_signal();       // Return 'true' if current entry is signal
  bool  is_signal(const char *entry); // Return true if entry is a signal

  bool  search(const char *);      // Search for a name in the list
  int   index(const char *);       // Return index of name in list
  const char *name (intptr_t index);// Return name at index in list

  void  dump();                    // output to stderr
  void  output(FILE *fp);          // Output list of names to 'fp'

  NameList();
  ~NameList();
};


// Convenience class to preserve iteration state since iterators are
// internal instead of being external.
class PreserveIter {
 private:
  NameList* _list;
  int _iter;
  bool _justReset;

 public:
  PreserveIter(NameList* nl) {
    _list = nl;
    _iter = _list->_iter;
    _justReset = _list->_justReset;
  }
  ~PreserveIter() {
    _list->_iter = _iter;
    _list->_justReset = _justReset;
  }

};


//------------------------------NameAndList------------------------------------
// Storage for a name and an associated list of names
class NameAndList {
private:
  const char *_name;
  NameList    _list;

public:
  NameAndList(char *name);
  ~NameAndList();

  // Add to entries in list
  void        add_entry(const char *entry);

  // Access the name and its associated list.
  const char *name() const;
  void        reset();
  const char *iter();

  int count() { return _list.count(); }

  // Return the "index" entry in the list, zero-based
  const char *operator[](int index);


  void  dump();                    // output to stderr
  void  output(FILE *fp);          // Output list of names to 'fp'
};

//------------------------------ComponentList---------------------------------
// Component lists always have match rule operands first, followed by parameter
// operands which do not appear in the match list (in order of declaration).
class ComponentList : private NameList {
private:
  int   _matchcnt;                 // Count of match rule operands

public:

  // This is a batch program.  (And I have a destructor bug!)
  void operator delete( void *ptr ) {}

  void insert(Component *component, bool mflag);
  void insert(const char *name, const char *opType, int usedef, bool mflag);

  int  count();
  int  match_count() { return _matchcnt; } // Get count of match rule opers

  Component *iter();               // after reset(), first element : else next
  Component *match_iter();         // after reset(), first element : else next
  Component *post_match_iter();    // after reset(), first element : else next
  void       reset();              // Reset iteration
  Component *current();            // return current element in iteration.

  // Return element at "position", else NULL
  Component *operator[](int position);
  Component *at(int position) { return (*this)[position]; }

  // Return first component having this name.
  const Component *search(const char *name);

  // Return number of USEs + number of DEFs
  int        num_operands();
  // Return zero-based position in list;  -1 if not in list.
  int        operand_position(const char *name, int usedef, Form *fm);
  // Find position for this name, regardless of use/def information
  int        operand_position(const char *name);
  // Find position for this name when looked up for output via "format"
  int        operand_position_format(const char *name, Form *fm);
  // Find position for the Label when looked up for output via "format"
  int        label_position();
  // Find position for the Method when looked up for output via "format"
  int        method_position();

  void       dump();               // output to stderr
  void       output(FILE *fp);     // Output list of names to 'fp'

  ComponentList();
  ~ComponentList();
};

//------------------------------SourceForm-------------------------------------
class SourceForm : public Form {
private:

public:
  // Public Data
  char *_code;                     // Buffer for storing code text

  // Public Methods
  SourceForm(char* code);
  ~SourceForm();

  virtual const char* classname() { return "SourceForm"; }

  void dump();                    // Debug printer
  void output(FILE *fp);          // Write output files
};

class HeaderForm : public SourceForm {
public:
  HeaderForm(char* code) : SourceForm(code) { }

  virtual const char* classname() { return "HeaderForm"; }
};

class PreHeaderForm : public SourceForm {
public:
  PreHeaderForm(char* code) : SourceForm(code) { }

  virtual const char* classname() { return "PreHeaderForm"; }
};




//------------------------------Expr------------------------------------------
#define STRING_BUFFER_LENGTH  2048
// class Expr represents integer expressions containing constants and addition
// Value must be in range zero through maximum positive integer. 32bits.
// Expected use: instruction and operand costs
class Expr {
public:
  enum {
    Zero     = 0,
    Max      = 0x7fffffff
  };
  const char *_external_name;  // if !NULL, then print this instead of _expr
  const char *_expr;
  int         _min_value;
  int         _max_value;

  Expr();
  Expr(const char *cost);
  Expr(const char *name, const char *expression, int min_value, int max_value);
  Expr *clone() const;

  bool  is_unknown() const { return (this == Expr::get_unknown()); }
  bool  is_zero()    const { return (_min_value == Expr::Zero && _max_value == Expr::Zero); }
  bool  less_than_or_equal(const Expr *c) const { return (_max_value <= c->_min_value); }

  void  add(const Expr *c);
  void  add(const char *c);
  void  add(const char *c, ArchDesc &AD);   // check if 'c' is defined in <arch>.ad
  void  set_external_name(const char *name) { _external_name = name; }

  const char *as_string()  const { return (_external_name != NULL ? _external_name : _expr); }
  void  print()            const;
  void  print_define(FILE *fp) const;
  void  print_assert(FILE *fp) const;

  static Expr *get_unknown();   // Returns pointer to shared unknown cost instance

  static char *buffer()         { return &external_buffer[0]; }
  static bool  init_buffers();  // Fill buffers with 0
  static bool  check_buffers(); // if buffer use may have overflowed, assert

private:
  static Expr *_unknown_expr;
  static char string_buffer[STRING_BUFFER_LENGTH];
  static char external_buffer[STRING_BUFFER_LENGTH];
  static bool _init_buffers;
  const char *compute_expr(const Expr *c1, const Expr *c2);  // cost as string after adding 'c1' and 'c2'
  int         compute_min (const Expr *c1, const Expr *c2);  // minimum after adding 'c1' and 'c2'
  int         compute_max (const Expr *c1, const Expr *c2);  // maximum after adding 'c1' and 'c2'
  const char *compute_external(const Expr *c1, const Expr *c2);  // external name after adding 'c1' and 'c2'
};

//------------------------------ExprDict---------------------------------------
// Dictionary containing Exprs
class ExprDict {
private:
  Dict         _expr;              // map names, char*, to their Expr* or NULL
  NameList     _defines;           // record the order of definitions entered with define call

  // Disable public use of constructor, copy-ctor, operator =, operator ==
  ExprDict( );
  ExprDict( const ExprDict & );    // Deep-copy guts
  ExprDict &operator =( const ExprDict & );
  // == compares two dictionaries; they must have the same keys (their keys
  // must match using CmpKey) and they must have the same values (pointer
  // comparison).  If so 1 is returned, if not 0 is returned.
  bool operator ==(const ExprDict &d) const; // Compare dictionaries for equal

public:
  // cmp is a key comparision routine.  hash is a routine to hash a key.
  ExprDict( CmpKey cmp, Hash hash, Arena *arena );
  ~ExprDict();

  // Return # of key-value pairs in dict
  int Size(void) const;

  // define inserts the given key-value pair into the dictionary,
  // and records the name in order for later output, ...
  const Expr  *define(const char *name, Expr *expr);

  // Insert inserts the given key-value pair into the dictionary.  The prior
  // value of the key is returned; NULL if the key was not previously defined.
  const Expr  *Insert(const char *name, Expr *expr); // A new key-value

  // Find finds the value of a given key; or NULL if not found.
  // The dictionary is NOT changed.
  const Expr  *operator [](const char *name) const;  // Do a lookup

  void print_defines(FILE *fp);
  void print_asserts(FILE *fp);
  void dump();
};

#endif // SHARE_VM_ADLC_FORMS_HPP