adlparse.cpp revision 0:a61af66fc99e
1193323Sed/* 2193323Sed * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 3193323Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4193323Sed * 5193323Sed * This code is free software; you can redistribute it and/or modify it 6193323Sed * under the terms of the GNU General Public License version 2 only, as 7193323Sed * published by the Free Software Foundation. 8193323Sed * 9193323Sed * This code is distributed in the hope that it will be useful, but WITHOUT 10193323Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11193323Sed * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12193323Sed * version 2 for more details (a copy is included in the LICENSE file that 13193323Sed * accompanied this code). 14193323Sed * 15198396Srdivacky * You should have received a copy of the GNU General Public License version 16243830Sdim * 2 along with this work; if not, write to the Free Software Foundation, 17193323Sed * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18193323Sed * 19193323Sed * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20193323Sed * CA 95054 USA or visit www.sun.com if you need additional information or 21193323Sed * have any questions. 22193323Sed * 23193323Sed */ 24193323Sed 25193323Sed// ADLPARSE.CPP - Architecture Description Language Parser 26193323Sed// Authors: Chris Vick and Mike Paleczny 27193323Sed#include "adlc.hpp" 28193323Sed 29193323Sed//----------------------------ADLParser---------------------------------------- 30193323Sed// Create a new ADL parser 31193323SedADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc) 32193323Sed : _buf(buffer), _AD(archDesc), 33193323Sed _globalNames(archDesc.globalNames()) { 34193323Sed _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file 35193323Sed _AD._warnings = 0; // No warnings either 36193323Sed _linenum = 0; // Will increment to first line 37193323Sed _curline = _ptr = NULL; // No pointers into buffer yet 38193323Sed 39193323Sed _preproc_depth = 0; 40193323Sed _preproc_not_taken = 0; 41193323Sed 42193323Sed // Delimit command-line definitions from in-file definitions: 43234353Sdim _AD._preproc_list.add_signal(); 44234353Sdim} 45234353Sdim 46234353Sdim//------------------------------~ADLParser------------------------------------- 47193323Sed// Delete an ADL parser. 48193323SedADLParser::~ADLParser() { 49234353Sdim if (!_AD._quiet_mode) 50193323Sed fprintf(stderr,"---------------------------- Errors and Warnings ----------------------------\n"); 51193323Sed#ifndef ASSERT 52193323Sed fprintf(stderr, "**************************************************************\n"); 53193323Sed fprintf(stderr, "***** WARNING: ASSERT is undefined, assertions disabled. *****\n"); 54193323Sed fprintf(stderr, "**************************************************************\n"); 55193323Sed#endif 56193323Sed if( _AD._syntax_errs + _AD._semantic_errs + _AD._warnings == 0 ) { 57193323Sed if (!_AD._quiet_mode) 58199481Srdivacky fprintf(stderr,"No errors or warnings to report from phase-1 parse.\n" ); 59193323Sed } 60193323Sed else { 61193323Sed if( _AD._syntax_errs ) { // Any syntax errors? 62193323Sed fprintf(stderr,"%s: Found %d syntax error", _buf._fp->_name, _AD._syntax_errs); 63193323Sed if( _AD._syntax_errs > 1 ) fprintf(stderr,"s.\n\n"); 64198396Srdivacky else fprintf(stderr,".\n\n"); 65193323Sed } 66234353Sdim if( _AD._semantic_errs ) { // Any semantic errors? 67234353Sdim fprintf(stderr,"%s: Found %d semantic error", _buf._fp->_name, _AD._semantic_errs); 68193323Sed if( _AD._semantic_errs > 1 ) fprintf(stderr,"s.\n\n"); 69193323Sed else fprintf(stderr,".\n\n"); 70193323Sed } 71234353Sdim if( _AD._warnings ) { // Any warnings? 72193323Sed fprintf(stderr,"%s: Found %d warning", _buf._fp->_name, _AD._warnings); 73243830Sdim if( _AD._warnings > 1 ) fprintf(stderr,"s.\n\n"); 74193323Sed else fprintf(stderr,".\n\n"); 75193323Sed } 76193323Sed } 77234353Sdim if (!_AD._quiet_mode) 78193323Sed fprintf(stderr,"-----------------------------------------------------------------------------\n"); 79193323Sed _AD._TotalLines += _linenum-1; // -1 for overshoot in "nextline" routine 80193323Sed 81234353Sdim // Write out information we have stored 82193323Sed // // UNIXism == fsync(stderr); 83193323Sed} 84193323Sed 85193323Sed//------------------------------parse------------------------------------------ 86193323Sed// Each top-level keyword should appear as the first non-whitespace on a line. 87193323Sed// 88243830Sdimvoid ADLParser::parse() { 89193323Sed char *ident; 90193323Sed 91193323Sed // Iterate over the lines in the file buffer parsing Level 1 objects 92193323Sed for( next_line(); _curline != NULL; next_line()) { 93193323Sed _ptr = _curline; // Reset ptr to start of new line 94198090Srdivacky skipws(); // Skip any leading whitespace 95193323Sed ident = get_ident(); // Get first token 96193323Sed if (ident == NULL) { // Empty line 97198090Srdivacky continue; // Get the next line 98193323Sed } 99193323Sed if (!strcmp(ident, "instruct")) instr_parse(); 100193323Sed else if (!strcmp(ident, "operand")) oper_parse(); 101193323Sed else if (!strcmp(ident, "opclass")) opclass_parse(); 102193323Sed else if (!strcmp(ident, "ins_attrib")) ins_attr_parse(); 103193323Sed else if (!strcmp(ident, "op_attrib")) op_attr_parse(); 104193323Sed else if (!strcmp(ident, "source")) source_parse(); 105193323Sed else if (!strcmp(ident, "source_hpp")) source_hpp_parse(); 106193323Sed else if (!strcmp(ident, "register")) reg_parse(); 107193323Sed else if (!strcmp(ident, "frame")) frame_parse(); 108193323Sed else if (!strcmp(ident, "encode")) encode_parse(); 109193323Sed else if (!strcmp(ident, "pipeline")) pipe_parse(); 110193323Sed else if (!strcmp(ident, "definitions")) definitions_parse(); 111193323Sed else if (!strcmp(ident, "peephole")) peep_parse(); 112193323Sed else if (!strcmp(ident, "#define")) preproc_define(); 113193323Sed else if (!strcmp(ident, "#undef")) preproc_undef(); 114193323Sed else { 115193323Sed parse_err(SYNERR, "expected one of - instruct, operand, ins_attrib, op_attrib, source, register, pipeline, encode\n Found %s",ident); 116199481Srdivacky } 117193323Sed } 118193323Sed 119198396Srdivacky // Done with parsing, check consistency. 120193323Sed 121234353Sdim if (_preproc_depth != 0) { 122234353Sdim parse_err(SYNERR, "End of file inside #ifdef"); 123193323Sed } 124193323Sed 125234353Sdim // AttributeForms ins_cost and op_cost must be defined for default behaviour 126193323Sed if (_globalNames[AttributeForm::_ins_cost] == NULL) { 127243830Sdim parse_err(SEMERR, "Did not declare 'ins_cost' attribute"); 128193323Sed } 129193323Sed if (_globalNames[AttributeForm::_ins_pc_relative] == NULL) { 130193323Sed parse_err(SEMERR, "Did not declare 'ins_pc_relative' attribute"); 131193323Sed } 132243830Sdim if (_globalNames[AttributeForm::_op_cost] == NULL) { 133193323Sed parse_err(SEMERR, "Did not declare 'op_cost' attribute"); 134193323Sed } 135193323Sed} 136193323Sed 137193323Sed// ******************** Private Level 1 Parse Functions ******************** 138193323Sed//------------------------------instr_parse------------------------------------ 139193323Sed// Parse the contents of an instruction definition, build the InstructForm to 140193323Sed// represent that instruction, and add it to the InstructForm list. 141198090Srdivackyvoid ADLParser::instr_parse(void) { 142193323Sed char *ident; 143193323Sed InstructForm *instr; 144193323Sed MatchRule *rule; 145193323Sed int match_rules_cnt = 0; 146193323Sed 147193323Sed // First get the name of the instruction 148193323Sed if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL ) 149193323Sed return; 150193323Sed instr = new InstructForm(ident); // Create new instruction form 151193323Sed instr->_linenum = _linenum; 152193323Sed _globalNames.Insert(ident, instr); // Add name to the name table 153193323Sed // Debugging Stuff 154193323Sed if (_AD._adl_debug > 1) 155193323Sed fprintf(stderr,"Parsing Instruction Form %s\n", ident); 156193323Sed 157193323Sed // Then get the operands 158193323Sed skipws(); 159193323Sed if (_curchar != '(') { 160198090Srdivacky parse_err(SYNERR, "missing '(' in instruct definition\n"); 161218893Sdim } 162193323Sed // Parse the operand list 163193323Sed else get_oplist(instr->_parameters, instr->_localNames); 164193323Sed skipws(); // Skip leading whitespace 165193323Sed // Check for block delimiter 166193323Sed if ( (_curchar != '%') 167199481Srdivacky || ( next_char(), (_curchar != '{')) ) { 168198090Srdivacky parse_err(SYNERR, "missing '%{' in instruction definition\n"); 169193323Sed return; 170193323Sed } 171234353Sdim next_char(); // Maintain the invariant 172234353Sdim do { 173193323Sed ident = get_ident(); // Grab next identifier 174193323Sed if (ident == NULL) { 175221345Sdim parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 176221345Sdim continue; 177193323Sed } 178193323Sed if (!strcmp(ident, "predicate")) instr->_predicate = pred_parse(); 179193323Sed else if (!strcmp(ident, "match")) { 180193323Sed // Allow one instruction have several match rules. 181193323Sed rule = instr->_matrule; 182193323Sed if (rule == NULL) { 183193323Sed // This is first match rule encountered 184193323Sed rule = match_parse(instr->_localNames); 185221345Sdim if (rule) { 186234353Sdim instr->_matrule = rule; 187221345Sdim // Special case the treatment of Control instructions. 188221345Sdim if( instr->is_ideal_control() ) { 189221345Sdim // Control instructions return a special result, 'Universe' 190221345Sdim rule->_result = "Universe"; 191221345Sdim } 192221345Sdim // Check for commutative operations with tree operands. 193239462Sdim matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt); 194221345Sdim } 195221345Sdim } else { 196221345Sdim // Find the end of the match rule list 197221345Sdim while (rule->_next != NULL) 198221345Sdim rule = rule->_next; 199193323Sed // Add the new match rule to the list 200193323Sed rule->_next = match_parse(instr->_localNames); 201234353Sdim if (rule->_next) { 202234353Sdim rule = rule->_next; 203234353Sdim if( instr->is_ideal_control() ) { 204234353Sdim parse_err(SYNERR, "unique match rule expected for %s\n", rule->_name); 205234353Sdim return; 206234353Sdim } 207193323Sed assert(match_rules_cnt < 100," too many match rule clones"); 208193323Sed char* buf = (char*) malloc(strlen(instr->_ident) + 4); 209234353Sdim sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++); 210234353Sdim rule->_result = buf; 211234353Sdim // Check for commutative operations with tree operands. 212193323Sed matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt); 213234353Sdim } 214193323Sed } 215234353Sdim } 216234353Sdim else if (!strcmp(ident, "encode")) { 217234353Sdim parse_err(SYNERR, "Instructions specify ins_encode, not encode\n"); 218193323Sed } 219193323Sed else if (!strcmp(ident, "ins_encode")) 220193323Sed instr->_insencode = ins_encode_parse(*instr); 221193323Sed else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr); 222193323Sed else if (!strcmp(ident, "size")) instr->_size = size_parse(instr); 223193323Sed else if (!strcmp(ident, "effect")) effect_parse(instr); 224193323Sed else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr); 225234353Sdim else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse(); 226193323Sed else if (!strcmp(ident, "constraint")) { 227193323Sed parse_err(SYNERR, "Instructions do not specify a constraint\n"); 228234353Sdim } 229234353Sdim else if (!strcmp(ident, "construct")) { 230193323Sed parse_err(SYNERR, "Instructions do not specify a construct\n"); 231193323Sed } 232193323Sed else if (!strcmp(ident, "format")) instr->_format = format_parse(); 233193323Sed else if (!strcmp(ident, "interface")) { 234193323Sed parse_err(SYNERR, "Instructions do not specify an interface\n"); 235193323Sed } 236193323Sed else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr); 237221345Sdim else { // Done with staticly defined parts of instruction definition 238193323Sed // Check identifier to see if it is the name of an attribute 239 const Form *form = _globalNames[ident]; 240 AttributeForm *attr = form ? form->is_attribute() : NULL; 241 if( attr && (attr->_atype == INS_ATTR) ) { 242 // Insert the new attribute into the linked list. 243 Attribute *temp = attr_parse(ident); 244 temp->_next = instr->_attribs; 245 instr->_attribs = temp; 246 } else { 247 parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of an instruction attribute at %s\n", ident); 248 } 249 } 250 skipws(); 251 } while(_curchar != '%'); 252 next_char(); 253 if (_curchar != '}') { 254 parse_err(SYNERR, "missing '%}' in instruction definition\n"); 255 return; 256 } 257 // Check for "Set" form of chain rule 258 adjust_set_rule(instr); 259 if (_AD._pipeline ) { 260 if( instr->expands() ) { 261 if( instr->_ins_pipe ) 262 parse_err(WARN, "ins_pipe and expand rule both specified for instruction \"%s\"; ins_pipe will be unused\n", instr->_ident); 263 } else { 264 if( !instr->_ins_pipe ) 265 parse_err(WARN, "No ins_pipe specified for instruction \"%s\"\n", instr->_ident); 266 } 267 } 268 // Add instruction to tail of instruction list 269 _AD.addForm(instr); 270 271 // Create instruction form for each additional match rule 272 rule = instr->_matrule; 273 if (rule != NULL) { 274 rule = rule->_next; 275 while (rule != NULL) { 276 ident = (char*)rule->_result; 277 InstructForm *clone = new InstructForm(ident, instr, rule); // Create new instruction form 278 _globalNames.Insert(ident, clone); // Add name to the name table 279 // Debugging Stuff 280 if (_AD._adl_debug > 1) 281 fprintf(stderr,"Parsing Instruction Form %s\n", ident); 282 // Check for "Set" form of chain rule 283 adjust_set_rule(clone); 284 // Add instruction to tail of instruction list 285 _AD.addForm(clone); 286 rule = rule->_next; 287 clone->_matrule->_next = NULL; // One match rule per clone 288 } 289 } 290} 291 292//------------------------------matchrule_clone_and_swap----------------------- 293// Check for commutative operations with subtree operands, 294// create clones and swap operands. 295void ADLParser::matchrule_clone_and_swap(MatchRule* rule, const char* instr_ident, int& match_rules_cnt) { 296 // Check for commutative operations with tree operands. 297 int count = 0; 298 rule->count_commutative_op(count); 299 if (count > 0) { 300 // Clone match rule and swap commutative operation's operands. 301 rule->swap_commutative_op(instr_ident, count, match_rules_cnt); 302 } 303} 304 305//------------------------------adjust_set_rule-------------------------------- 306// Check for "Set" form of chain rule 307void ADLParser::adjust_set_rule(InstructForm *instr) { 308 if (instr->_matrule == NULL || instr->_matrule->_rChild == NULL) return; 309 const char *rch = instr->_matrule->_rChild->_opType; 310 const Form *frm = _globalNames[rch]; 311 if( (! strcmp(instr->_matrule->_opType,"Set")) && 312 frm && frm->is_operand() && (! frm->ideal_only()) ) { 313 // Previous implementation, which missed leaP*, but worked for loadCon* 314 unsigned position = 0; 315 const char *result = NULL; 316 const char *name = NULL; 317 const char *optype = NULL; 318 MatchNode *right = instr->_matrule->_rChild; 319 if (right->base_operand(position, _globalNames, result, name, optype)) { 320 position = 1; 321 const char *result2 = NULL; 322 const char *name2 = NULL; 323 const char *optype2 = NULL; 324 // Can not have additional base operands in right side of match! 325 if ( ! right->base_operand( position, _globalNames, result2, name2, optype2) ) { 326 assert( instr->_predicate == NULL, "ADLC does not support instruction chain rules with predicates"); 327 // Chain from input _ideal_operand_type_, 328 // Needed for shared roots of match-trees 329 ChainList *lst = (ChainList *)_AD._chainRules[optype]; 330 if (lst == NULL) { 331 lst = new ChainList(); 332 _AD._chainRules.Insert(optype, lst); 333 } 334 if (!lst->search(instr->_matrule->_lChild->_opType)) { 335 const char *cost = instr->cost(); 336 if (cost == NULL) { 337 cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; 338 } 339 // The ADLC does not support chaining from the ideal operand type 340 // of a predicated user-defined operand 341 if( frm->is_operand() == NULL || frm->is_operand()->_predicate == NULL ) { 342 lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident); 343 } 344 } 345 // Chain from input _user_defined_operand_type_, 346 lst = (ChainList *)_AD._chainRules[result]; 347 if (lst == NULL) { 348 lst = new ChainList(); 349 _AD._chainRules.Insert(result, lst); 350 } 351 if (!lst->search(instr->_matrule->_lChild->_opType)) { 352 const char *cost = instr->cost(); 353 if (cost == NULL) { 354 cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; 355 } 356 // It is safe to chain from the top-level user-defined operand even 357 // if it has a predicate, since the predicate is checked before 358 // the user-defined type is available. 359 lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident); 360 } 361 } else { 362 // May have instruction chain rule if root of right-tree is an ideal 363 OperandForm *rightOp = _globalNames[right->_opType]->is_operand(); 364 if( rightOp ) { 365 const Form *rightRoot = _globalNames[rightOp->_matrule->_opType]; 366 if( rightRoot && rightRoot->ideal_only() ) { 367 const char *chain_op = NULL; 368 if( rightRoot->is_instruction() ) 369 chain_op = rightOp->_ident; 370 if( chain_op ) { 371 // Look-up the operation in chain rule table 372 ChainList *lst = (ChainList *)_AD._chainRules[chain_op]; 373 if (lst == NULL) { 374 lst = new ChainList(); 375 _AD._chainRules.Insert(chain_op, lst); 376 } 377 // if (!lst->search(instr->_matrule->_lChild->_opType)) { 378 const char *cost = instr->cost(); 379 if (cost == NULL) { 380 cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; 381 } 382 // This chains from a top-level operand whose predicate, if any, 383 // has been checked. 384 lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident); 385 // } 386 } 387 } 388 } 389 } // end chain rule from right-tree's ideal root 390 } 391 } 392} 393 394 395//------------------------------oper_parse------------------------------------- 396void ADLParser::oper_parse(void) { 397 char *ident; 398 OperandForm *oper; 399 AttributeForm *attr; 400 MatchRule *rule; 401 402 // First get the name of the operand 403 skipws(); 404 if( (ident = get_unique_ident(_globalNames,"operand")) == NULL ) 405 return; 406 oper = new OperandForm(ident); // Create new operand form 407 oper->_linenum = _linenum; 408 _globalNames.Insert(ident, oper); // Add name to the name table 409 410 // Debugging Stuff 411 if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Operand Form %s\n", ident); 412 413 // Get the component operands 414 skipws(); 415 if (_curchar != '(') { 416 parse_err(SYNERR, "missing '(' in operand definition\n"); 417 return; 418 } 419 else get_oplist(oper->_parameters, oper->_localNames); // Parse the component operand list 420 skipws(); 421 // Check for block delimiter 422 if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block 423 parse_err(SYNERR, "missing '%c{' in operand definition\n","%"); 424 return; 425 } 426 next_char(); next_char(); // Skip over "%{" symbol 427 do { 428 ident = get_ident(); // Grab next identifier 429 if (ident == NULL) { 430 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 431 continue; 432 } 433 if (!strcmp(ident, "predicate")) oper->_predicate = pred_parse(); 434 else if (!strcmp(ident, "match")) { 435 // Find the end of the match rule list 436 rule = oper->_matrule; 437 if (rule) { 438 while (rule->_next) rule = rule->_next; 439 // Add the new match rule to the list 440 rule->_next = match_parse(oper->_localNames); 441 if (rule->_next) { 442 rule->_next->_result = oper->_ident; 443 } 444 } 445 else { 446 // This is first match rule encountered 447 oper->_matrule = match_parse(oper->_localNames); 448 if (oper->_matrule) { 449 oper->_matrule->_result = oper->_ident; 450 } 451 } 452 } 453 else if (!strcmp(ident, "encode")) oper->_interface = interface_parse(); 454 else if (!strcmp(ident, "ins_encode")) { 455 parse_err(SYNERR, "Operands specify 'encode', not 'ins_encode'\n"); 456 } 457 else if (!strcmp(ident, "opcode")) { 458 parse_err(SYNERR, "Operands do not specify an opcode\n"); 459 } 460 else if (!strcmp(ident, "effect")) { 461 parse_err(SYNERR, "Operands do not specify an effect\n"); 462 } 463 else if (!strcmp(ident, "expand")) { 464 parse_err(SYNERR, "Operands do not specify an expand\n"); 465 } 466 else if (!strcmp(ident, "rewrite")) { 467 parse_err(SYNERR, "Operands do not specify a rewrite\n"); 468 } 469 else if (!strcmp(ident, "constraint"))oper->_constraint= constraint_parse(); 470 else if (!strcmp(ident, "construct")) oper->_construct = construct_parse(); 471 else if (!strcmp(ident, "format")) oper->_format = format_parse(); 472 else if (!strcmp(ident, "interface")) oper->_interface = interface_parse(); 473 // Check identifier to see if it is the name of an attribute 474 else if (((attr = _globalNames[ident]->is_attribute()) != NULL) && 475 (attr->_atype == OP_ATTR)) oper->_attribs = attr_parse(ident); 476 else { 477 parse_err(SYNERR, "expected one of - constraint, predicate, match, encode, format, construct, or the name of a defined operand attribute at %s\n", ident); 478 } 479 skipws(); 480 } while(_curchar != '%'); 481 next_char(); 482 if (_curchar != '}') { 483 parse_err(SYNERR, "missing '%}' in operand definition\n"); 484 return; 485 } 486 // Add operand to tail of operand list 487 _AD.addForm(oper); 488} 489 490//------------------------------opclass_parse---------------------------------- 491// Operand Classes are a block with a comma delimited list of operand names 492void ADLParser::opclass_parse(void) { 493 char *ident; 494 OpClassForm *opc; 495 OperandForm *opForm; 496 497 // First get the name of the operand class 498 skipws(); 499 if( (ident = get_unique_ident(_globalNames,"opclass")) == NULL ) 500 return; 501 opc = new OpClassForm(ident); // Create new operand class form 502 _globalNames.Insert(ident, opc); // Add name to the name table 503 504 // Debugging Stuff 505 if (_AD._adl_debug > 1) 506 fprintf(stderr,"Parsing Operand Class Form %s\n", ident); 507 508 // Get the list of operands 509 skipws(); 510 if (_curchar != '(') { 511 parse_err(SYNERR, "missing '(' in operand definition\n"); 512 return; 513 } 514 do { 515 next_char(); // Skip past open paren or comma 516 ident = get_ident(); // Grab next identifier 517 if (ident == NULL) { 518 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 519 continue; 520 } 521 // Check identifier to see if it is the name of an operand 522 const Form *form = _globalNames[ident]; 523 opForm = form ? form->is_operand() : NULL; 524 if ( opForm ) { 525 opc->_oplst.addName(ident); // Add operand to opclass list 526 opForm->_classes.addName(opc->_ident);// Add opclass to operand list 527 } 528 else { 529 parse_err(SYNERR, "expected name of a defined operand at %s\n", ident); 530 } 531 skipws(); // skip trailing whitespace 532 } while (_curchar == ','); // Check for the comma 533 // Check for closing ')' 534 if (_curchar != ')') { 535 parse_err(SYNERR, "missing ')' or ',' in opclass definition\n"); 536 return; 537 } 538 next_char(); // Consume the ')' 539 skipws(); 540 // Check for closing ';' 541 if (_curchar != ';') { 542 parse_err(SYNERR, "missing ';' in opclass definition\n"); 543 return; 544 } 545 next_char(); // Consume the ';' 546 // Add operand to tail of operand list 547 _AD.addForm(opc); 548} 549 550//------------------------------ins_attr_parse--------------------------------- 551void ADLParser::ins_attr_parse(void) { 552 char *ident; 553 char *aexpr; 554 AttributeForm *attrib; 555 556 // get name for the instruction attribute 557 skipws(); // Skip leading whitespace 558 if( (ident = get_unique_ident(_globalNames,"inst_attrib")) == NULL ) 559 return; 560 // Debugging Stuff 561 if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Ins_Attribute Form %s\n", ident); 562 563 // Get default value of the instruction attribute 564 skipws(); // Skip whitespace 565 if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) { 566 parse_err(SYNERR, "missing '(' in ins_attrib definition\n"); 567 return; 568 } 569 // Debug Stuff 570 if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr); 571 572 // Check for terminator 573 if (_curchar != ';') { 574 parse_err(SYNERR, "missing ';' in ins_attrib definition\n"); 575 return; 576 } 577 next_char(); // Advance past the ';' 578 579 // Construct the attribute, record global name, and store in ArchDesc 580 attrib = new AttributeForm(ident, INS_ATTR, aexpr); 581 _globalNames.Insert(ident, attrib); // Add name to the name table 582 _AD.addForm(attrib); 583} 584 585//------------------------------op_attr_parse---------------------------------- 586void ADLParser::op_attr_parse(void) { 587 char *ident; 588 char *aexpr; 589 AttributeForm *attrib; 590 591 // get name for the operand attribute 592 skipws(); // Skip leading whitespace 593 if( (ident = get_unique_ident(_globalNames,"op_attrib")) == NULL ) 594 return; 595 // Debugging Stuff 596 if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Op_Attribute Form %s\n", ident); 597 598 // Get default value of the instruction attribute 599 skipws(); // Skip whitespace 600 if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) { 601 parse_err(SYNERR, "missing '(' in op_attrib definition\n"); 602 return; 603 } 604 // Debug Stuff 605 if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr); 606 607 // Check for terminator 608 if (_curchar != ';') { 609 parse_err(SYNERR, "missing ';' in op_attrib definition\n"); 610 return; 611 } 612 next_char(); // Advance past the ';' 613 614 // Construct the attribute, record global name, and store in ArchDesc 615 attrib = new AttributeForm(ident, OP_ATTR, aexpr); 616 _globalNames.Insert(ident, attrib); 617 _AD.addForm(attrib); 618} 619 620//------------------------------definitions_parse----------------------------------- 621void ADLParser::definitions_parse(void) { 622 skipws(); // Skip leading whitespace 623 if (_curchar == '%' && *(_ptr+1) == '{') { 624 next_char(); next_char(); // Skip "%{" 625 skipws(); 626 while (_curchar != '%' && *(_ptr+1) != '}') { 627 // Process each definition until finding closing string "%}" 628 char *token = get_ident(); 629 if (token == NULL) { 630 parse_err(SYNERR, "missing identifier inside definitions block.\n"); 631 return; 632 } 633 if (strcmp(token,"int_def")==0) { int_def_parse(); } 634 // if (strcmp(token,"str_def")==0) { str_def_parse(); } 635 skipws(); 636 } 637 } 638 else { 639 parse_err(SYNERR, "Missing %%{ ... %%} block after definitions keyword.\n"); 640 return; 641 } 642} 643 644//------------------------------int_def_parse---------------------------------- 645// Parse Example: 646// int_def MEMORY_REF_COST ( 200, DEFAULT_COST * 2); 647// <keyword> <name> ( <int_value>, <description> ); 648// 649void ADLParser::int_def_parse(void) { 650 char *name = NULL; // Name of definition 651 char *value = NULL; // its value, 652 int int_value = -1; // positive values only 653 char *description = NULL; // textual description 654 655 // Get definition name 656 skipws(); // Skip whitespace 657 name = get_ident(); 658 if (name == NULL) { 659 parse_err(SYNERR, "missing definition name after int_def\n"); 660 return; 661 } 662 663 // Check for value of int_def dname( integer_value [, string_expression ] ) 664 skipws(); 665 if (_curchar == '(') { 666 667 // Parse the integer value. 668 next_char(); 669 value = get_ident(); 670 if (value == NULL) { 671 parse_err(SYNERR, "missing value in int_def\n"); 672 return; 673 } 674 if( !is_int_token(value, int_value) ) { 675 parse_err(SYNERR, "value in int_def is not recognized as integer\n"); 676 return; 677 } 678 skipws(); 679 680 // Check for description 681 if (_curchar == ',') { 682 next_char(); // skip ',' 683 684 description = get_expr("int_def description", ")"); 685 if (description == NULL) { 686 parse_err(SYNERR, "invalid or missing description in int_def\n"); 687 return; 688 } 689 trim(description); 690 } 691 692 if (_curchar != ')') { 693 parse_err(SYNERR, "missing ')' in register definition statement\n"); 694 return; 695 } 696 next_char(); 697 } 698 699 // Check for closing ';' 700 skipws(); 701 if (_curchar != ';') { 702 parse_err(SYNERR, "missing ';' after int_def\n"); 703 return; 704 } 705 next_char(); // move past ';' 706 707 // Debug Stuff 708 if (_AD._adl_debug > 1) { 709 fprintf(stderr,"int_def: %s ( %s, %s )\n", name, 710 (value), (description ? description : "")); 711 } 712 713 // Record new definition. 714 Expr *expr = new Expr(name, description, int_value, int_value); 715 const Expr *old_expr = _AD.globalDefs().define(name, expr); 716 if (old_expr != NULL) { 717 parse_err(SYNERR, "Duplicate definition\n"); 718 return; 719 } 720 721 return; 722} 723 724 725//------------------------------source_parse----------------------------------- 726void ADLParser::source_parse(void) { 727 SourceForm *source; // Encode class for instruction/operand 728 char *rule = NULL; // String representation of encode rule 729 730 skipws(); // Skip leading whitespace 731 if ( (rule = find_cpp_block("source block")) == NULL ) { 732 parse_err(SYNERR, "incorrect or missing block for 'source'.\n"); 733 return; 734 } 735 // Debug Stuff 736 if (_AD._adl_debug > 1) fprintf(stderr,"Source Form: %s\n", rule); 737 738 source = new SourceForm(rule); // Build new Source object 739 _AD.addForm(source); 740 // skipws(); 741} 742 743//------------------------------source_hpp_parse------------------------------- 744// Parse a source_hpp %{ ... %} block. 745// The code gets stuck into the ad_<arch>.hpp file. 746// If the source_hpp block appears before the register block in the AD 747// file, it goes up at the very top of the ad_<arch>.hpp file, so that 748// it can be used by register encodings, etc. Otherwise, it goes towards 749// the bottom, where it's useful as a global definition to *.cpp files. 750void ADLParser::source_hpp_parse(void) { 751 char *rule = NULL; // String representation of encode rule 752 753 skipws(); // Skip leading whitespace 754 if ( (rule = find_cpp_block("source_hpp block")) == NULL ) { 755 parse_err(SYNERR, "incorrect or missing block for 'source_hpp'.\n"); 756 return; 757 } 758 // Debug Stuff 759 if (_AD._adl_debug > 1) fprintf(stderr,"Header Form: %s\n", rule); 760 761 if (_AD.get_registers() == NULL) { 762 // Very early in the file, before reg_defs, we collect pre-headers. 763 PreHeaderForm* pre_header = new PreHeaderForm(rule); 764 _AD.addForm(pre_header); 765 } else { 766 // Normally, we collect header info, placed at the bottom of the hpp file. 767 HeaderForm* header = new HeaderForm(rule); 768 _AD.addForm(header); 769 } 770} 771 772//------------------------------reg_parse-------------------------------------- 773void ADLParser::reg_parse(void) { 774 775 // Create the RegisterForm for the architecture description. 776 RegisterForm *regBlock = new RegisterForm(); // Build new Source object 777 regBlock->_linenum = _linenum; 778 _AD.addForm(regBlock); 779 780 skipws(); // Skip leading whitespace 781 if (_curchar == '%' && *(_ptr+1) == '{') { 782 next_char(); next_char(); // Skip "%{" 783 skipws(); 784 while (_curchar != '%' && *(_ptr+1) != '}') { 785 char *token = get_ident(); 786 if (token == NULL) { 787 parse_err(SYNERR, "missing identifier inside register block.\n"); 788 return; 789 } 790 if (strcmp(token,"reg_def")==0) { reg_def_parse(); } 791 if (strcmp(token,"reg_class")==0) { reg_class_parse(); } 792 if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); } 793 skipws(); 794 } 795 } 796 else { 797 parse_err(SYNERR, "Missing %c{ ... %c} block after register keyword.\n",'%','%'); 798 return; 799 } 800 801 // Add reg_class spill_regs 802 regBlock->addSpillRegClass(); 803} 804 805//------------------------------encode_parse----------------------------------- 806void ADLParser::encode_parse(void) { 807 EncodeForm *encBlock; // Information about instruction/operand encoding 808 char *desc = NULL; // String representation of encode rule 809 810 _AD.getForm(&encBlock); 811 if ( encBlock == NULL) { 812 // Create the EncodeForm for the architecture description. 813 encBlock = new EncodeForm(); // Build new Source object 814 _AD.addForm(encBlock); 815 } 816 817 skipws(); // Skip leading whitespace 818 if (_curchar == '%' && *(_ptr+1) == '{') { 819 next_char(); next_char(); // Skip "%{" 820 skipws(); 821 while (_curchar != '%' && *(_ptr+1) != '}') { 822 char *token = get_ident(); 823 if (token == NULL) { 824 parse_err(SYNERR, "missing identifier inside encoding block.\n"); 825 return; 826 } 827 if (strcmp(token,"enc_class")==0) { enc_class_parse(); } 828 skipws(); 829 } 830 } 831 else { 832 parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%'); 833 return; 834 } 835} 836 837//------------------------------enc_class_parse-------------------------------- 838void ADLParser::enc_class_parse(void) { 839 char *ec_name; // Name of encoding class being defined 840 841 // Get encoding class name 842 skipws(); // Skip whitespace 843 ec_name = get_ident(); 844 if (ec_name == NULL) { 845 parse_err(SYNERR, "missing encoding class name after encode.\n"); 846 return; 847 } 848 849 EncClass *encoding = _AD._encode->add_EncClass(ec_name); 850 encoding->_linenum = _linenum; 851 852 skipws(); // Skip leading whitespace 853 // Check for optional parameter list 854 if (_curchar == '(') { 855 do { 856 char *pType = NULL; // parameter type 857 char *pName = NULL; // parameter name 858 859 next_char(); // skip open paren & comma characters 860 skipws(); 861 if (_curchar == ')') break; 862 863 // Get parameter type 864 pType = get_ident(); 865 if (pType == NULL) { 866 parse_err(SYNERR, "parameter type expected at %c\n", _curchar); 867 return; 868 } 869 870 skipws(); 871 // Get parameter name 872 pName = get_ident(); 873 if (pName == NULL) { 874 parse_err(SYNERR, "parameter name expected at %c\n", _curchar); 875 return; 876 } 877 878 // Record parameter type and name 879 encoding->add_parameter( pType, pName ); 880 881 skipws(); 882 } while(_curchar == ','); 883 884 if (_curchar != ')') parse_err(SYNERR, "missing ')'\n"); 885 else { 886 next_char(); // Skip ')' 887 } 888 } // Done with parameter list 889 890 skipws(); 891 // Check for block starting delimiters 892 if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block 893 parse_err(SYNERR, "missing '%c{' in enc_class definition\n", '%'); 894 return; 895 } 896 next_char(); // Skip '%' 897 next_char(); // Skip '{' 898 899 enc_class_parse_block(encoding, ec_name); 900} 901 902 903void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) { 904 skipws_no_preproc(); // Skip leading whitespace 905 // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block 906 if (_AD._adlocation_debug) { 907 const char* file = _AD._ADL_file._name; 908 int line = _linenum; 909 char* location = (char *)malloc(strlen(file) + 100); 910 sprintf(location, "#line %d \"%s\"\n", line, file); 911 encoding->add_code(location); 912 } 913 914 // Collect the parts of the encode description 915 // (1) strings that are passed through to output 916 // (2) replacement/substitution variable, preceeded by a '$' 917 while ( (_curchar != '%') && (*(_ptr+1) != '}') ) { 918 919 // (1) 920 // Check if there is a string to pass through to output 921 char *start = _ptr; // Record start of the next string 922 while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) { 923 // If at the start of a comment, skip past it 924 if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) { 925 skipws_no_preproc(); 926 } else { 927 // ELSE advance to the next character, or start of the next line 928 next_char_or_line(); 929 } 930 } 931 // If a string was found, terminate it and record in EncClass 932 if ( start != _ptr ) { 933 *_ptr = '\0'; // Terminate the string 934 encoding->add_code(start); 935 } 936 937 // (2) 938 // If we are at a replacement variable, 939 // copy it and record in EncClass 940 if ( _curchar == '$' ) { 941 // Found replacement Variable 942 char *rep_var = get_rep_var_ident_dup(); 943 // Add flag to _strings list indicating we should check _rep_vars 944 encoding->add_rep_var(rep_var); 945 } 946 } // end while part of format description 947 next_char(); // Skip '%' 948 next_char(); // Skip '}' 949 950 skipws(); 951 952 // Debug Stuff 953 if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name); 954} 955 956//------------------------------frame_parse----------------------------------- 957void ADLParser::frame_parse(void) { 958 FrameForm *frame; // Information about stack-frame layout 959 char *desc = NULL; // String representation of frame 960 961 skipws(); // Skip leading whitespace 962 963 frame = new FrameForm(); // Build new Frame object 964 // Check for open block sequence 965 skipws(); // Skip leading whitespace 966 if (_curchar == '%' && *(_ptr+1) == '{') { 967 next_char(); next_char(); // Skip "%{" 968 skipws(); 969 while (_curchar != '%' && *(_ptr+1) != '}') { 970 char *token = get_ident(); 971 if (token == NULL) { 972 parse_err(SYNERR, "missing identifier inside frame block.\n"); 973 return; 974 } 975 if (strcmp(token,"stack_direction")==0) { 976 stack_dir_parse(frame); 977 } 978 if (strcmp(token,"sync_stack_slots")==0) { 979 sync_stack_slots_parse(frame); 980 } 981 if (strcmp(token,"frame_pointer")==0) { 982 frame_pointer_parse(frame, false); 983 } 984 if (strcmp(token,"interpreter_frame_pointer")==0) { 985 interpreter_frame_pointer_parse(frame, false); 986 // Add reg_class interpreter_frame_pointer_reg 987 if( _AD._register != NULL ) { 988 RegClass *reg_class = _AD._register->addRegClass("interpreter_frame_pointer_reg"); 989 char *interpreter_frame_pointer_reg = frame->_interpreter_frame_pointer_reg; 990 if( interpreter_frame_pointer_reg != NULL ) { 991 RegDef *regDef = _AD._register->getRegDef(interpreter_frame_pointer_reg); 992 reg_class->addReg(regDef); // add regDef to regClass 993 } 994 } 995 } 996 if (strcmp(token,"inline_cache_reg")==0) { 997 inline_cache_parse(frame, false); 998 // Add reg_class inline_cache_reg 999 if( _AD._register != NULL ) { 1000 RegClass *reg_class = _AD._register->addRegClass("inline_cache_reg"); 1001 char *inline_cache_reg = frame->_inline_cache_reg; 1002 if( inline_cache_reg != NULL ) { 1003 RegDef *regDef = _AD._register->getRegDef(inline_cache_reg); 1004 reg_class->addReg(regDef); // add regDef to regClass 1005 } 1006 } 1007 } 1008 if (strcmp(token,"compiler_method_oop_reg")==0) { 1009 parse_err(WARN, "Using obsolete Token, compiler_method_oop_reg"); 1010 skipws(); 1011 } 1012 if (strcmp(token,"interpreter_method_oop_reg")==0) { 1013 interpreter_method_oop_parse(frame, false); 1014 // Add reg_class interpreter_method_oop_reg 1015 if( _AD._register != NULL ) { 1016 RegClass *reg_class = _AD._register->addRegClass("interpreter_method_oop_reg"); 1017 char *method_oop_reg = frame->_interpreter_method_oop_reg; 1018 if( method_oop_reg != NULL ) { 1019 RegDef *regDef = _AD._register->getRegDef(method_oop_reg); 1020 reg_class->addReg(regDef); // add regDef to regClass 1021 } 1022 } 1023 } 1024 if (strcmp(token,"cisc_spilling_operand_name")==0) { 1025 cisc_spilling_operand_name_parse(frame, false); 1026 } 1027 if (strcmp(token,"stack_alignment")==0) { 1028 stack_alignment_parse(frame); 1029 } 1030 if (strcmp(token,"return_addr")==0) { 1031 return_addr_parse(frame, false); 1032 } 1033 if (strcmp(token,"in_preserve_stack_slots")==0) { 1034 preserve_stack_parse(frame); 1035 } 1036 if (strcmp(token,"out_preserve_stack_slots")==0) { 1037 parse_err(WARN, "Using obsolete token, out_preserve_stack_slots"); 1038 skipws(); 1039 } 1040 if (strcmp(token,"varargs_C_out_slots_killed")==0) { 1041 frame->_varargs_C_out_slots_killed = parse_one_arg("varargs C out slots killed"); 1042 } 1043 if (strcmp(token,"calling_convention")==0) { 1044 frame->_calling_convention = calling_convention_parse(); 1045 } 1046 if (strcmp(token,"return_value")==0) { 1047 frame->_return_value = return_value_parse(); 1048 } 1049 if (strcmp(token,"c_frame_pointer")==0) { 1050 frame_pointer_parse(frame, true); 1051 } 1052 if (strcmp(token,"c_return_addr")==0) { 1053 return_addr_parse(frame, true); 1054 } 1055 if (strcmp(token,"c_calling_convention")==0) { 1056 frame->_c_calling_convention = calling_convention_parse(); 1057 } 1058 if (strcmp(token,"c_return_value")==0) { 1059 frame->_c_return_value = return_value_parse(); 1060 } 1061 1062 skipws(); 1063 } 1064 } 1065 else { 1066 parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%'); 1067 return; 1068 } 1069 // All Java versions are required, native versions are optional 1070 if(frame->_frame_pointer == NULL) { 1071 parse_err(SYNERR, "missing frame pointer definition in frame section.\n"); 1072 return; 1073 } 1074 // !!!!! !!!!! 1075 // if(frame->_interpreter_frame_ptr_reg == NULL) { 1076 // parse_err(SYNERR, "missing interpreter frame pointer definition in frame section.\n"); 1077 // return; 1078 // } 1079 if(frame->_alignment == NULL) { 1080 parse_err(SYNERR, "missing alignment definition in frame section.\n"); 1081 return; 1082 } 1083 if(frame->_return_addr == NULL) { 1084 parse_err(SYNERR, "missing return address location in frame section.\n"); 1085 return; 1086 } 1087 if(frame->_in_preserve_slots == NULL) { 1088 parse_err(SYNERR, "missing stack slot preservation definition in frame section.\n"); 1089 return; 1090 } 1091 if(frame->_varargs_C_out_slots_killed == NULL) { 1092 parse_err(SYNERR, "missing varargs C out slots killed definition in frame section.\n"); 1093 return; 1094 } 1095 if(frame->_calling_convention == NULL) { 1096 parse_err(SYNERR, "missing calling convention definition in frame section.\n"); 1097 return; 1098 } 1099 if(frame->_return_value == NULL) { 1100 parse_err(SYNERR, "missing return value definition in frame section.\n"); 1101 return; 1102 } 1103 // Fill natives in identically with the Java versions if not present. 1104 if(frame->_c_frame_pointer == NULL) { 1105 frame->_c_frame_pointer = frame->_frame_pointer; 1106 } 1107 if(frame->_c_return_addr == NULL) { 1108 frame->_c_return_addr = frame->_return_addr; 1109 frame->_c_return_addr_loc = frame->_return_addr_loc; 1110 } 1111 if(frame->_c_calling_convention == NULL) { 1112 frame->_c_calling_convention = frame->_calling_convention; 1113 } 1114 if(frame->_c_return_value == NULL) { 1115 frame->_c_return_value = frame->_return_value; 1116 } 1117 1118 // Debug Stuff 1119 if (_AD._adl_debug > 1) fprintf(stderr,"Frame Form: %s\n", desc); 1120 1121 // Create the EncodeForm for the architecture description. 1122 _AD.addForm(frame); 1123 // skipws(); 1124} 1125 1126//------------------------------stack_dir_parse-------------------------------- 1127void ADLParser::stack_dir_parse(FrameForm *frame) { 1128 char *direction = parse_one_arg("stack direction entry"); 1129 if (strcmp(direction, "TOWARDS_LOW") == 0) { 1130 frame->_direction = false; 1131 } 1132 else if (strcmp(direction, "TOWARDS_HIGH") == 0) { 1133 frame->_direction = true; 1134 } 1135 else { 1136 parse_err(SYNERR, "invalid value inside stack direction entry.\n"); 1137 return; 1138 } 1139} 1140 1141//------------------------------sync_stack_slots_parse------------------------- 1142void ADLParser::sync_stack_slots_parse(FrameForm *frame) { 1143 // Assign value into frame form 1144 frame->_sync_stack_slots = parse_one_arg("sync stack slots entry"); 1145} 1146 1147//------------------------------frame_pointer_parse---------------------------- 1148void ADLParser::frame_pointer_parse(FrameForm *frame, bool native) { 1149 char *frame_pointer = parse_one_arg("frame pointer entry"); 1150 // Assign value into frame form 1151 if (native) { frame->_c_frame_pointer = frame_pointer; } 1152 else { frame->_frame_pointer = frame_pointer; } 1153} 1154 1155//------------------------------interpreter_frame_pointer_parse---------------------------- 1156void ADLParser::interpreter_frame_pointer_parse(FrameForm *frame, bool native) { 1157 frame->_interpreter_frame_pointer_reg = parse_one_arg("interpreter frame pointer entry"); 1158} 1159 1160//------------------------------inline_cache_parse----------------------------- 1161void ADLParser::inline_cache_parse(FrameForm *frame, bool native) { 1162 frame->_inline_cache_reg = parse_one_arg("inline cache reg entry"); 1163} 1164 1165//------------------------------interpreter_method_oop_parse------------------ 1166void ADLParser::interpreter_method_oop_parse(FrameForm *frame, bool native) { 1167 frame->_interpreter_method_oop_reg = parse_one_arg("method oop reg entry"); 1168} 1169 1170//------------------------------cisc_spilling_operand_parse--------------------- 1171void ADLParser::cisc_spilling_operand_name_parse(FrameForm *frame, bool native) { 1172 frame->_cisc_spilling_operand_name = parse_one_arg("cisc spilling operand name"); 1173} 1174 1175//------------------------------stack_alignment_parse-------------------------- 1176void ADLParser::stack_alignment_parse(FrameForm *frame) { 1177 char *alignment = parse_one_arg("stack alignment entry"); 1178 // Assign value into frame 1179 frame->_alignment = alignment; 1180} 1181 1182//------------------------------parse_one_arg------------------------------- 1183char *ADLParser::parse_one_arg(const char *description) { 1184 char *token = NULL; 1185 if(_curchar == '(') { 1186 next_char(); 1187 skipws(); 1188 token = get_expr(description, ")"); 1189 if (token == NULL) { 1190 parse_err(SYNERR, "missing value inside %s.\n", description); 1191 return NULL; 1192 } 1193 next_char(); // skip the close paren 1194 if(_curchar != ';') { // check for semi-colon 1195 parse_err(SYNERR, "missing %c in.\n", ';', description); 1196 return NULL; 1197 } 1198 next_char(); // skip the semi-colon 1199 } 1200 else { 1201 parse_err(SYNERR, "Missing %c in.\n", '(', description); 1202 return NULL; 1203 } 1204 1205 trim(token); 1206 return token; 1207} 1208 1209//------------------------------return_addr_parse------------------------------ 1210void ADLParser::return_addr_parse(FrameForm *frame, bool native) { 1211 bool in_register = true; 1212 if(_curchar == '(') { 1213 next_char(); 1214 skipws(); 1215 char *token = get_ident(); 1216 if (token == NULL) { 1217 parse_err(SYNERR, "missing value inside return address entry.\n"); 1218 return; 1219 } 1220 // check for valid values for stack/register 1221 if (strcmp(token, "REG") == 0) { 1222 in_register = true; 1223 } 1224 else if (strcmp(token, "STACK") == 0) { 1225 in_register = false; 1226 } 1227 else { 1228 parse_err(SYNERR, "invalid value inside return_address entry.\n"); 1229 return; 1230 } 1231 if (native) { frame->_c_return_addr_loc = in_register; } 1232 else { frame->_return_addr_loc = in_register; } 1233 1234 // Parse expression that specifies register or stack position 1235 skipws(); 1236 char *token2 = get_expr("return address entry", ")"); 1237 if (token2 == NULL) { 1238 parse_err(SYNERR, "missing value inside return address entry.\n"); 1239 return; 1240 } 1241 next_char(); // skip the close paren 1242 if (native) { frame->_c_return_addr = token2; } 1243 else { frame->_return_addr = token2; } 1244 1245 if(_curchar != ';') { // check for semi-colon 1246 parse_err(SYNERR, "missing %c in return address entry.\n", ';'); 1247 return; 1248 } 1249 next_char(); // skip the semi-colon 1250 } 1251 else { 1252 parse_err(SYNERR, "Missing %c in return_address entry.\n", '('); 1253 } 1254} 1255 1256//------------------------------preserve_stack_parse--------------------------- 1257void ADLParser::preserve_stack_parse(FrameForm *frame) { 1258 if(_curchar == '(') { 1259 char *token = get_paren_expr("preserve_stack_slots"); 1260 frame->_in_preserve_slots = token; 1261 1262 if(_curchar != ';') { // check for semi-colon 1263 parse_err(SYNERR, "missing %c in preserve stack slot entry.\n", ';'); 1264 return; 1265 } 1266 next_char(); // skip the semi-colon 1267 } 1268 else { 1269 parse_err(SYNERR, "Missing %c in preserve stack slot entry.\n", '('); 1270 } 1271} 1272 1273//------------------------------calling_convention_parse----------------------- 1274char *ADLParser::calling_convention_parse() { 1275 char *desc = NULL; // String representation of calling_convention 1276 1277 skipws(); // Skip leading whitespace 1278 if ( (desc = find_cpp_block("calling convention block")) == NULL ) { 1279 parse_err(SYNERR, "incorrect or missing block for 'calling_convention'.\n"); 1280 } 1281 return desc; 1282} 1283 1284//------------------------------return_value_parse----------------------------- 1285char *ADLParser::return_value_parse() { 1286 char *desc = NULL; // String representation of calling_convention 1287 1288 skipws(); // Skip leading whitespace 1289 if ( (desc = find_cpp_block("return value block")) == NULL ) { 1290 parse_err(SYNERR, "incorrect or missing block for 'return_value'.\n"); 1291 } 1292 return desc; 1293} 1294 1295//------------------------------ins_pipe_parse--------------------------------- 1296void ADLParser::ins_pipe_parse(InstructForm &instr) { 1297 char * ident; 1298 1299 skipws(); 1300 if ( _curchar != '(' ) { // Check for delimiter 1301 parse_err(SYNERR, "missing \"(\" in ins_pipe definition\n"); 1302 return; 1303 } 1304 1305 next_char(); 1306 ident = get_ident(); // Grab next identifier 1307 1308 if (ident == NULL) { 1309 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 1310 return; 1311 } 1312 1313 skipws(); 1314 if ( _curchar != ')' ) { // Check for delimiter 1315 parse_err(SYNERR, "missing \")\" in ins_pipe definition\n"); 1316 return; 1317 } 1318 1319 next_char(); // skip the close paren 1320 if(_curchar != ';') { // check for semi-colon 1321 parse_err(SYNERR, "missing %c in return value entry.\n", ';'); 1322 return; 1323 } 1324 next_char(); // skip the semi-colon 1325 1326 // Check ident for validity 1327 if (_AD._pipeline && !_AD._pipeline->_classlist.search(ident)) { 1328 parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", ident); 1329 return; 1330 } 1331 1332 // Add this instruction to the list in the pipeline class 1333 _AD._pipeline->_classdict[ident]->is_pipeclass()->_instructs.addName(instr._ident); 1334 1335 // Set the name of the pipeline class in the instruction 1336 instr._ins_pipe = ident; 1337 return; 1338} 1339 1340//------------------------------pipe_parse------------------------------------- 1341void ADLParser::pipe_parse(void) { 1342 PipelineForm *pipeline; // Encode class for instruction/operand 1343 char * ident; 1344 1345 pipeline = new PipelineForm(); // Build new Source object 1346 _AD.addForm(pipeline); 1347 1348 skipws(); // Skip leading whitespace 1349 // Check for block delimiter 1350 if ( (_curchar != '%') 1351 || ( next_char(), (_curchar != '{')) ) { 1352 parse_err(SYNERR, "missing '%{' in pipeline definition\n"); 1353 return; 1354 } 1355 next_char(); // Maintain the invariant 1356 do { 1357 ident = get_ident(); // Grab next identifier 1358 if (ident == NULL) { 1359 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 1360 continue; 1361 } 1362 if (!strcmp(ident, "resources" )) resource_parse(*pipeline); 1363 else if (!strcmp(ident, "pipe_desc" )) pipe_desc_parse(*pipeline); 1364 else if (!strcmp(ident, "pipe_class")) pipe_class_parse(*pipeline); 1365 else if (!strcmp(ident, "define")) { 1366 skipws(); 1367 if ( (_curchar != '%') 1368 || ( next_char(), (_curchar != '{')) ) { 1369 parse_err(SYNERR, "expected '%{'\n"); 1370 return; 1371 } 1372 next_char(); skipws(); 1373 1374 char *node_class = get_ident(); 1375 if (node_class == NULL) { 1376 parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar); 1377 return; 1378 } 1379 1380 skipws(); 1381 if (_curchar != ',' && _curchar != '=') { 1382 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1383 break; 1384 } 1385 next_char(); skipws(); 1386 1387 char *pipe_class = get_ident(); 1388 if (pipe_class == NULL) { 1389 parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar); 1390 return; 1391 } 1392 if (_curchar != ';' ) { 1393 parse_err(SYNERR, "expected `;`, found '%c'\n", _curchar); 1394 break; 1395 } 1396 next_char(); // Skip over semi-colon 1397 1398 skipws(); 1399 if ( (_curchar != '%') 1400 || ( next_char(), (_curchar != '}')) ) { 1401 parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar); 1402 } 1403 next_char(); 1404 1405 // Check ident for validity 1406 if (_AD._pipeline && !_AD._pipeline->_classlist.search(pipe_class)) { 1407 parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", pipe_class); 1408 return; 1409 } 1410 1411 // Add this machine node to the list in the pipeline class 1412 _AD._pipeline->_classdict[pipe_class]->is_pipeclass()->_instructs.addName(node_class); 1413 1414 MachNodeForm *machnode = new MachNodeForm(node_class); // Create new machnode form 1415 machnode->_machnode_pipe = pipe_class; 1416 1417 _AD.addForm(machnode); 1418 } 1419 else if (!strcmp(ident, "attributes")) { 1420 bool vsi_seen = false, bhds_seen = false; 1421 1422 skipws(); 1423 if ( (_curchar != '%') 1424 || ( next_char(), (_curchar != '{')) ) { 1425 parse_err(SYNERR, "expected '%{'\n"); 1426 return; 1427 } 1428 next_char(); skipws(); 1429 1430 while (_curchar != '%') { 1431 ident = get_ident(); 1432 if (ident == NULL) 1433 break; 1434 1435 if (!strcmp(ident, "variable_size_instructions")) { 1436 skipws(); 1437 if (_curchar == ';') { 1438 next_char(); skipws(); 1439 } 1440 1441 pipeline->_variableSizeInstrs = true; 1442 vsi_seen = true; 1443 continue; 1444 } 1445 1446 if (!strcmp(ident, "fixed_size_instructions")) { 1447 skipws(); 1448 if (_curchar == ';') { 1449 next_char(); skipws(); 1450 } 1451 1452 pipeline->_variableSizeInstrs = false; 1453 vsi_seen = true; 1454 continue; 1455 } 1456 1457 if (!strcmp(ident, "branch_has_delay_slot")) { 1458 skipws(); 1459 if (_curchar == ';') { 1460 next_char(); skipws(); 1461 } 1462 1463 pipeline->_branchHasDelaySlot = true; 1464 bhds_seen = true; 1465 continue; 1466 } 1467 1468 if (!strcmp(ident, "max_instructions_per_bundle")) { 1469 skipws(); 1470 if (_curchar != '=') { 1471 parse_err(SYNERR, "expected `=`\n"); 1472 break; 1473 } 1474 1475 next_char(); skipws(); 1476 pipeline->_maxInstrsPerBundle = get_int(); 1477 skipws(); 1478 1479 if (_curchar == ';') { 1480 next_char(); skipws(); 1481 } 1482 1483 continue; 1484 } 1485 1486 if (!strcmp(ident, "max_bundles_per_cycle")) { 1487 skipws(); 1488 if (_curchar != '=') { 1489 parse_err(SYNERR, "expected `=`\n"); 1490 break; 1491 } 1492 1493 next_char(); skipws(); 1494 pipeline->_maxBundlesPerCycle = get_int(); 1495 skipws(); 1496 1497 if (_curchar == ';') { 1498 next_char(); skipws(); 1499 } 1500 1501 continue; 1502 } 1503 1504 if (!strcmp(ident, "instruction_unit_size")) { 1505 skipws(); 1506 if (_curchar != '=') { 1507 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1508 break; 1509 } 1510 1511 next_char(); skipws(); 1512 pipeline->_instrUnitSize = get_int(); 1513 skipws(); 1514 1515 if (_curchar == ';') { 1516 next_char(); skipws(); 1517 } 1518 1519 continue; 1520 } 1521 1522 if (!strcmp(ident, "bundle_unit_size")) { 1523 skipws(); 1524 if (_curchar != '=') { 1525 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1526 break; 1527 } 1528 1529 next_char(); skipws(); 1530 pipeline->_bundleUnitSize = get_int(); 1531 skipws(); 1532 1533 if (_curchar == ';') { 1534 next_char(); skipws(); 1535 } 1536 1537 continue; 1538 } 1539 1540 if (!strcmp(ident, "instruction_fetch_unit_size")) { 1541 skipws(); 1542 if (_curchar != '=') { 1543 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1544 break; 1545 } 1546 1547 next_char(); skipws(); 1548 pipeline->_instrFetchUnitSize = get_int(); 1549 skipws(); 1550 1551 if (_curchar == ';') { 1552 next_char(); skipws(); 1553 } 1554 1555 continue; 1556 } 1557 1558 if (!strcmp(ident, "instruction_fetch_units")) { 1559 skipws(); 1560 if (_curchar != '=') { 1561 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1562 break; 1563 } 1564 1565 next_char(); skipws(); 1566 pipeline->_instrFetchUnits = get_int(); 1567 skipws(); 1568 1569 if (_curchar == ';') { 1570 next_char(); skipws(); 1571 } 1572 1573 continue; 1574 } 1575 1576 if (!strcmp(ident, "nops")) { 1577 skipws(); 1578 if (_curchar != '(') { 1579 parse_err(SYNERR, "expected `(`, found '%c'\n", _curchar); 1580 break; 1581 } 1582 1583 next_char(); skipws(); 1584 1585 while (_curchar != ')') { 1586 ident = get_ident(); 1587 if (ident == NULL) { 1588 parse_err(SYNERR, "expected identifier for nop instruction, found '%c'\n", _curchar); 1589 break; 1590 } 1591 1592 pipeline->_noplist.addName(ident); 1593 pipeline->_nopcnt++; 1594 skipws(); 1595 1596 if (_curchar == ',') { 1597 next_char(); skipws(); 1598 } 1599 } 1600 1601 next_char(); skipws(); 1602 1603 if (_curchar == ';') { 1604 next_char(); skipws(); 1605 } 1606 1607 continue; 1608 } 1609 1610 parse_err(SYNERR, "unknown specifier \"%s\"\n", ident); 1611 } 1612 1613 if ( (_curchar != '%') 1614 || ( next_char(), (_curchar != '}')) ) { 1615 parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar); 1616 } 1617 next_char(); skipws(); 1618 1619 if (pipeline->_maxInstrsPerBundle == 0) 1620 parse_err(SYNERR, "\"max_instructions_per_bundle\" unspecified\n"); 1621 if (pipeline->_instrUnitSize == 0 && pipeline->_bundleUnitSize == 0) 1622 parse_err(SYNERR, "\"instruction_unit_size\" and \"bundle_unit_size\" unspecified\n"); 1623 if (pipeline->_instrFetchUnitSize == 0) 1624 parse_err(SYNERR, "\"instruction_fetch_unit_size\" unspecified\n"); 1625 if (pipeline->_instrFetchUnits == 0) 1626 parse_err(SYNERR, "\"instruction_fetch_units\" unspecified\n"); 1627 if (!vsi_seen) 1628 parse_err(SYNERR, "\"variable_size_instruction\" or \"fixed_size_instruction\" unspecified\n"); 1629 } 1630 else { // Done with staticly defined parts of instruction definition 1631 parse_err(SYNERR, "expected one of \"resources\", \"pipe_desc\", \"pipe_class\", found \"%s\"\n", ident); 1632 return; 1633 } 1634 skipws(); 1635 if (_curchar == ';') 1636 skipws(); 1637 } while(_curchar != '%'); 1638 1639 next_char(); 1640 if (_curchar != '}') { 1641 parse_err(SYNERR, "missing \"%}\" in pipeline definition\n"); 1642 return; 1643 } 1644 1645 next_char(); 1646} 1647 1648//------------------------------resource_parse---------------------------- 1649void ADLParser::resource_parse(PipelineForm &pipeline) { 1650 ResourceForm *resource; 1651 char * ident; 1652 char * expr; 1653 unsigned mask; 1654 pipeline._rescount = 0; 1655 1656 skipws(); // Skip leading whitespace 1657 1658 if (_curchar != '(') { 1659 parse_err(SYNERR, "missing \"(\" in resource definition\n"); 1660 return; 1661 } 1662 1663 do { 1664 next_char(); // Skip "(" or "," 1665 ident = get_ident(); // Grab next identifier 1666 1667 if (ident == NULL) { 1668 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1669 return; 1670 } 1671 skipws(); 1672 1673 if (_curchar != '=') { 1674 mask = (1 << pipeline._rescount++); 1675 } 1676 else { 1677 next_char(); skipws(); 1678 expr = get_ident(); // Grab next identifier 1679 if (expr == NULL) { 1680 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1681 return; 1682 } 1683 resource = (ResourceForm *) pipeline._resdict[expr]; 1684 if (resource == NULL) { 1685 parse_err(SYNERR, "resource \"%s\" is not defined\n", expr); 1686 return; 1687 } 1688 mask = resource->mask(); 1689 1690 skipws(); 1691 while (_curchar == '|') { 1692 next_char(); skipws(); 1693 1694 expr = get_ident(); // Grab next identifier 1695 if (expr == NULL) { 1696 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1697 return; 1698 } 1699 1700 resource = (ResourceForm *) pipeline._resdict[expr]; // Look up the value 1701 if (resource == NULL) { 1702 parse_err(SYNERR, "resource \"%s\" is not defined\n", expr); 1703 return; 1704 } 1705 1706 mask |= resource->mask(); 1707 skipws(); 1708 } 1709 } 1710 1711 resource = new ResourceForm(mask); 1712 1713 pipeline._resdict.Insert(ident, resource); 1714 pipeline._reslist.addName(ident); 1715 } while (_curchar == ','); 1716 1717 if (_curchar != ')') { 1718 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 1719 return; 1720 } 1721 1722 next_char(); // Skip ")" 1723 if (_curchar == ';') 1724 next_char(); // Skip ";" 1725} 1726 1727//------------------------------resource_parse---------------------------- 1728void ADLParser::pipe_desc_parse(PipelineForm &pipeline) { 1729 char * ident; 1730 1731 skipws(); // Skip leading whitespace 1732 1733 if (_curchar != '(') { 1734 parse_err(SYNERR, "missing \"(\" in pipe_desc definition\n"); 1735 return; 1736 } 1737 1738 do { 1739 next_char(); // Skip "(" or "," 1740 ident = get_ident(); // Grab next identifier 1741 if (ident == NULL) { 1742 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1743 return; 1744 } 1745 1746 // Add the name to the list 1747 pipeline._stages.addName(ident); 1748 pipeline._stagecnt++; 1749 1750 skipws(); 1751 } while (_curchar == ','); 1752 1753 if (_curchar != ')') { 1754 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 1755 return; 1756 } 1757 1758 next_char(); // Skip ")" 1759 if (_curchar == ';') 1760 next_char(); // Skip ";" 1761} 1762 1763//------------------------------pipe_class_parse-------------------------- 1764void ADLParser::pipe_class_parse(PipelineForm &pipeline) { 1765 PipeClassForm *pipe_class; 1766 char * ident; 1767 char * stage; 1768 char * read_or_write; 1769 int is_write; 1770 int is_read; 1771 OperandForm *oper; 1772 1773 skipws(); // Skip leading whitespace 1774 1775 ident = get_ident(); // Grab next identifier 1776 1777 if (ident == NULL) { 1778 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1779 return; 1780 } 1781 1782 // Create a record for the pipe_class 1783 pipe_class = new PipeClassForm(ident, ++pipeline._classcnt); 1784 pipeline._classdict.Insert(ident, pipe_class); 1785 pipeline._classlist.addName(ident); 1786 1787 // Then get the operands 1788 skipws(); 1789 if (_curchar != '(') { 1790 parse_err(SYNERR, "missing \"(\" in pipe_class definition\n"); 1791 } 1792 // Parse the operand list 1793 else get_oplist(pipe_class->_parameters, pipe_class->_localNames); 1794 skipws(); // Skip leading whitespace 1795 // Check for block delimiter 1796 if ( (_curchar != '%') 1797 || ( next_char(), (_curchar != '{')) ) { 1798 parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n"); 1799 return; 1800 } 1801 next_char(); 1802 1803 do { 1804 ident = get_ident(); // Grab next identifier 1805 if (ident == NULL) { 1806 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1807 continue; 1808 } 1809 skipws(); 1810 1811 if (!strcmp(ident, "fixed_latency")) { 1812 skipws(); 1813 if (_curchar != '(') { 1814 parse_err(SYNERR, "missing \"(\" in latency definition\n"); 1815 return; 1816 } 1817 next_char(); skipws(); 1818 if( !isdigit(_curchar) ) { 1819 parse_err(SYNERR, "number expected for \"%c\" in latency definition\n", _curchar); 1820 return; 1821 } 1822 int fixed_latency = get_int(); 1823 skipws(); 1824 if (_curchar != ')') { 1825 parse_err(SYNERR, "missing \")\" in latency definition\n"); 1826 return; 1827 } 1828 next_char(); skipws(); 1829 if (_curchar != ';') { 1830 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1831 return; 1832 } 1833 1834 pipe_class->setFixedLatency(fixed_latency); 1835 next_char(); skipws(); 1836 continue; 1837 } 1838 1839 if (!strcmp(ident, "zero_instructions") || 1840 !strcmp(ident, "no_instructions")) { 1841 skipws(); 1842 if (_curchar != ';') { 1843 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1844 return; 1845 } 1846 1847 pipe_class->setInstructionCount(0); 1848 next_char(); skipws(); 1849 continue; 1850 } 1851 1852 if (!strcmp(ident, "one_instruction_with_delay_slot") || 1853 !strcmp(ident, "single_instruction_with_delay_slot")) { 1854 skipws(); 1855 if (_curchar != ';') { 1856 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1857 return; 1858 } 1859 1860 pipe_class->setInstructionCount(1); 1861 pipe_class->setBranchDelay(true); 1862 next_char(); skipws(); 1863 continue; 1864 } 1865 1866 if (!strcmp(ident, "one_instruction") || 1867 !strcmp(ident, "single_instruction")) { 1868 skipws(); 1869 if (_curchar != ';') { 1870 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1871 return; 1872 } 1873 1874 pipe_class->setInstructionCount(1); 1875 next_char(); skipws(); 1876 continue; 1877 } 1878 1879 if (!strcmp(ident, "instructions_in_first_bundle") || 1880 !strcmp(ident, "instruction_count")) { 1881 skipws(); 1882 1883 int number_of_instructions = 1; 1884 1885 if (_curchar != '(') { 1886 parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar); 1887 continue; 1888 } 1889 1890 next_char(); skipws(); 1891 number_of_instructions = get_int(); 1892 1893 skipws(); 1894 if (_curchar != ')') { 1895 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 1896 continue; 1897 } 1898 1899 next_char(); skipws(); 1900 if (_curchar != ';') { 1901 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1902 return; 1903 } 1904 1905 pipe_class->setInstructionCount(number_of_instructions); 1906 next_char(); skipws(); 1907 continue; 1908 } 1909 1910 if (!strcmp(ident, "multiple_bundles")) { 1911 skipws(); 1912 if (_curchar != ';') { 1913 parse_err(SYNERR, "missing \";\" after multiple bundles\n"); 1914 return; 1915 } 1916 1917 pipe_class->setMultipleBundles(true); 1918 next_char(); skipws(); 1919 continue; 1920 } 1921 1922 if (!strcmp(ident, "has_delay_slot")) { 1923 skipws(); 1924 if (_curchar != ';') { 1925 parse_err(SYNERR, "missing \";\" after \"has_delay_slot\"\n"); 1926 return; 1927 } 1928 1929 pipe_class->setBranchDelay(true); 1930 next_char(); skipws(); 1931 continue; 1932 } 1933 1934 if (!strcmp(ident, "force_serialization")) { 1935 skipws(); 1936 if (_curchar != ';') { 1937 parse_err(SYNERR, "missing \";\" after \"force_serialization\"\n"); 1938 return; 1939 } 1940 1941 pipe_class->setForceSerialization(true); 1942 next_char(); skipws(); 1943 continue; 1944 } 1945 1946 if (!strcmp(ident, "may_have_no_code")) { 1947 skipws(); 1948 if (_curchar != ';') { 1949 parse_err(SYNERR, "missing \";\" after \"may_have_no_code\"\n"); 1950 return; 1951 } 1952 1953 pipe_class->setMayHaveNoCode(true); 1954 next_char(); skipws(); 1955 continue; 1956 } 1957 1958 const Form *parm = pipe_class->_localNames[ident]; 1959 if (parm != NULL) { 1960 oper = parm->is_operand(); 1961 if (oper == NULL && !parm->is_opclass()) { 1962 parse_err(SYNERR, "operand name expected at %s\n", ident); 1963 continue; 1964 } 1965 1966 if (_curchar != ':') { 1967 parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar); 1968 continue; 1969 } 1970 next_char(); skipws(); 1971 stage = get_ident(); 1972 if (stage == NULL) { 1973 parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar); 1974 continue; 1975 } 1976 1977 skipws(); 1978 if (_curchar != '(') { 1979 parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar); 1980 continue; 1981 } 1982 1983 next_char(); 1984 read_or_write = get_ident(); 1985 if (read_or_write == NULL) { 1986 parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar); 1987 continue; 1988 } 1989 1990 is_read = strcmp(read_or_write, "read") == 0; 1991 is_write = strcmp(read_or_write, "write") == 0; 1992 if (!is_read && !is_write) { 1993 parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar); 1994 continue; 1995 } 1996 1997 skipws(); 1998 if (_curchar != ')') { 1999 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 2000 continue; 2001 } 2002 2003 next_char(); skipws(); 2004 int more_instrs = 0; 2005 if (_curchar == '+') { 2006 next_char(); skipws(); 2007 if (_curchar < '0' || _curchar > '9') { 2008 parse_err(SYNERR, "<number> expected at \"%c\"\n", _curchar); 2009 continue; 2010 } 2011 while (_curchar >= '0' && _curchar <= '9') { 2012 more_instrs *= 10; 2013 more_instrs += _curchar - '0'; 2014 next_char(); 2015 } 2016 skipws(); 2017 } 2018 2019 PipeClassOperandForm *pipe_operand = new PipeClassOperandForm(stage, is_write, more_instrs); 2020 pipe_class->_localUsage.Insert(ident, pipe_operand); 2021 2022 if (_curchar == '%') 2023 continue; 2024 2025 if (_curchar != ';') { 2026 parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar); 2027 continue; 2028 } 2029 next_char(); skipws(); 2030 continue; 2031 } 2032 2033 // Scan for Resource Specifier 2034 const Form *res = pipeline._resdict[ident]; 2035 if (res != NULL) { 2036 int cyclecnt = 1; 2037 if (_curchar != ':') { 2038 parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar); 2039 continue; 2040 } 2041 next_char(); skipws(); 2042 stage = get_ident(); 2043 if (stage == NULL) { 2044 parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar); 2045 continue; 2046 } 2047 2048 skipws(); 2049 if (_curchar == '(') { 2050 next_char(); 2051 cyclecnt = get_int(); 2052 2053 skipws(); 2054 if (_curchar != ')') { 2055 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 2056 continue; 2057 } 2058 2059 next_char(); skipws(); 2060 } 2061 2062 PipeClassResourceForm *resource = new PipeClassResourceForm(ident, stage, cyclecnt); 2063 int stagenum = pipeline._stages.index(stage); 2064 if (pipeline._maxcycleused < (stagenum+cyclecnt)) 2065 pipeline._maxcycleused = (stagenum+cyclecnt); 2066 pipe_class->_resUsage.addForm(resource); 2067 2068 if (_curchar == '%') 2069 continue; 2070 2071 if (_curchar != ';') { 2072 parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar); 2073 continue; 2074 } 2075 next_char(); skipws(); 2076 continue; 2077 } 2078 2079 parse_err(SYNERR, "resource expected at \"%s\"\n", ident); 2080 return; 2081 } while(_curchar != '%'); 2082 2083 next_char(); 2084 if (_curchar != '}') { 2085 parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n"); 2086 return; 2087 } 2088 2089 next_char(); 2090} 2091 2092//------------------------------peep_parse------------------------------------- 2093void ADLParser::peep_parse(void) { 2094 Peephole *peep; // Pointer to current peephole rule form 2095 char *desc = NULL; // String representation of rule 2096 2097 skipws(); // Skip leading whitespace 2098 2099 peep = new Peephole(); // Build new Peephole object 2100 // Check for open block sequence 2101 skipws(); // Skip leading whitespace 2102 if (_curchar == '%' && *(_ptr+1) == '{') { 2103 next_char(); next_char(); // Skip "%{" 2104 skipws(); 2105 while (_curchar != '%' && *(_ptr+1) != '}') { 2106 char *token = get_ident(); 2107 if (token == NULL) { 2108 parse_err(SYNERR, "missing identifier inside peephole rule.\n"); 2109 return; 2110 } 2111 // check for legal subsections of peephole rule 2112 if (strcmp(token,"peepmatch")==0) { 2113 peep_match_parse(*peep); } 2114 else if (strcmp(token,"peepconstraint")==0) { 2115 peep_constraint_parse(*peep); } 2116 else if (strcmp(token,"peepreplace")==0) { 2117 peep_replace_parse(*peep); } 2118 else { 2119 parse_err(SYNERR, "expected peepmatch, peepconstraint, or peepreplace for identifier %s.\n", token); 2120 } 2121 skipws(); 2122 } 2123 } 2124 else { 2125 parse_err(SYNERR, "Missing %%{ ... %%} block after peephole keyword.\n"); 2126 return; 2127 } 2128 next_char(); // Skip past '%' 2129 next_char(); // Skip past '}' 2130} 2131 2132// ******************** Private Level 2 Parse Functions ******************** 2133//------------------------------constraint_parse------------------------------ 2134Constraint *ADLParser::constraint_parse(void) { 2135 char *func; 2136 char *arg; 2137 2138 // Check for constraint expression 2139 skipws(); 2140 if (_curchar != '(') { 2141 parse_err(SYNERR, "missing constraint expression, (...)\n"); 2142 return NULL; 2143 } 2144 next_char(); // Skip past '(' 2145 2146 // Get constraint function 2147 skipws(); 2148 func = get_ident(); 2149 if (func == NULL) { 2150 parse_err(SYNERR, "missing function in constraint expression.\n"); 2151 return NULL; 2152 } 2153 if (strcmp(func,"ALLOC_IN_RC")==0 2154 || strcmp(func,"IS_R_CLASS")==0) { 2155 // Check for '(' before argument 2156 skipws(); 2157 if (_curchar != '(') { 2158 parse_err(SYNERR, "missing '(' for constraint function's argument.\n"); 2159 return NULL; 2160 } 2161 next_char(); 2162 2163 // Get it's argument 2164 skipws(); 2165 arg = get_ident(); 2166 if (arg == NULL) { 2167 parse_err(SYNERR, "missing argument for constraint function %s\n",func); 2168 return NULL; 2169 } 2170 // Check for ')' after argument 2171 skipws(); 2172 if (_curchar != ')') { 2173 parse_err(SYNERR, "missing ')' after constraint function argument %s\n",arg); 2174 return NULL; 2175 } 2176 next_char(); 2177 } else { 2178 parse_err(SYNERR, "Invalid constraint function %s\n",func); 2179 return NULL; 2180 } 2181 2182 // Check for closing paren and ';' 2183 skipws(); 2184 if (_curchar != ')') { 2185 parse_err(SYNERR, "Missing ')' for constraint function %s\n",func); 2186 return NULL; 2187 } 2188 next_char(); 2189 skipws(); 2190 if (_curchar != ';') { 2191 parse_err(SYNERR, "Missing ';' after constraint.\n"); 2192 return NULL; 2193 } 2194 next_char(); 2195 2196 // Create new "Constraint" 2197 Constraint *constraint = new Constraint(func,arg); 2198 return constraint; 2199} 2200 2201//------------------------------constr_parse----------------------------------- 2202ConstructRule *ADLParser::construct_parse(void) { 2203 return NULL; 2204} 2205 2206 2207//------------------------------reg_def_parse---------------------------------- 2208void ADLParser::reg_def_parse(void) { 2209 char *rname; // Name of register being defined 2210 2211 // Get register name 2212 skipws(); // Skip whitespace 2213 rname = get_ident(); 2214 if (rname == NULL) { 2215 parse_err(SYNERR, "missing register name after reg_def\n"); 2216 return; 2217 } 2218 2219 // Check for definition of register calling convention (save on call, ...), 2220 // register save type, and register encoding value. 2221 skipws(); 2222 char *callconv = NULL; 2223 char *c_conv = NULL; 2224 char *idealtype = NULL; 2225 char *encoding = NULL; 2226 char *concrete = NULL; 2227 if (_curchar == '(') { 2228 next_char(); 2229 callconv = get_ident(); 2230 // Parse the internal calling convention, must be NS, SOC, SOE, or AS. 2231 if (callconv == NULL) { 2232 parse_err(SYNERR, "missing register calling convention value\n"); 2233 return; 2234 } 2235 if(strcmp(callconv, "SOC") && strcmp(callconv,"SOE") && 2236 strcmp(callconv, "NS") && strcmp(callconv, "AS")) { 2237 parse_err(SYNERR, "invalid value for register calling convention\n"); 2238 } 2239 skipws(); 2240 if (_curchar != ',') { 2241 parse_err(SYNERR, "missing comma in register definition statement\n"); 2242 return; 2243 } 2244 next_char(); 2245 2246 // Parse the native calling convention, must be NS, SOC, SOE, AS 2247 c_conv = get_ident(); 2248 if (c_conv == NULL) { 2249 parse_err(SYNERR, "missing register native calling convention value\n"); 2250 return; 2251 } 2252 if(strcmp(c_conv, "SOC") && strcmp(c_conv,"SOE") && 2253 strcmp(c_conv, "NS") && strcmp(c_conv, "AS")) { 2254 parse_err(SYNERR, "invalid value for register calling convention\n"); 2255 } 2256 skipws(); 2257 if (_curchar != ',') { 2258 parse_err(SYNERR, "missing comma in register definition statement\n"); 2259 return; 2260 } 2261 next_char(); 2262 skipws(); 2263 2264 // Parse the ideal save type 2265 idealtype = get_ident(); 2266 if (idealtype == NULL) { 2267 parse_err(SYNERR, "missing register save type value\n"); 2268 return; 2269 } 2270 skipws(); 2271 if (_curchar != ',') { 2272 parse_err(SYNERR, "missing comma in register definition statement\n"); 2273 return; 2274 } 2275 next_char(); 2276 skipws(); 2277 2278 // Parse the encoding value 2279 encoding = get_expr("encoding", ","); 2280 if (encoding == NULL) { 2281 parse_err(SYNERR, "missing register encoding value\n"); 2282 return; 2283 } 2284 trim(encoding); 2285 if (_curchar != ',') { 2286 parse_err(SYNERR, "missing comma in register definition statement\n"); 2287 return; 2288 } 2289 next_char(); 2290 skipws(); 2291 // Parse the concrete name type 2292 // concrete = get_ident(); 2293 concrete = get_expr("concrete", ")"); 2294 if (concrete == NULL) { 2295 parse_err(SYNERR, "missing vm register name value\n"); 2296 return; 2297 } 2298 2299 if (_curchar != ')') { 2300 parse_err(SYNERR, "missing ')' in register definition statement\n"); 2301 return; 2302 } 2303 next_char(); 2304 } 2305 2306 // Check for closing ';' 2307 skipws(); 2308 if (_curchar != ';') { 2309 parse_err(SYNERR, "missing ';' after reg_def\n"); 2310 return; 2311 } 2312 next_char(); // move past ';' 2313 2314 // Debug Stuff 2315 if (_AD._adl_debug > 1) { 2316 fprintf(stderr,"Register Definition: %s ( %s, %s %s )\n", rname, 2317 (callconv ? callconv : ""), (c_conv ? c_conv : ""), concrete); 2318 } 2319 2320 // Record new register definition. 2321 _AD._register->addRegDef(rname, callconv, c_conv, idealtype, encoding, concrete); 2322 return; 2323} 2324 2325//------------------------------reg_class_parse-------------------------------- 2326void ADLParser::reg_class_parse(void) { 2327 char *cname; // Name of register class being defined 2328 2329 // Get register class name 2330 skipws(); // Skip leading whitespace 2331 cname = get_ident(); 2332 if (cname == NULL) { 2333 parse_err(SYNERR, "missing register class name after 'reg_class'\n"); 2334 return; 2335 } 2336 // Debug Stuff 2337 if (_AD._adl_debug >1) fprintf(stderr,"Register Class: %s\n", cname); 2338 2339 RegClass *reg_class = _AD._register->addRegClass(cname); 2340 2341 // Collect registers in class 2342 skipws(); 2343 if (_curchar == '(') { 2344 next_char(); // Skip '(' 2345 skipws(); 2346 while (_curchar != ')') { 2347 char *rname = get_ident(); 2348 if (rname==NULL) { 2349 parse_err(SYNERR, "missing identifier inside reg_class list.\n"); 2350 return; 2351 } 2352 RegDef *regDef = _AD._register->getRegDef(rname); 2353 reg_class->addReg(regDef); // add regDef to regClass 2354 2355 // Check for ',' and position to next token. 2356 skipws(); 2357 if (_curchar == ',') { 2358 next_char(); // Skip trailing ',' 2359 skipws(); 2360 } 2361 } 2362 next_char(); // Skip closing ')' 2363 } 2364 2365 // Check for terminating ';' 2366 skipws(); 2367 if (_curchar != ';') { 2368 parse_err(SYNERR, "missing ';' at end of reg_class definition.\n"); 2369 return; 2370 } 2371 next_char(); // Skip trailing ';' 2372 2373 // Check RegClass size, must be <= 32 registers in class. 2374 2375 return; 2376} 2377 2378//------------------------------alloc_class_parse------------------------------ 2379void ADLParser::alloc_class_parse(void) { 2380 char *name; // Name of allocation class being defined 2381 2382 // Get allocation class name 2383 skipws(); // Skip leading whitespace 2384 name = get_ident(); 2385 if (name == NULL) { 2386 parse_err(SYNERR, "missing allocation class name after 'reg_class'\n"); 2387 return; 2388 } 2389 // Debug Stuff 2390 if (_AD._adl_debug >1) fprintf(stderr,"Allocation Class: %s\n", name); 2391 2392 AllocClass *alloc_class = _AD._register->addAllocClass(name); 2393 2394 // Collect registers in class 2395 skipws(); 2396 if (_curchar == '(') { 2397 next_char(); // Skip '(' 2398 skipws(); 2399 while (_curchar != ')') { 2400 char *rname = get_ident(); 2401 if (rname==NULL) { 2402 parse_err(SYNERR, "missing identifier inside reg_class list.\n"); 2403 return; 2404 } 2405 // Check if name is a RegDef 2406 RegDef *regDef = _AD._register->getRegDef(rname); 2407 if (regDef) { 2408 alloc_class->addReg(regDef); // add regDef to allocClass 2409 } else { 2410 2411 // name must be a RegDef or a RegClass 2412 parse_err(SYNERR, "name %s should be a previously defined reg_def.\n", rname); 2413 return; 2414 } 2415 2416 // Check for ',' and position to next token. 2417 skipws(); 2418 if (_curchar == ',') { 2419 next_char(); // Skip trailing ',' 2420 skipws(); 2421 } 2422 } 2423 next_char(); // Skip closing ')' 2424 } 2425 2426 // Check for terminating ';' 2427 skipws(); 2428 if (_curchar != ';') { 2429 parse_err(SYNERR, "missing ';' at end of reg_class definition.\n"); 2430 return; 2431 } 2432 next_char(); // Skip trailing ';' 2433 2434 return; 2435} 2436 2437//------------------------------peep_match_child_parse------------------------- 2438InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, int &position, int input){ 2439 char *token = NULL; 2440 int lparen = 0; // keep track of parenthesis nesting depth 2441 int rparen = 0; // position of instruction at this depth 2442 InstructForm *inst_seen = NULL; 2443 InstructForm *child_seen = NULL; 2444 2445 // Walk the match tree, 2446 // Record <parent, position, instruction name, input position> 2447 while ( lparen >= rparen ) { 2448 skipws(); 2449 // Left paren signals start of an input, collect with recursive call 2450 if (_curchar == '(') { 2451 ++lparen; 2452 next_char(); 2453 child_seen = peep_match_child_parse(match, parent, position, rparen); 2454 } 2455 // Right paren signals end of an input, may be more 2456 else if (_curchar == ')') { 2457 ++rparen; 2458 if( rparen == lparen ) { // IF rparen matches an lparen I've seen 2459 next_char(); // move past ')' 2460 } else { // ELSE leave ')' for parent 2461 assert( rparen == lparen + 1, "Should only see one extra ')'"); 2462 // if an instruction was not specified for this paren-pair 2463 if( ! inst_seen ) { // record signal entry 2464 match.add_instruction( parent, position, NameList::_signal, input ); 2465 ++position; 2466 } 2467 // ++input; // TEMPORARY 2468 return inst_seen; 2469 } 2470 } 2471 // if no parens, then check for instruction name 2472 // This instruction is the parent of a sub-tree 2473 else if ((token = get_ident_dup()) != NULL) { 2474 const Form *form = _AD._globalNames[token]; 2475 if (form) { 2476 InstructForm *inst = form->is_instruction(); 2477 // Record the first instruction at this level 2478 if( inst_seen == NULL ) { 2479 inst_seen = inst; 2480 } 2481 if (inst) { 2482 match.add_instruction( parent, position, token, input ); 2483 parent = position; 2484 ++position; 2485 } else { 2486 parse_err(SYNERR, "instruction name expected at identifier %s.\n", 2487 token); 2488 return inst_seen; 2489 } 2490 } 2491 else { 2492 parse_err(SYNERR, "missing identifier in peepmatch rule.\n"); 2493 return NULL; 2494 } 2495 } 2496 else { 2497 parse_err(SYNERR, "missing identifier in peepmatch rule.\n"); 2498 return NULL; 2499 } 2500 2501 } // end while 2502 2503 assert( false, "ShouldNotReachHere();"); 2504 return NULL; 2505} 2506 2507//------------------------------peep_match_parse------------------------------- 2508// Syntax for a peepmatch rule 2509// 2510// peepmatch ( root_instr_name [(instruction subtree)] [,(instruction subtree)]* ); 2511// 2512void ADLParser::peep_match_parse(Peephole &peep) { 2513 2514 skipws(); 2515 // Check the structure of the rule 2516 // Check for open paren 2517 if (_curchar != '(') { 2518 parse_err(SYNERR, "missing '(' at start of peepmatch rule.\n"); 2519 return; 2520 } 2521 next_char(); // skip '(' 2522 2523 // Construct PeepMatch and parse the peepmatch rule. 2524 PeepMatch *match = new PeepMatch(_ptr); 2525 int parent = -1; // parent of root 2526 int position = 0; // zero-based positions 2527 int input = 0; // input position in parent's operands 2528 InstructForm *root= peep_match_child_parse( *match, parent, position, input); 2529 if( root == NULL ) { 2530 parse_err(SYNERR, "missing instruction-name at start of peepmatch.\n"); 2531 return; 2532 } 2533 2534 if( _curchar != ')' ) { 2535 parse_err(SYNERR, "missing ')' at end of peepmatch.\n"); 2536 return; 2537 } 2538 next_char(); // skip ')' 2539 2540 // Check for closing semicolon 2541 skipws(); 2542 if( _curchar != ';' ) { 2543 parse_err(SYNERR, "missing ';' at end of peepmatch.\n"); 2544 return; 2545 } 2546 next_char(); // skip ';' 2547 2548 // Store match into peep, and store peep into instruction 2549 peep.add_match(match); 2550 root->append_peephole(&peep); 2551} 2552 2553//------------------------------peep_constraint_parse-------------------------- 2554// Syntax for a peepconstraint rule 2555// A parenthesized list of relations between operands in peepmatch subtree 2556// 2557// peepconstraint %{ 2558// (instruction_number.operand_name 2559// relational_op 2560// instruction_number.operand_name OR register_name 2561// [, ...] ); 2562// 2563// // instruction numbers are zero-based using topological order in peepmatch 2564// 2565void ADLParser::peep_constraint_parse(Peephole &peep) { 2566 2567 skipws(); 2568 // Check the structure of the rule 2569 // Check for open paren 2570 if (_curchar != '(') { 2571 parse_err(SYNERR, "missing '(' at start of peepconstraint rule.\n"); 2572 return; 2573 } 2574 else { 2575 next_char(); // Skip '(' 2576 } 2577 2578 // Check for a constraint 2579 skipws(); 2580 while( _curchar != ')' ) { 2581 // Get information on the left instruction and its operand 2582 // left-instructions's number 2583 intptr_t left_inst = get_int(); 2584 // Left-instruction's operand 2585 skipws(); 2586 if( _curchar != '.' ) { 2587 parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n"); 2588 return; 2589 } 2590 next_char(); // Skip '.' 2591 char *left_op = get_ident_dup(); 2592 2593 skipws(); 2594 // Collect relational operator 2595 char *relation = get_relation_dup(); 2596 2597 skipws(); 2598 // Get information on the right instruction and its operand 2599 intptr_t right_inst; // Right-instructions's number 2600 if( isdigit(_curchar) ) { 2601 right_inst = get_int(); 2602 // Right-instruction's operand 2603 skipws(); 2604 if( _curchar != '.' ) { 2605 parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n"); 2606 return; 2607 } 2608 next_char(); // Skip '.' 2609 } else { 2610 right_inst = -1; // Flag as being a register constraint 2611 } 2612 2613 char *right_op = get_ident_dup(); 2614 2615 // Construct the next PeepConstraint 2616 PeepConstraint *constraint = new PeepConstraint( left_inst, left_op, 2617 relation, 2618 right_inst, right_op ); 2619 // And append it to the list for this peephole rule 2620 peep.append_constraint( constraint ); 2621 2622 // Check for another constraint, or end of rule 2623 skipws(); 2624 if( _curchar == ',' ) { 2625 next_char(); // Skip ',' 2626 skipws(); 2627 } 2628 else if( _curchar != ')' ) { 2629 parse_err(SYNERR, "expected ',' or ')' after peephole constraint.\n"); 2630 return; 2631 } 2632 } // end while( processing constraints ) 2633 next_char(); // Skip ')' 2634 2635 // Check for terminating ';' 2636 skipws(); 2637 if (_curchar != ';') { 2638 parse_err(SYNERR, "missing ';' at end of peepconstraint.\n"); 2639 return; 2640 } 2641 next_char(); // Skip trailing ';' 2642} 2643 2644 2645//------------------------------peep_replace_parse----------------------------- 2646// Syntax for a peepreplace rule 2647// root instruction name followed by a 2648// parenthesized list of whitespace separated instruction.operand specifiers 2649// 2650// peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 2651// 2652// 2653void ADLParser::peep_replace_parse(Peephole &peep) { 2654 int lparen = 0; // keep track of parenthesis nesting depth 2655 int rparen = 0; // keep track of parenthesis nesting depth 2656 int icount = 0; // count of instructions in rule for naming 2657 char *str = NULL; 2658 char *token = NULL; 2659 2660 skipws(); 2661 // Check for open paren 2662 if (_curchar != '(') { 2663 parse_err(SYNERR, "missing '(' at start of peepreplace rule.\n"); 2664 return; 2665 } 2666 else { 2667 lparen++; 2668 next_char(); 2669 } 2670 2671 // Check for root instruction 2672 char *inst = get_ident_dup(); 2673 const Form *form = _AD._globalNames[inst]; 2674 if( form == NULL || form->is_instruction() == NULL ) { 2675 parse_err(SYNERR, "Instruction name expected at start of peepreplace.\n"); 2676 return; 2677 } 2678 2679 // Store string representation of rule into replace 2680 PeepReplace *replace = new PeepReplace(str); 2681 replace->add_instruction( inst ); 2682 2683 skipws(); 2684 // Start of root's operand-list 2685 if (_curchar != '(') { 2686 parse_err(SYNERR, "missing '(' at peepreplace root's operand-list.\n"); 2687 return; 2688 } 2689 else { 2690 lparen++; 2691 next_char(); 2692 } 2693 2694 skipws(); 2695 // Get the list of operands 2696 while( _curchar != ')' ) { 2697 // Get information on an instruction and its operand 2698 // instructions's number 2699 int inst_num = get_int(); 2700 // Left-instruction's operand 2701 skipws(); 2702 if( _curchar != '.' ) { 2703 parse_err(SYNERR, "missing '.' in peepreplace after instruction number.\n"); 2704 return; 2705 } 2706 next_char(); // Skip '.' 2707 char *inst_op = get_ident_dup(); 2708 if( inst_op == NULL ) { 2709 parse_err(SYNERR, "missing operand identifier in peepreplace.\n"); 2710 return; 2711 } 2712 2713 // Record this operand's position in peepmatch 2714 replace->add_operand( inst_num, inst_op ); 2715 skipws(); 2716 } 2717 2718 // Check for the end of operands list 2719 skipws(); 2720 assert( _curchar == ')', "While loop should have advanced to ')'."); 2721 next_char(); // Skip ')' 2722 2723 skipws(); 2724 // Check for end of peepreplace 2725 if( _curchar != ')' ) { 2726 parse_err(SYNERR, "missing ')' at end of peepmatch.\n"); 2727 parse_err(SYNERR, "Support one replacement instruction.\n"); 2728 return; 2729 } 2730 next_char(); // Skip ')' 2731 2732 // Check for closing semicolon 2733 skipws(); 2734 if( _curchar != ';' ) { 2735 parse_err(SYNERR, "missing ';' at end of peepreplace.\n"); 2736 return; 2737 } 2738 next_char(); // skip ';' 2739 2740 // Store replace into peep 2741 peep.add_replace( replace ); 2742} 2743 2744//------------------------------pred_parse------------------------------------- 2745Predicate *ADLParser::pred_parse(void) { 2746 Predicate *predicate; // Predicate class for operand 2747 char *rule = NULL; // String representation of predicate 2748 2749 skipws(); // Skip leading whitespace 2750 if ( (rule = get_paren_expr("pred expression")) == NULL ) { 2751 parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n"); 2752 return NULL; 2753 } 2754 // Debug Stuff 2755 if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule); 2756 if (_curchar != ';') { 2757 parse_err(SYNERR, "missing ';' in predicate definition\n"); 2758 return NULL; 2759 } 2760 next_char(); // Point after the terminator 2761 2762 predicate = new Predicate(rule); // Build new predicate object 2763 skipws(); 2764 return predicate; 2765} 2766 2767 2768//------------------------------ins_encode_parse_block------------------------- 2769// Parse the block form of ins_encode. See ins_encode_parse for more details 2770InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) { 2771 // Create a new encoding name based on the name of the instruction 2772 // definition, which should be unique. 2773 const char * prefix = "__enc_"; 2774 char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1); 2775 sprintf(ec_name, "%s%s", prefix, inst._ident); 2776 2777 assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); 2778 EncClass *encoding = _AD._encode->add_EncClass(ec_name); 2779 encoding->_linenum = _linenum; 2780 2781 // synthesize the arguments list for the enc_class from the 2782 // arguments to the instruct definition. 2783 const char * param = NULL; 2784 inst._parameters.reset(); 2785 while ((param = inst._parameters.iter()) != NULL) { 2786 OperandForm *opForm = (OperandForm*)inst._localNames[param]; 2787 encoding->add_parameter(opForm->_ident, param); 2788 } 2789 2790 // Add the prologue to create the MacroAssembler 2791 encoding->add_code("\n" 2792 " // Define a MacroAssembler instance for use by the encoding. The\n" 2793 " // name is chosen to match the __ idiom used for assembly in other\n" 2794 " // parts of hotspot and assumes the existence of the standard\n" 2795 " // #define __ _masm.\n" 2796 " MacroAssembler _masm(&cbuf);\n"); 2797 2798 // Parse the following %{ }% block 2799 enc_class_parse_block(encoding, ec_name); 2800 2801 // Build an encoding rule which invokes the encoding rule we just 2802 // created, passing all arguments that we received. 2803 InsEncode *encrule = new InsEncode(); // Encode class for instruction 2804 NameAndList *params = encrule->add_encode(ec_name); 2805 inst._parameters.reset(); 2806 while ((param = inst._parameters.iter()) != NULL) { 2807 params->add_entry(param); 2808 } 2809 2810 return encrule; 2811} 2812 2813 2814//------------------------------ins_encode_parse------------------------------- 2815// Encode rules have the form 2816// ins_encode( encode_class_name(parameter_list), ... ); 2817// 2818// The "encode_class_name" must be defined in the encode section 2819// The parameter list contains $names that are locals. 2820// 2821// Alternatively it can be written like this: 2822// 2823// ins_encode %{ 2824// ... // body 2825// %} 2826// 2827// which synthesizes a new encoding class taking the same arguments as 2828// the InstructForm, and automatically prefixes the definition with: 2829// 2830// MacroAssembler masm(&cbuf);\n"); 2831// 2832// making it more compact to take advantage of the MacroAssembler and 2833// placing the assembly closer to it's use by instructions. 2834InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) { 2835 2836 // Parse encode class name 2837 skipws(); // Skip whitespace 2838 if (_curchar != '(') { 2839 // Check for ins_encode %{ form 2840 if ((_curchar == '%') && (*(_ptr+1) == '{')) { 2841 next_char(); // Skip '%' 2842 next_char(); // Skip '{' 2843 2844 // Parse the block form of ins_encode 2845 return ins_encode_parse_block(inst); 2846 } 2847 2848 parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n"); 2849 return NULL; 2850 } 2851 next_char(); // move past '(' 2852 skipws(); 2853 2854 InsEncode *encrule = new InsEncode(); // Encode class for instruction 2855 encrule->_linenum = _linenum; 2856 char *ec_name = NULL; // String representation of encode rule 2857 // identifier is optional. 2858 while (_curchar != ')') { 2859 ec_name = get_ident(); 2860 if (ec_name == NULL) { 2861 parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n"); 2862 return NULL; 2863 } 2864 // Check that encoding is defined in the encode section 2865 EncClass *encode_class = _AD._encode->encClass(ec_name); 2866 if (encode_class == NULL) { 2867 // Like to defer checking these till later... 2868 // parse_err(WARN, "Using an undefined encode class '%s' in 'ins_encode'.\n", ec_name); 2869 } 2870 2871 // Get list for encode method's parameters 2872 NameAndList *params = encrule->add_encode(ec_name); 2873 2874 // Parse the parameters to this encode method. 2875 skipws(); 2876 if ( _curchar == '(' ) { 2877 next_char(); // move past '(' for parameters 2878 2879 // Parse the encode method's parameters 2880 while (_curchar != ')') { 2881 char *param = get_ident_or_literal_constant("encoding operand"); 2882 if ( param != NULL ) { 2883 // Found a parameter: 2884 // Check it is a local name, add it to the list, then check for more 2885 // New: allow hex constants as parameters to an encode method. 2886 // New: allow parenthesized expressions as parameters. 2887 // New: allow "primary", "secondary", "tertiary" as parameters. 2888 // New: allow user-defined register name as parameter 2889 if ( (inst._localNames[param] == NULL) && 2890 !ADLParser::is_literal_constant(param) && 2891 (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) && 2892 ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) { 2893 parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name); 2894 return NULL; 2895 } 2896 params->add_entry(param); 2897 2898 skipws(); 2899 if (_curchar == ',' ) { 2900 // More parameters to come 2901 next_char(); // move past ',' between parameters 2902 skipws(); // Skip to next parameter 2903 } 2904 else if (_curchar == ')') { 2905 // Done with parameter list 2906 } 2907 else { 2908 // Only ',' or ')' are valid after a parameter name 2909 parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n", 2910 ec_name); 2911 return NULL; 2912 } 2913 2914 } else { 2915 skipws(); 2916 // Did not find a parameter 2917 if (_curchar == ',') { 2918 parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name); 2919 return NULL; 2920 } 2921 if (_curchar != ')') { 2922 parse_err(SYNERR, "Expected ')' after encode parameters.\n"); 2923 return NULL; 2924 } 2925 } 2926 } // WHILE loop collecting parameters 2927 next_char(); // move past ')' at end of parameters 2928 } // done with parameter list for encoding 2929 2930 // Check for ',' or ')' after encoding 2931 skipws(); // move to character after parameters 2932 if ( _curchar == ',' ) { 2933 // Found a ',' 2934 next_char(); // move past ',' between encode methods 2935 skipws(); 2936 } 2937 else if ( _curchar != ')' ) { 2938 // If not a ',' then only a ')' is allowed 2939 parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name); 2940 return NULL; 2941 } 2942 2943 // Check for ',' separating parameters 2944 // if ( _curchar != ',' && _curchar != ')' ) { 2945 // parse_err(SYNERR, "expected ',' or ')' after encode method inside ins_encode.\n"); 2946 // return NULL; 2947 // } 2948 2949 } // done parsing ins_encode methods and their parameters 2950 if (_curchar != ')') { 2951 parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n"); 2952 return NULL; 2953 } 2954 next_char(); // move past ')' 2955 skipws(); // Skip leading whitespace 2956 2957 if ( _curchar != ';' ) { 2958 parse_err(SYNERR, "Missing ';' at end of ins_encode.\n"); 2959 return NULL; 2960 } 2961 next_char(); // move past ';' 2962 skipws(); // be friendly to oper_parse() 2963 2964 // Debug Stuff 2965 if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name); 2966 2967 return encrule; 2968} 2969 2970 2971//------------------------------size_parse----------------------------------- 2972char* ADLParser::size_parse(InstructForm *instr) { 2973 char* sizeOfInstr = NULL; 2974 2975 // Get value of the instruction's size 2976 skipws(); 2977 2978 // Parse size 2979 sizeOfInstr = get_paren_expr("size expression"); 2980 if (sizeOfInstr == NULL) { 2981 parse_err(SYNERR, "size of opcode expected at %c\n", _curchar); 2982 return NULL; 2983 } 2984 2985 skipws(); 2986 2987 // Check for terminator 2988 if (_curchar != ';') { 2989 parse_err(SYNERR, "missing ';' in ins_attrib definition\n"); 2990 return NULL; 2991 } 2992 next_char(); // Advance past the ';' 2993 skipws(); // necessary for instr_parse() 2994 2995 // Debug Stuff 2996 if (_AD._adl_debug > 1) { 2997 if (sizeOfInstr != NULL) { 2998 fprintf(stderr,"size of opcode: %s\n", sizeOfInstr); 2999 } 3000 } 3001 3002 return sizeOfInstr; 3003} 3004 3005 3006//------------------------------opcode_parse----------------------------------- 3007Opcode * ADLParser::opcode_parse(InstructForm *instr) { 3008 char *primary = NULL; 3009 char *secondary = NULL; 3010 char *tertiary = NULL; 3011 3012 char *val = NULL; 3013 Opcode *opcode = NULL; 3014 3015 // Get value of the instruction's opcode 3016 skipws(); 3017 if (_curchar != '(') { // Check for parenthesized operand list 3018 parse_err(SYNERR, "missing '(' in expand instruction declaration\n"); 3019 return NULL; 3020 } 3021 next_char(); // skip open paren 3022 skipws(); 3023 if (_curchar != ')') { 3024 // Parse primary, secondary, and tertiary opcodes, if provided. 3025 if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) { 3026 parse_err(SYNERR, "primary hex opcode expected at %c\n", _curchar); 3027 return NULL; 3028 } 3029 skipws(); 3030 if (_curchar == ',') { 3031 next_char(); 3032 skipws(); 3033 // Parse secondary opcode 3034 if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) { 3035 parse_err(SYNERR, "secondary hex opcode expected at %c\n", _curchar); 3036 return NULL; 3037 } 3038 skipws(); 3039 if (_curchar == ',') { 3040 next_char(); 3041 skipws(); 3042 // Parse tertiary opcode 3043 if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) { 3044 parse_err(SYNERR,"tertiary hex opcode expected at %c\n", _curchar); 3045 return NULL; 3046 } 3047 skipws(); 3048 } 3049 } 3050 skipws(); 3051 if (_curchar != ')') { 3052 parse_err(SYNERR, "Missing ')' in opcode description\n"); 3053 return NULL; 3054 } 3055 } 3056 next_char(); // Skip ')' 3057 skipws(); 3058 // Check for terminator 3059 if (_curchar != ';') { 3060 parse_err(SYNERR, "missing ';' in ins_attrib definition\n"); 3061 return NULL; 3062 } 3063 next_char(); // Advance past the ';' 3064 skipws(); // necessary for instr_parse() 3065 3066 // Debug Stuff 3067 if (_AD._adl_debug > 1) { 3068 if (primary != NULL) fprintf(stderr,"primary opcode: %s\n", primary); 3069 if (secondary != NULL) fprintf(stderr,"secondary opcode: %s\n", secondary); 3070 if (tertiary != NULL) fprintf(stderr,"tertiary opcode: %s\n", tertiary); 3071 } 3072 3073 // Generate new object and return 3074 opcode = new Opcode(primary, secondary, tertiary); 3075 return opcode; 3076} 3077 3078 3079//------------------------------interface_parse-------------------------------- 3080Interface *ADLParser::interface_parse(void) { 3081 char *iface_name = NULL; // Name of interface class being used 3082 char *iface_code = NULL; // Describe components of this class 3083 3084 // Get interface class name 3085 skipws(); // Skip whitespace 3086 if (_curchar != '(') { 3087 parse_err(SYNERR, "Missing '(' at start of interface description.\n"); 3088 return NULL; 3089 } 3090 next_char(); // move past '(' 3091 skipws(); 3092 iface_name = get_ident(); 3093 if (iface_name == NULL) { 3094 parse_err(SYNERR, "missing interface name after 'interface'.\n"); 3095 return NULL; 3096 } 3097 skipws(); 3098 if (_curchar != ')') { 3099 parse_err(SYNERR, "Missing ')' after name of interface.\n"); 3100 return NULL; 3101 } 3102 next_char(); // move past ')' 3103 3104 // Get details of the interface, 3105 // for the type of interface indicated by iface_name. 3106 Interface *inter = NULL; 3107 skipws(); 3108 if ( _curchar != ';' ) { 3109 if ( strcmp(iface_name,"MEMORY_INTER") == 0 ) { 3110 inter = mem_interface_parse(); 3111 } 3112 else if ( strcmp(iface_name,"COND_INTER") == 0 ) { 3113 inter = cond_interface_parse(); 3114 } 3115 // The parse routines consume the "%}" 3116 3117 // Check for probable extra ';' after defining block. 3118 if ( _curchar == ';' ) { 3119 parse_err(SYNERR, "Extra ';' after defining interface block.\n"); 3120 next_char(); // Skip ';' 3121 return NULL; 3122 } 3123 } else { 3124 next_char(); // move past ';' 3125 3126 // Create appropriate interface object 3127 if ( strcmp(iface_name,"REG_INTER") == 0 ) { 3128 inter = new RegInterface(); 3129 } 3130 else if ( strcmp(iface_name,"CONST_INTER") == 0 ) { 3131 inter = new ConstInterface(); 3132 } 3133 } 3134 skipws(); // be friendly to oper_parse() 3135 // Debug Stuff 3136 if (_AD._adl_debug > 1) fprintf(stderr,"Interface Form: %s\n", iface_name); 3137 3138 // Create appropriate interface object and return. 3139 return inter; 3140} 3141 3142 3143//------------------------------mem_interface_parse---------------------------- 3144Interface *ADLParser::mem_interface_parse(void) { 3145 // Fields for MemInterface 3146 char *base = NULL; 3147 char *index = NULL; 3148 char *scale = NULL; 3149 char *disp = NULL; 3150 3151 if (_curchar != '%') { 3152 parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); 3153 return NULL; 3154 } 3155 next_char(); // Skip '%' 3156 if (_curchar != '{') { 3157 parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); 3158 return NULL; 3159 } 3160 next_char(); // Skip '{' 3161 skipws(); 3162 do { 3163 char *field = get_ident(); 3164 if (field == NULL) { 3165 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3166 return NULL; 3167 } 3168 if ( strcmp(field,"base") == 0 ) { 3169 base = interface_field_parse(); 3170 } 3171 else if ( strcmp(field,"index") == 0 ) { 3172 index = interface_field_parse(); 3173 } 3174 else if ( strcmp(field,"scale") == 0 ) { 3175 scale = interface_field_parse(); 3176 } 3177 else if ( strcmp(field,"disp") == 0 ) { 3178 disp = interface_field_parse(); 3179 } 3180 else { 3181 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3182 return NULL; 3183 } 3184 } while( _curchar != '%' ); 3185 next_char(); // Skip '%' 3186 if ( _curchar != '}' ) { 3187 parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); 3188 return NULL; 3189 } 3190 next_char(); // Skip '}' 3191 3192 // Construct desired object and return 3193 Interface *inter = new MemInterface(base, index, scale, disp); 3194 return inter; 3195} 3196 3197 3198//------------------------------cond_interface_parse--------------------------- 3199Interface *ADLParser::cond_interface_parse(void) { 3200 char *equal; 3201 char *not_equal; 3202 char *less; 3203 char *greater_equal; 3204 char *less_equal; 3205 char *greater; 3206 3207 if (_curchar != '%') { 3208 parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); 3209 return NULL; 3210 } 3211 next_char(); // Skip '%' 3212 if (_curchar != '{') { 3213 parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); 3214 return NULL; 3215 } 3216 next_char(); // Skip '{' 3217 skipws(); 3218 do { 3219 char *field = get_ident(); 3220 if (field == NULL) { 3221 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3222 return NULL; 3223 } 3224 if ( strcmp(field,"equal") == 0 ) { 3225 equal = interface_field_parse(); 3226 } 3227 else if ( strcmp(field,"not_equal") == 0 ) { 3228 not_equal = interface_field_parse(); 3229 } 3230 else if ( strcmp(field,"less") == 0 ) { 3231 less = interface_field_parse(); 3232 } 3233 else if ( strcmp(field,"greater_equal") == 0 ) { 3234 greater_equal = interface_field_parse(); 3235 } 3236 else if ( strcmp(field,"less_equal") == 0 ) { 3237 less_equal = interface_field_parse(); 3238 } 3239 else if ( strcmp(field,"greater") == 0 ) { 3240 greater = interface_field_parse(); 3241 } 3242 else { 3243 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3244 return NULL; 3245 } 3246 } while( _curchar != '%' ); 3247 next_char(); // Skip '%' 3248 if ( _curchar != '}' ) { 3249 parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); 3250 return NULL; 3251 } 3252 next_char(); // Skip '}' 3253 3254 // Construct desired object and return 3255 Interface *inter = new CondInterface(equal, not_equal, less, greater_equal, 3256 less_equal, greater); 3257 return inter; 3258} 3259 3260 3261//------------------------------interface_field_parse-------------------------- 3262char *ADLParser::interface_field_parse(void) { 3263 char *iface_field = NULL; 3264 3265 // Get interface field 3266 skipws(); // Skip whitespace 3267 if (_curchar != '(') { 3268 parse_err(SYNERR, "Missing '(' at start of interface field.\n"); 3269 return NULL; 3270 } 3271 next_char(); // move past '(' 3272 skipws(); 3273 if ( _curchar != '0' && _curchar != '$' ) { 3274 parse_err(SYNERR, "missing or invalid interface field contents.\n"); 3275 return NULL; 3276 } 3277 iface_field = get_rep_var_ident(); 3278 if (iface_field == NULL) { 3279 parse_err(SYNERR, "missing or invalid interface field contents.\n"); 3280 return NULL; 3281 } 3282 skipws(); 3283 if (_curchar != ')') { 3284 parse_err(SYNERR, "Missing ')' after interface field.\n"); 3285 return NULL; 3286 } 3287 next_char(); // move past ')' 3288 skipws(); 3289 if ( _curchar != ';' ) { 3290 parse_err(SYNERR, "Missing ';' at end of interface field.\n"); 3291 return NULL; 3292 } 3293 next_char(); // move past ';' 3294 skipws(); // be friendly to interface_parse() 3295 3296 return iface_field; 3297} 3298 3299 3300//------------------------------match_parse------------------------------------ 3301MatchRule *ADLParser::match_parse(FormDict &operands) { 3302 MatchRule *match; // Match Rule class for instruction/operand 3303 char *cnstr = NULL; // Code for constructor 3304 int depth = 0; // Counter for matching parentheses 3305 int numleaves = 0; // Counter for number of leaves in rule 3306 3307 // Parse the match rule tree 3308 MatchNode *mnode = matchNode_parse(operands, depth, numleaves, true); 3309 3310 // Either there is a block with a constructor, or a ';' here 3311 skipws(); // Skip whitespace 3312 if ( _curchar == ';' ) { // Semicolon is valid terminator 3313 cnstr = NULL; // no constructor for this form 3314 next_char(); // Move past the ';', replaced with '\0' 3315 } 3316 else if ((cnstr = find_cpp_block("match constructor")) == NULL ) { 3317 parse_err(SYNERR, "invalid construction of match rule\n" 3318 "Missing ';' or invalid '%{' and '%}' constructor\n"); 3319 return NULL; // No MatchRule to return 3320 } 3321 if (_AD._adl_debug > 1) 3322 if (cnstr) fprintf(stderr,"Match Constructor: %s\n", cnstr); 3323 // Build new MatchRule object 3324 match = new MatchRule(_AD, mnode, depth, cnstr, numleaves); 3325 skipws(); // Skip any trailing whitespace 3326 return match; // Return MatchRule object 3327} 3328 3329//------------------------------format_parse----------------------------------- 3330FormatRule* ADLParser::format_parse(void) { 3331 char *desc = NULL; 3332 FormatRule *format = (new FormatRule(desc)); 3333 3334 // Without expression form, MUST have a code block; 3335 skipws(); // Skip whitespace 3336 if ( _curchar == ';' ) { // Semicolon is valid terminator 3337 desc = NULL; // no constructor for this form 3338 next_char(); // Move past the ';', replaced with '\0' 3339 } 3340 else if ( _curchar == '%' && *(_ptr+1) == '{') { 3341 next_char(); // Move past the '%' 3342 next_char(); // Move past the '{' 3343 3344 skipws(); 3345 // Check for the opening '"' inside the format description 3346 if ( _curchar == '"' ) { 3347 next_char(); // Move past the initial '"' 3348 if( _curchar == '"' ) { // Handle empty format string case 3349 *_ptr = '\0'; // Terminate empty string 3350 format->_strings.addName(_ptr); 3351 } 3352 3353 // Collect the parts of the format description 3354 // (1) strings that are passed through to tty->print 3355 // (2) replacement/substitution variable, preceeded by a '$' 3356 // (3) multi-token ANSIY C style strings 3357 while ( true ) { 3358 if ( _curchar == '%' || _curchar == '\n' ) { 3359 if ( _curchar != '"' ) { 3360 parse_err(SYNERR, "missing '\"' at end of format block"); 3361 return NULL; 3362 } 3363 } 3364 3365 // (1) 3366 // Check if there is a string to pass through to output 3367 char *start = _ptr; // Record start of the next string 3368 while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) { 3369 if (_curchar == '\\') next_char(); // superquote 3370 if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! 3371 next_char(); 3372 } 3373 // If a string was found, terminate it and record in FormatRule 3374 if ( start != _ptr ) { 3375 *_ptr = '\0'; // Terminate the string 3376 format->_strings.addName(start); 3377 } 3378 3379 // (2) 3380 // If we are at a replacement variable, 3381 // copy it and record in FormatRule 3382 if ( _curchar == '$' ) { 3383 next_char(); // Move past the '$' 3384 char* rep_var = get_ident(); // Nil terminate the variable name 3385 rep_var = strdup(rep_var);// Copy the string 3386 *_ptr = _curchar; // and replace Nil with original character 3387 format->_rep_vars.addName(rep_var); 3388 // Add flag to _strings list indicating we should check _rep_vars 3389 format->_strings.addName(NameList::_signal); 3390 } 3391 3392 // (3) 3393 // Allow very long strings to be broken up, 3394 // using the ANSI C syntax "foo\n" <newline> "bar" 3395 if ( _curchar == '"') { 3396 next_char(); // Move past the '"' 3397 skipws(); // Skip white space before next string token 3398 if ( _curchar != '"') { 3399 break; 3400 } else { 3401 // Found one. Skip both " and the whitespace in between. 3402 next_char(); 3403 } 3404 } 3405 } // end while part of format description 3406 3407 // Check for closing '"' and '%}' in format description 3408 skipws(); // Move to closing '%}' 3409 if ( _curchar != '%' ) { 3410 parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format"); 3411 return NULL; 3412 } 3413 } // Done with format description inside 3414 3415 skipws(); 3416 // Past format description, at '%' 3417 if ( _curchar != '%' || *(_ptr+1) != '}' ) { 3418 parse_err(SYNERR, "missing '%}' at end of format block"); 3419 return NULL; 3420 } 3421 next_char(); // Move past the '%' 3422 next_char(); // Move past the '}' 3423 } 3424 else { // parameter list alone must terminate with a ';' 3425 parse_err(SYNERR, "missing ';' after Format expression"); 3426 return NULL; 3427 } 3428 // Debug Stuff 3429 if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc); 3430 3431 skipws(); 3432 return format; 3433} 3434 3435 3436//------------------------------effect_parse----------------------------------- 3437void ADLParser::effect_parse(InstructForm *instr) { 3438 char* desc = NULL; 3439 3440 skipws(); // Skip whitespace 3441 if (_curchar != '(') { 3442 parse_err(SYNERR, "missing '(' in effect definition\n"); 3443 return; 3444 } 3445 // Get list of effect-operand pairs and insert into dictionary 3446 else get_effectlist(instr->_effects, instr->_localNames); 3447 3448 // Debug Stuff 3449 if (_AD._adl_debug > 1) fprintf(stderr,"Effect description: %s\n", desc); 3450 if (_curchar != ';') { 3451 parse_err(SYNERR, "missing ';' in Effect definition\n"); 3452 } 3453 next_char(); // Skip ';' 3454 3455} 3456 3457//------------------------------expand_parse----------------------------------- 3458ExpandRule* ADLParser::expand_parse(InstructForm *instr) { 3459 char *ident, *ident2; 3460 OperandForm *oper; 3461 InstructForm *ins; 3462 NameAndList *instr_and_operands = NULL; 3463 ExpandRule *exp = new ExpandRule(); 3464 3465 // Expand is a block containing an ordered list of instructions, each of 3466 // which has an ordered list of operands. 3467 // Check for block delimiter 3468 skipws(); // Skip leading whitespace 3469 if ((_curchar != '%') 3470 || (next_char(), (_curchar != '{')) ) { // If not open block 3471 parse_err(SYNERR, "missing '%{' in expand definition\n"); 3472 return(NULL); 3473 } 3474 next_char(); // Maintain the invariant 3475 do { 3476 ident = get_ident(); // Grab next identifier 3477 if (ident == NULL) { 3478 parse_err(SYNERR, "identifier expected at %c\n", _curchar); 3479 continue; 3480 } // Check that you have a valid instruction 3481 const Form *form = _globalNames[ident]; 3482 ins = form ? form->is_instruction() : NULL; 3483 if (ins == NULL) { 3484 // This is a new operand 3485 oper = form ? form->is_operand() : NULL; 3486 if (oper == NULL) { 3487 parse_err(SYNERR, "instruction/operand name expected at %s\n", ident); 3488 continue; 3489 } 3490 // Throw the operand on the _newopers list 3491 skipws(); 3492 ident = get_unique_ident(instr->_localNames,"Operand"); 3493 if (ident == NULL) { 3494 parse_err(SYNERR, "identifier expected at %c\n", _curchar); 3495 continue; 3496 } 3497 exp->_newopers.addName(ident); 3498 // Add new operand to LocalNames 3499 instr->_localNames.Insert(ident, oper); 3500 // Grab any constructor code and save as a string 3501 char *c = NULL; 3502 skipws(); 3503 if (_curchar == '%') { // Need a constructor for the operand 3504 c = find_cpp_block("Operand Constructor"); 3505 if (c == NULL) { 3506 parse_err(SYNERR, "Invalid code block for operand constructor\n", _curchar); 3507 continue; 3508 } 3509 // Add constructor to _newopconst Dict 3510 exp->_newopconst.Insert(ident, c); 3511 } 3512 else if (_curchar != ';') { // If no constructor, need a ; 3513 parse_err(SYNERR, "Missing ; in expand rule operand declaration\n"); 3514 continue; 3515 } 3516 else next_char(); // Skip the ; 3517 skipws(); 3518 } 3519 else { 3520 // Add instruction to list 3521 instr_and_operands = new NameAndList(ident); 3522 // Grab operands, build nameList of them, and then put into dictionary 3523 skipws(); 3524 if (_curchar != '(') { // Check for parenthesized operand list 3525 parse_err(SYNERR, "missing '(' in expand instruction declaration\n"); 3526 continue; 3527 } 3528 do { 3529 next_char(); // skip open paren & comma characters 3530 skipws(); 3531 if (_curchar == ')') break; 3532 ident2 = get_ident(); 3533 skipws(); 3534 if (ident2 == NULL) { 3535 parse_err(SYNERR, "identifier expected at %c\n", _curchar); 3536 continue; 3537 } // Check that you have a valid operand 3538 const Form *form = instr->_localNames[ident2]; 3539 if (!form) { 3540 parse_err(SYNERR, "operand name expected at %s\n", ident2); 3541 continue; 3542 } 3543 oper = form->is_operand(); 3544 if (oper == NULL && !form->is_opclass()) { 3545 parse_err(SYNERR, "operand name expected at %s\n", ident2); 3546 continue; 3547 } // Add operand to list 3548 instr_and_operands->add_entry(ident2); 3549 } while(_curchar == ','); 3550 if (_curchar != ')') { 3551 parse_err(SYNERR, "missing ')'in expand instruction declaration\n"); 3552 continue; 3553 } 3554 next_char(); 3555 if (_curchar != ';') { 3556 parse_err(SYNERR, "missing ';'in expand instruction declaration\n"); 3557 continue; 3558 } 3559 next_char(); 3560 3561 // Record both instruction name and its operand list 3562 exp->add_instruction(instr_and_operands); 3563 3564 skipws(); 3565 } 3566 3567 } while(_curchar != '%'); 3568 next_char(); 3569 if (_curchar != '}') { 3570 parse_err(SYNERR, "missing '%}' in expand rule definition\n"); 3571 return(NULL); 3572 } 3573 next_char(); 3574 3575 // Debug Stuff 3576 if (_AD._adl_debug > 1) fprintf(stderr,"Expand Rule:\n"); 3577 3578 skipws(); 3579 return (exp); 3580} 3581 3582//------------------------------rewrite_parse---------------------------------- 3583RewriteRule* ADLParser::rewrite_parse(void) { 3584 char* params = NULL; 3585 char* desc = NULL; 3586 3587 3588 // This feature targeted for second generation description language. 3589 3590 skipws(); // Skip whitespace 3591 // Get parameters for rewrite 3592 if ((params = get_paren_expr("rewrite parameters")) == NULL) { 3593 parse_err(SYNERR, "missing '(' in rewrite rule\n"); 3594 return NULL; 3595 } 3596 // Debug Stuff 3597 if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite parameters: %s\n", params); 3598 3599 // For now, grab entire block; 3600 skipws(); 3601 if ( (desc = find_cpp_block("rewrite block")) == NULL ) { 3602 parse_err(SYNERR, "incorrect or missing block for 'rewrite'.\n"); 3603 return NULL; 3604 } 3605 // Debug Stuff 3606 if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite Rule: %s\n", desc); 3607 3608 skipws(); 3609 return (new RewriteRule(params,desc)); 3610} 3611 3612//------------------------------attr_parse------------------------------------- 3613Attribute *ADLParser::attr_parse(char* ident) { 3614 Attribute *attrib; // Attribute class 3615 char *cost = NULL; // String representation of cost attribute 3616 3617 skipws(); // Skip leading whitespace 3618 if ( (cost = get_paren_expr("attribute")) == NULL ) { 3619 parse_err(SYNERR, "incorrect or missing expression for 'attribute'\n"); 3620 return NULL; 3621 } 3622 // Debug Stuff 3623 if (_AD._adl_debug > 1) fprintf(stderr,"Attribute: %s\n", cost); 3624 if (_curchar != ';') { 3625 parse_err(SYNERR, "missing ';' in attribute definition\n"); 3626 return NULL; 3627 } 3628 next_char(); // Point after the terminator 3629 3630 skipws(); 3631 attrib = new Attribute(ident,cost,INS_ATTR); // Build new predicate object 3632 return attrib; 3633} 3634 3635 3636//------------------------------matchNode_parse-------------------------------- 3637MatchNode *ADLParser::matchNode_parse(FormDict &operands, int &depth, int &numleaves, bool atroot) { 3638 // Count depth of parenthesis nesting for both left and right children 3639 int lParens = depth; 3640 int rParens = depth; 3641 3642 // MatchNode objects for left, right, and root of subtree. 3643 MatchNode *lChild = NULL; 3644 MatchNode *rChild = NULL; 3645 char *token; // Identifier which may be opcode or operand 3646 3647 // Match expression starts with a '(' 3648 if (cur_char() != '(') 3649 return NULL; 3650 3651 next_char(); // advance past '(' 3652 3653 // Parse the opcode 3654 token = get_ident(); // Get identifier, opcode 3655 if (token == NULL) { 3656 parse_err(SYNERR, "missing opcode in match expression\n"); 3657 return NULL; 3658 } 3659 3660 // Take note if we see one of a few special operations - those that are 3661 // treated differently on different architectures in the sense that on 3662 // one architecture there is a match rule and on another there isn't (so 3663 // a call will eventually be generated). 3664 3665 for (int i = _last_machine_leaf + 1; i < _last_opcode; i++) { 3666 if (strcmp(token, NodeClassNames[i]) == 0) { 3667 _AD.has_match_rule(i, true); 3668 } 3669 } 3670 3671 // Lookup the root value in the operands dict to perform substitution 3672 const char *result = NULL; // Result type will be filled in later 3673 const char *name = token; // local name associated with this node 3674 const char *operation = token; // remember valid operation for later 3675 const Form *form = operands[token]; 3676 OpClassForm *opcForm = form ? form->is_opclass() : NULL; 3677 if (opcForm != NULL) { 3678 // If this token is an entry in the local names table, record its type 3679 if (!opcForm->ideal_only()) { 3680 operation = opcForm->_ident; 3681 result = operation; // Operands result in their own type 3682 } 3683 // Otherwise it is an ideal type, and so, has no local name 3684 else name = NULL; 3685 } 3686 3687 // Parse the operands 3688 skipws(); 3689 if (cur_char() != ')') { 3690 3691 // Parse the left child 3692 if (strcmp(operation,"Set")) 3693 lChild = matchChild_parse(operands, lParens, numleaves, false); 3694 else 3695 lChild = matchChild_parse(operands, lParens, numleaves, true); 3696 3697 skipws(); 3698 if (cur_char() != ')' ) { 3699 if(strcmp(operation, "Set")) 3700 rChild = matchChild_parse(operands,rParens,numleaves,false); 3701 else 3702 rChild = matchChild_parse(operands,rParens,numleaves,true); 3703 } 3704 } 3705 3706 // Check for required ')' 3707 skipws(); 3708 if (cur_char() != ')') { 3709 parse_err(SYNERR, "missing ')' in match expression\n"); 3710 return NULL; 3711 } 3712 next_char(); // skip the ')' 3713 3714 MatchNode* mroot = new MatchNode(_AD,result,name,operation,lChild,rChild); 3715 3716 // If not the root, reduce this subtree to an internal operand 3717 if (!atroot) { 3718 mroot->build_internalop(); 3719 } 3720 // depth is greater of left and right paths. 3721 depth = (lParens > rParens) ? lParens : rParens; 3722 3723 return mroot; 3724} 3725 3726 3727//------------------------------matchChild_parse------------------------------- 3728MatchNode *ADLParser::matchChild_parse(FormDict &operands, int &parens, int &numleaves, bool atroot) { 3729 MatchNode *child = NULL; 3730 const char *result = NULL; 3731 const char *token = NULL; 3732 const char *opType = NULL; 3733 3734 if (cur_char() == '(') { // child is an operation 3735 ++parens; 3736 child = matchNode_parse(operands, parens, numleaves, atroot); 3737 } 3738 else { // child is an operand 3739 token = get_ident(); 3740 const Form *form = operands[token]; 3741 OpClassForm *opcForm = form ? form->is_opclass() : NULL; 3742 if (opcForm != NULL) { 3743 opType = opcForm->_ident; 3744 result = opcForm->_ident; // an operand's result matches its type 3745 } else { 3746 parse_err(SYNERR, "undefined operand %s in match rule\n", token); 3747 return NULL; 3748 } 3749 3750 if (opType == NULL) { 3751 parse_err(SYNERR, "missing type for argument '%s'\n", token); 3752 } 3753 3754 child = new MatchNode(_AD, result, token, opType); 3755 ++numleaves; 3756 } 3757 3758 return child; 3759} 3760 3761 3762 3763// ******************** Private Utility Functions ************************* 3764 3765 3766char* ADLParser::find_cpp_block(const char* description) { 3767 char *next; // Pointer for finding block delimiters 3768 char* cppBlock = NULL; // Beginning of C++ code block 3769 3770 if (_curchar == '%') { // Encoding is a C++ expression 3771 next_char(); 3772 if (_curchar != '{') { 3773 parse_err(SYNERR, "missing '{' in %s \n", description); 3774 return NULL; 3775 } 3776 next_char(); // Skip block delimiter 3777 skipws_no_preproc(); // Skip leading whitespace 3778 cppBlock = _ptr; // Point to start of expression 3779 const char* file = _AD._ADL_file._name; 3780 int line = _linenum; 3781 next = _ptr + 1; 3782 while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) { 3783 next_char_or_line(); 3784 next = _ptr+1; // Maintain the next pointer 3785 } // Grab string 3786 if (_curchar == '\0') { 3787 parse_err(SYNERR, "invalid termination of %s \n", description); 3788 return NULL; 3789 } 3790 *_ptr = '\0'; // Terminate string 3791 _ptr += 2; // Skip block delimiter 3792 _curchar = *_ptr; // Maintain invariant 3793 3794 // Prepend location descriptor, for debugging. 3795 char* location = (char *)malloc(strlen(file) + 100); 3796 *location = '\0'; 3797 if (_AD._adlocation_debug) 3798 sprintf(location, "#line %d \"%s\"\n", line, file); 3799 char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1); 3800 strcpy(result, location); 3801 strcat(result, cppBlock); 3802 cppBlock = result; 3803 free(location); 3804 } 3805 3806 return cppBlock; 3807} 3808 3809// Move to the closing token of the expression we are currently at, 3810// as defined by stop_chars. Match parens and quotes. 3811char* ADLParser::get_expr(const char *desc, const char *stop_chars) { 3812 char* expr = NULL; 3813 int paren = 0; 3814 3815 expr = _ptr; 3816 while (paren > 0 || !strchr(stop_chars, _curchar)) { 3817 if (_curchar == '(') { // Down level of nesting 3818 paren++; // Bump the parenthesis counter 3819 next_char(); // maintain the invariant 3820 } 3821 else if (_curchar == ')') { // Up one level of nesting 3822 if (paren == 0) { 3823 // Paren underflow: We didn't encounter the required stop-char. 3824 parse_err(SYNERR, "too many )'s, did not find %s after %s\n", 3825 stop_chars, desc); 3826 return NULL; 3827 } 3828 paren--; // Drop the parenthesis counter 3829 next_char(); // Maintain the invariant 3830 } 3831 else if (_curchar == '"' || _curchar == '\'') { 3832 int qchar = _curchar; 3833 while (true) { 3834 next_char(); 3835 if (_curchar == qchar) { next_char(); break; } 3836 if (_curchar == '\\') next_char(); // superquote 3837 if (_curchar == '\n' || _curchar == '\0') { 3838 parse_err(SYNERR, "newline in string in %s\n", desc); 3839 return NULL; 3840 } 3841 } 3842 } 3843 else if (_curchar == '%' && (_ptr[1] == '{' || _ptr[1] == '}')) { 3844 // Make sure we do not stray into the next ADLC-level form. 3845 parse_err(SYNERR, "unexpected %%%c in %s\n", _ptr[1], desc); 3846 return NULL; 3847 } 3848 else if (_curchar == '\0') { 3849 parse_err(SYNERR, "unexpected EOF in %s\n", desc); 3850 return NULL; 3851 } 3852 else { 3853 // Always walk over whitespace, comments, preprocessor directives, etc. 3854 char* pre_skip_ptr = _ptr; 3855 skipws(); 3856 // If the parser declined to make progress on whitespace, 3857 // skip the next character, which is therefore NOT whitespace. 3858 if (pre_skip_ptr == _ptr) { 3859 next_char(); 3860 } else if (pre_skip_ptr+strlen(pre_skip_ptr) != _ptr+strlen(_ptr)) { 3861 parse_err(SYNERR, "unimplemented: preprocessor must not elide subexpression in %s", desc); 3862 } 3863 } 3864 } 3865 3866 assert(strchr(stop_chars, _curchar), "non-null return must be at stop-char"); 3867 *_ptr = '\0'; // Replace ')' or other stop-char with '\0' 3868 return expr; 3869} 3870 3871// Helper function around get_expr 3872// Sets _curchar to '(' so that get_paren_expr will search for a matching ')' 3873char *ADLParser::get_paren_expr(const char *description) { 3874 if (_curchar != '(') // Escape if not valid starting position 3875 return NULL; 3876 next_char(); // Skip the required initial paren. 3877 char *token2 = get_expr(description, ")"); 3878 if (_curchar == ')') 3879 next_char(); // Skip required final paren. 3880 return token2; 3881} 3882 3883//------------------------------get_ident_common------------------------------- 3884// Looks for an identifier in the buffer, and turns it into a null terminated 3885// string(still inside the file buffer). Returns a pointer to the string or 3886// NULL if some other token is found instead. 3887char *ADLParser::get_ident_common(bool do_preproc) { 3888 register char c; 3889 char *start; // Pointer to start of token 3890 char *end; // Pointer to end of token 3891 3892 if( _curline == NULL ) // Return NULL at EOF. 3893 return NULL; 3894 3895 skipws_common(do_preproc); // Skip whitespace before identifier 3896 start = end = _ptr; // Start points at first character 3897 end--; // unwind end by one to prepare for loop 3898 do { 3899 end++; // Increment end pointer 3900 c = *end; // Grab character to test 3901 } while ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) 3902 || ((c >= '0') && (c <= '9')) 3903 || ((c == '_')) || ((c == ':')) || ((c == '#')) ); 3904 if (start == end) { // We popped out on the first try 3905 parse_err(SYNERR, "identifier expected at %c\n", c); 3906 start = NULL; 3907 } 3908 else { 3909 _curchar = c; // Save the first character of next token 3910 *end = '\0'; // NULL terminate the string in place 3911 } 3912 _ptr = end; // Reset _ptr to point to next char after token 3913 3914 // Make sure we do not try to use #defined identifiers. If start is 3915 // NULL an error was already reported. 3916 if (do_preproc && start != NULL) { 3917 const char* def = _AD.get_preproc_def(start); 3918 if (def != NULL && strcmp(def, start)) { 3919 const char* def2 = _AD.get_preproc_def(def); 3920 if (def2 != NULL && strcmp(def2, def)) { 3921 parse_err(SYNERR, "unimplemented: using %s defined as %s => %s", 3922 start, def, def2); 3923 } 3924 start = strdup(def); 3925 } 3926 } 3927 3928 return start; // Pointer to token in filebuf 3929} 3930 3931//------------------------------get_ident_dup---------------------------------- 3932// Looks for an identifier in the buffer, and returns a duplicate 3933// or NULL if some other token is found instead. 3934char *ADLParser::get_ident_dup(void) { 3935 char *ident = get_ident(); 3936 3937 // Duplicate an identifier before returning and restore string. 3938 if( ident != NULL ) { 3939 ident = strdup(ident); // Copy the string 3940 *_ptr = _curchar; // and replace Nil with original character 3941 } 3942 3943 return ident; 3944} 3945 3946//----------------------get_ident_or_literal_constant-------------------------- 3947// Looks for an identifier in the buffer, or a parenthesized expression. 3948char *ADLParser::get_ident_or_literal_constant(const char* description) { 3949 char* param = NULL; 3950 skipws(); 3951 if (_curchar == '(') { 3952 // Grab a constant expression. 3953 param = get_paren_expr(description); 3954 if (param[0] != '(') { 3955 char* buf = (char*) malloc(strlen(param) + 3); 3956 sprintf(buf, "(%s)", param); 3957 param = buf; 3958 } 3959 assert(is_literal_constant(param), 3960 "expr must be recognizable as a constant"); 3961 } else { 3962 param = get_ident(); 3963 } 3964 return param; 3965} 3966 3967//------------------------------get_rep_var_ident----------------------------- 3968// Do NOT duplicate, 3969// Leave nil terminator in buffer 3970// Preserve initial '$'(s) in string 3971char *ADLParser::get_rep_var_ident(void) { 3972 // Remember starting point 3973 char *rep_var = _ptr; 3974 3975 // Check for replacement variable indicator '$' and pass if present 3976 if ( _curchar == '$' ) { 3977 next_char(); 3978 } 3979 // Check for a subfield indicator, a second '$', and pass if present 3980 if ( _curchar == '$' ) { 3981 next_char(); 3982 } 3983 3984 // Check for a control indicator, a third '$': 3985 if ( _curchar == '$' ) { 3986 next_char(); 3987 } 3988 3989 // Check for more than three '$'s in sequence, SYNERR 3990 if( _curchar == '$' ) { 3991 parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'"); 3992 next_char(); 3993 return NULL; 3994 } 3995 3996 // Nil terminate the variable name following the '$' 3997 char *rep_var_name = get_ident(); 3998 assert( rep_var_name != NULL, 3999 "Missing identifier after replacement variable indicator '$'"); 4000 4001 return rep_var; 4002} 4003 4004 4005 4006//------------------------------get_rep_var_ident_dup------------------------- 4007// Return the next replacement variable identifier, skipping first '$' 4008// given a pointer into a line of the buffer. 4009// Null terminates string, still inside the file buffer, 4010// Returns a pointer to a copy of the string, or NULL on failure 4011char *ADLParser::get_rep_var_ident_dup(void) { 4012 if( _curchar != '$' ) return NULL; 4013 4014 next_char(); // Move past the '$' 4015 char *rep_var = _ptr; // Remember starting point 4016 4017 // Check for a subfield indicator, a second '$': 4018 if ( _curchar == '$' ) { 4019 next_char(); 4020 } 4021 4022 // Check for a control indicator, a third '$': 4023 if ( _curchar == '$' ) { 4024 next_char(); 4025 } 4026 4027 // Check for more than three '$'s in sequence, SYNERR 4028 if( _curchar == '$' ) { 4029 parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'"); 4030 next_char(); 4031 return NULL; 4032 } 4033 4034 // Nil terminate the variable name following the '$' 4035 char *rep_var_name = get_ident(); 4036 assert( rep_var_name != NULL, 4037 "Missing identifier after replacement variable indicator '$'"); 4038 rep_var = strdup(rep_var); // Copy the string 4039 *_ptr = _curchar; // and replace Nil with original character 4040 4041 return rep_var; 4042} 4043 4044 4045//------------------------------get_unique_ident------------------------------ 4046// Looks for an identifier in the buffer, terminates it with a NULL, 4047// and checks that it is unique 4048char *ADLParser::get_unique_ident(FormDict& dict, const char* nameDescription){ 4049 char* ident = get_ident(); 4050 4051 if (ident == NULL) { 4052 parse_err(SYNERR, "missing %s identifier at %c\n", nameDescription, _curchar); 4053 } 4054 else { 4055 if (dict[ident] != NULL) { 4056 parse_err(SYNERR, "duplicate name %s for %s\n", ident, nameDescription); 4057 ident = NULL; 4058 } 4059 } 4060 4061 return ident; 4062} 4063 4064 4065//------------------------------get_int---------------------------------------- 4066// Looks for a character string integer in the buffer, and turns it into an int 4067// invokes a parse_err if the next token is not an integer. 4068// This routine does not leave the integer null-terminated. 4069int ADLParser::get_int(void) { 4070 register char c; 4071 char *start; // Pointer to start of token 4072 char *end; // Pointer to end of token 4073 int result; // Storage for integer result 4074 4075 if( _curline == NULL ) // Return NULL at EOF. 4076 return NULL; 4077 4078 skipws(); // Skip whitespace before identifier 4079 start = end = _ptr; // Start points at first character 4080 c = *end; // Grab character to test 4081 while ((c >= '0') && (c <= '9') 4082 || ((c == '-') && (end == start))) { 4083 end++; // Increment end pointer 4084 c = *end; // Grab character to test 4085 } 4086 if (start == end) { // We popped out on the first try 4087 parse_err(SYNERR, "integer expected at %c\n", c); 4088 result = 0; 4089 } 4090 else { 4091 _curchar = c; // Save the first character of next token 4092 *end = '\0'; // NULL terminate the string in place 4093 result = atoi(start); // Convert the string to an integer 4094 *end = _curchar; // Restore buffer to original condition 4095 } 4096 4097 // Reset _ptr to next char after token 4098 _ptr = end; 4099 4100 return result; // integer 4101} 4102 4103 4104//------------------------------get_relation_dup------------------------------ 4105// Looks for a relational operator in the buffer 4106// invokes a parse_err if the next token is not a relation 4107// This routine creates a duplicate of the string in the buffer. 4108char *ADLParser::get_relation_dup(void) { 4109 char *result = NULL; // relational operator being returned 4110 4111 if( _curline == NULL ) // Return NULL at EOF. 4112 return NULL; 4113 4114 skipws(); // Skip whitespace before relation 4115 char *start = _ptr; // Store start of relational operator 4116 char first = *_ptr; // the first character 4117 if( (first == '=') || (first == '!') || (first == '<') || (first == '>') ) { 4118 next_char(); 4119 char second = *_ptr; // the second character 4120 if( (second == '=') ) { 4121 next_char(); 4122 char tmp = *_ptr; 4123 *_ptr = '\0'; // NULL terminate 4124 result = strdup(start); // Duplicate the string 4125 *_ptr = tmp; // restore buffer 4126 } else { 4127 parse_err(SYNERR, "relational operator expected at %s\n", _ptr); 4128 } 4129 } else { 4130 parse_err(SYNERR, "relational operator expected at %s\n", _ptr); 4131 } 4132 4133 return result; 4134} 4135 4136 4137 4138//------------------------------get_oplist------------------------------------- 4139// Looks for identifier pairs where first must be the name of an operand, and 4140// second must be a name unique in the scope of this instruction. Stores the 4141// names with a pointer to the OpClassForm of their type in a local name table. 4142void ADLParser::get_oplist(NameList ¶meters, FormDict &operands) { 4143 OpClassForm *opclass = NULL; 4144 char *ident = NULL; 4145 4146 do { 4147 next_char(); // skip open paren & comma characters 4148 skipws(); 4149 if (_curchar == ')') break; 4150 4151 // Get operand type, and check it against global name table 4152 ident = get_ident(); 4153 if (ident == NULL) { 4154 parse_err(SYNERR, "optype identifier expected at %c\n", _curchar); 4155 return; 4156 } 4157 else { 4158 const Form *form = _globalNames[ident]; 4159 if( form == NULL ) { 4160 parse_err(SYNERR, "undefined operand type %s\n", ident); 4161 return; 4162 } 4163 4164 // Check for valid operand type 4165 OpClassForm *opc = form->is_opclass(); 4166 OperandForm *oper = form->is_operand(); 4167 if((oper == NULL) && (opc == NULL)) { 4168 parse_err(SYNERR, "identifier %s not operand type\n", ident); 4169 return; 4170 } 4171 opclass = opc; 4172 } 4173 // Debugging Stuff 4174 if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Type: %s\t", ident); 4175 4176 // Get name of operand and add it to local name table 4177 if( (ident = get_unique_ident(operands, "operand")) == NULL) { 4178 return; 4179 } 4180 // Parameter names must not be global names. 4181 if( _globalNames[ident] != NULL ) { 4182 parse_err(SYNERR, "Reuse of global name %s as operand.\n",ident); 4183 return; 4184 } 4185 operands.Insert(ident, opclass); 4186 parameters.addName(ident); 4187 4188 // Debugging Stuff 4189 if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident); 4190 skipws(); 4191 } while(_curchar == ','); 4192 4193 if (_curchar != ')') parse_err(SYNERR, "missing ')'\n"); 4194 else { 4195 next_char(); // set current character position past the close paren 4196 } 4197} 4198 4199 4200//------------------------------get_effectlist--------------------------------- 4201// Looks for identifier pairs where first must be the name of a pre-defined, 4202// effect, and the second must be the name of an operand defined in the 4203// operand list of this instruction. Stores the names with a pointer to the 4204// effect form in a local effects table. 4205void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) { 4206 OperandForm *opForm; 4207 Effect *eForm; 4208 char *ident; 4209 4210 do { 4211 next_char(); // skip open paren & comma characters 4212 skipws(); 4213 if (_curchar == ')') break; 4214 4215 // Get effect type, and check it against global name table 4216 ident = get_ident(); 4217 if (ident == NULL) { 4218 parse_err(SYNERR, "effect type identifier expected at %c\n", _curchar); 4219 return; 4220 } 4221 else { 4222 // Check for valid effect type 4223 const Form *form = _globalNames[ident]; 4224 if( form == NULL ) { 4225 parse_err(SYNERR, "undefined effect type %s\n", ident); 4226 return; 4227 } 4228 else { 4229 if( (eForm = form->is_effect()) == NULL) { 4230 parse_err(SYNERR, "identifier %s not effect type\n", ident); 4231 return; 4232 } 4233 } 4234 } 4235 // Debugging Stuff 4236 if (_AD._adl_debug > 1) fprintf(stderr, "\tEffect Type: %s\t", ident); 4237 skipws(); 4238 // Get name of operand and check that it is in the local name table 4239 if( (ident = get_unique_ident(effects, "effect")) == NULL) { 4240 parse_err(SYNERR, "missing operand identifier in effect list\n"); 4241 return; 4242 } 4243 const Form *form = operands[ident]; 4244 opForm = form ? form->is_operand() : NULL; 4245 if( opForm == NULL ) { 4246 if( form && form->is_opclass() ) { 4247 const char* cname = form->is_opclass()->_ident; 4248 parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident); 4249 } else { 4250 parse_err(SYNERR, "undefined operand %s in effect list\n", ident); 4251 } 4252 return; 4253 } 4254 // Add the pair to the effects table 4255 effects.Insert(ident, eForm); 4256 // Debugging Stuff 4257 if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident); 4258 skipws(); 4259 } while(_curchar == ','); 4260 4261 if (_curchar != ')') parse_err(SYNERR, "missing ')'\n"); 4262 else { 4263 next_char(); // set current character position past the close paren 4264 } 4265} 4266 4267 4268//------------------------------preproc_define--------------------------------- 4269// A "#define" keyword has been seen, so parse the rest of the line. 4270void ADLParser::preproc_define(void) { 4271 char* flag = get_ident_no_preproc(); 4272 skipws_no_preproc(); 4273 // only #define x y is supported for now 4274 char* def = get_ident_no_preproc(); 4275 _AD.set_preproc_def(flag, def); 4276 skipws_no_preproc(); 4277 if (_curchar != '\n') { 4278 parse_err(SYNERR, "non-identifier in preprocessor definition\n"); 4279 } 4280} 4281 4282//------------------------------preproc_undef---------------------------------- 4283// An "#undef" keyword has been seen, so parse the rest of the line. 4284void ADLParser::preproc_undef(void) { 4285 char* flag = get_ident_no_preproc(); 4286 skipws_no_preproc(); 4287 ensure_end_of_line(); 4288 _AD.set_preproc_def(flag, NULL); 4289} 4290 4291 4292 4293//------------------------------parse_err-------------------------------------- 4294// Issue a parser error message, and skip to the end of the current line 4295void ADLParser::parse_err(int flag, const char *fmt, ...) { 4296 va_list args; 4297 4298 va_start(args, fmt); 4299 if (flag == 1) 4300 _AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); 4301 else if (flag == 2) 4302 _AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); 4303 else 4304 _AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args); 4305 4306 int error_char = _curchar; 4307 char* error_ptr = _ptr+1; 4308 for(;*_ptr != '\n'; _ptr++) ; // Skip to the end of the current line 4309 _curchar = '\n'; 4310 va_end(args); 4311 _AD._no_output = 1; 4312 4313 if (flag == 1) { 4314 char* error_tail = strchr(error_ptr, '\n'); 4315 char tem = *error_ptr; 4316 error_ptr[-1] = '\0'; 4317 char* error_head = error_ptr-1; 4318 while (error_head > _curline && *error_head) --error_head; 4319 if (error_tail) *error_tail = '\0'; 4320 fprintf(stderr, "Error Context: %s>>>%c<<<%s\n", 4321 error_head, error_char, error_ptr); 4322 if (error_tail) *error_tail = '\n'; 4323 error_ptr[-1] = tem; 4324 } 4325} 4326 4327//---------------------------ensure_start_of_line------------------------------ 4328// A preprocessor directive has been encountered. Be sure it has fallen at 4329// the begining of a line, or else report an error. 4330void ADLParser::ensure_start_of_line(void) { 4331 assert( _ptr >= _curline && _ptr < _curline+strlen(_curline), 4332 "Must be able to find which line we are in" ); 4333 4334 for (char *s = _curline; s < _ptr; s++) { 4335 if (*s > ' ') { 4336 parse_err(SYNERR, "'%c' must be at beginning of line\n", _curchar); 4337 break; 4338 } 4339 } 4340} 4341 4342//---------------------------ensure_end_of_line-------------------------------- 4343// A preprocessor directive has been parsed. Be sure there is no trailing 4344// garbage at the end of this line. Set the scan point to the beginning of 4345// the next line. 4346void ADLParser::ensure_end_of_line(void) { 4347 skipws_no_preproc(); 4348 if (_curchar != '\n' && _curchar != '\0') { 4349 parse_err(SYNERR, "garbage char '%c' at end of line\n", _curchar); 4350 } else { 4351 next_char_or_line(); 4352 } 4353} 4354 4355//---------------------------handle_preproc------------------------------------ 4356// The '#' character introducing a preprocessor directive has been found. 4357// Parse the whole directive name (e.g., #define, #endif) and take appropriate 4358// action. If we are in an "untaken" span of text, simply keep track of 4359// #ifdef nesting structure, so we can find out when to start taking text 4360// again. (In this state, we "sort of support" C's #if directives, enough 4361// to disregard their associated #else and #endif lines.) If we are in a 4362// "taken" span of text, there are two cases: "#define" and "#undef" 4363// directives are preserved and passed up to the caller, which eventually 4364// passes control to the top-level parser loop, which handles #define and 4365// #undef directly. (This prevents these directives from occurring in 4366// arbitrary positions in the AD file--we require better structure than C.) 4367// In the other case, and #ifdef, #ifndef, #else, or #endif is silently 4368// processed as whitespace, with the "taken" state of the text correctly 4369// updated. This routine returns "false" exactly in the case of a "taken" 4370// #define or #undef, which tells the caller that a preprocessor token 4371// has appeared which must be handled explicitly by the parse loop. 4372bool ADLParser::handle_preproc_token() { 4373 assert(*_ptr == '#', "must be at start of preproc"); 4374 ensure_start_of_line(); 4375 next_char(); 4376 skipws_no_preproc(); 4377 char* start_ident = _ptr; 4378 char* ident = (_curchar == '\n') ? NULL : get_ident_no_preproc(); 4379 if (ident == NULL) { 4380 parse_err(SYNERR, "expected preprocessor command, got end of line\n"); 4381 } else if (!strcmp(ident, "ifdef") || 4382 !strcmp(ident, "ifndef")) { 4383 char* flag = get_ident_no_preproc(); 4384 ensure_end_of_line(); 4385 // Test the identifier only if we are already in taken code: 4386 bool flag_def = preproc_taken() && (_AD.get_preproc_def(flag) != NULL); 4387 bool now_taken = !strcmp(ident, "ifdef") ? flag_def : !flag_def; 4388 begin_if_def(now_taken); 4389 } else if (!strcmp(ident, "if")) { 4390 if (preproc_taken()) 4391 parse_err(SYNERR, "unimplemented: #%s %s", ident, _ptr+1); 4392 next_line(); 4393 // Intelligently skip this nested C preprocessor directive: 4394 begin_if_def(true); 4395 } else if (!strcmp(ident, "else")) { 4396 ensure_end_of_line(); 4397 invert_if_def(); 4398 } else if (!strcmp(ident, "endif")) { 4399 ensure_end_of_line(); 4400 end_if_def(); 4401 } else if (preproc_taken()) { 4402 // pass this token up to the main parser as "#define" or "#undef" 4403 _ptr = start_ident; 4404 _curchar = *--_ptr; 4405 if( _curchar != '#' ) { 4406 parse_err(SYNERR, "no space allowed after # in #define or #undef"); 4407 assert(_curchar == '#', "no space allowed after # in #define or #undef"); 4408 } 4409 return false; 4410 } 4411 return true; 4412} 4413 4414//---------------------------skipws_common------------------------------------- 4415// Skip whitespace, including comments and newlines, while keeping an accurate 4416// line count. 4417// Maybe handle certain preprocessor constructs: #ifdef, #ifndef, #else, #endif 4418void ADLParser::skipws_common(bool do_preproc) { 4419 char *start = _ptr; 4420 char *next = _ptr + 1; 4421 4422 if (*_ptr == '\0') { 4423 // Check for string terminator 4424 if (_curchar > ' ') return; 4425 if (_curchar == '\n') { 4426 if (!do_preproc) return; // let caller handle the newline 4427 next_line(); 4428 _ptr = _curline; next = _ptr + 1; 4429 } 4430 else if (_curchar == '#' || 4431 (_curchar == '/' && (*next == '/' || *next == '*'))) { 4432 parse_err(SYNERR, "unimplemented: comment token in a funny place"); 4433 } 4434 } 4435 while(_curline != NULL) { // Check for end of file 4436 if (*_ptr == '\n') { // keep proper track of new lines 4437 if (!do_preproc) break; // let caller handle the newline 4438 next_line(); 4439 _ptr = _curline; next = _ptr + 1; 4440 } 4441 else if ((*_ptr == '/') && (*next == '/')) // C++ comment 4442 do { _ptr++; next++; } while(*_ptr != '\n'); // So go to end of line 4443 else if ((*_ptr == '/') && (*next == '*')) { // C comment 4444 _ptr++; next++; 4445 do { 4446 _ptr++; next++; 4447 if (*_ptr == '\n') { // keep proper track of new lines 4448 next_line(); // skip newlines within comments 4449 if (_curline == NULL) { // check for end of file 4450 parse_err(SYNERR, "end-of-file detected inside comment\n"); 4451 break; 4452 } 4453 _ptr = _curline; next = _ptr + 1; 4454 } 4455 } while(!((*_ptr == '*') && (*next == '/'))); // Go to end of comment 4456 _ptr = ++next; next++; // increment _ptr past comment end 4457 } 4458 else if (do_preproc && *_ptr == '#') { 4459 // Note that this calls skipws_common(false) recursively! 4460 bool preproc_handled = handle_preproc_token(); 4461 if (!preproc_handled) { 4462 if (preproc_taken()) { 4463 return; // short circuit 4464 } 4465 ++_ptr; // skip the preprocessor character 4466 } 4467 next = _ptr+1; 4468 } else if(*_ptr > ' ' && !(do_preproc && !preproc_taken())) { 4469 break; 4470 } 4471 else if (*_ptr == '"' || *_ptr == '\'') { 4472 assert(do_preproc, "only skip strings if doing preproc"); 4473 // skip untaken quoted string 4474 int qchar = *_ptr; 4475 while (true) { 4476 ++_ptr; 4477 if (*_ptr == qchar) { ++_ptr; break; } 4478 if (*_ptr == '\\') ++_ptr; 4479 if (*_ptr == '\n' || *_ptr == '\0') { 4480 parse_err(SYNERR, "newline in string"); 4481 break; 4482 } 4483 } 4484 next = _ptr + 1; 4485 } 4486 else { ++_ptr; ++next; } 4487 } 4488 if( _curline != NULL ) // at end of file _curchar isn't valid 4489 _curchar = *_ptr; // reset _curchar to maintain invariant 4490} 4491 4492//---------------------------cur_char----------------------------------------- 4493char ADLParser::cur_char() { 4494 return (_curchar); 4495} 4496 4497//---------------------------next_char----------------------------------------- 4498void ADLParser::next_char() { 4499 _curchar = *++_ptr; 4500 // if ( _curchar == '\n' ) { 4501 // next_line(); 4502 // } 4503} 4504 4505//---------------------------next_char_or_line--------------------------------- 4506void ADLParser::next_char_or_line() { 4507 if ( _curchar != '\n' ) { 4508 _curchar = *++_ptr; 4509 } else { 4510 next_line(); 4511 _ptr = _curline; 4512 _curchar = *_ptr; // maintain invariant 4513 } 4514} 4515 4516//---------------------------next_line----------------------------------------- 4517void ADLParser::next_line() { 4518 _curline = _buf.get_line(); _linenum++; 4519} 4520 4521//-------------------------is_literal_constant--------------------------------- 4522bool ADLParser::is_literal_constant(const char *param) { 4523 if (param[0] == 0) return false; // null string 4524 if (param[0] == '(') return true; // parenthesized expression 4525 if (param[0] == '0' && (param[1] == 'x' || param[1] == 'X')) { 4526 // Make sure it's a hex constant. 4527 int i = 2; 4528 do { 4529 if( !ADLParser::is_hex_digit(*(param+i)) ) return false; 4530 ++i; 4531 } while( *(param+i) != 0 ); 4532 return true; 4533 } 4534 return false; 4535} 4536 4537//---------------------------is_hex_digit-------------------------------------- 4538bool ADLParser::is_hex_digit(char digit) { 4539 return ((digit >= '0') && (digit <= '9')) 4540 ||((digit >= 'a') && (digit <= 'f')) 4541 ||((digit >= 'A') && (digit <= 'F')); 4542} 4543 4544//---------------------------is_int_token-------------------------------------- 4545bool ADLParser::is_int_token(const char* token, int& intval) { 4546 const char* cp = token; 4547 while (*cp != '\0' && *cp <= ' ') cp++; 4548 if (*cp == '-') cp++; 4549 int ndigit = 0; 4550 while (*cp >= '0' && *cp <= '9') { cp++; ndigit++; } 4551 while (*cp != '\0' && *cp <= ' ') cp++; 4552 if (ndigit == 0 || *cp != '\0') { 4553 return false; 4554 } 4555 intval = atoi(token); 4556 return true; 4557} 4558 4559//-------------------------------trim------------------------------------------ 4560void ADLParser::trim(char* &token) { 4561 while (*token <= ' ') token++; 4562 char* end = token + strlen(token); 4563 while (end > token && *(end-1) <= ' ') --end; 4564 *end = '\0'; 4565} 4566