forms.hpp 18.5 KB
Newer Older
D
duke 已提交
1
/*
X
xdono 已提交
2
 * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
D
duke 已提交
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
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

// 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 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
  long  _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) { };
  ~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
171 172
    idealS      =  8,  // String  type
    idealN      =  9   // Narrow oop types
D
duke 已提交
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
  };
  // 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
332 333
  static const char *_signal2;      // reserved user-defined string
  static const char *_signal3;      // reserved user-defined string
D
duke 已提交
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
  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.

  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);
  // 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);
  // 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();
};