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