/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
// ADLPARSE.CPP - Architecture Description Language Parser
// Authors: Chris Vick and Mike Paleczny
#include "adlc.hpp"
//----------------------------ADLParser----------------------------------------
// Create a new ADL parser
_preproc_depth = 0;
_preproc_not_taken = 0;
// Delimit command-line definitions from in-file definitions:
}
//------------------------------~ADLParser-------------------------------------
// Delete an ADL parser.
if (!_AD._quiet_mode)
#ifndef ASSERT
#endif
if (!_AD._quiet_mode)
}
else {
}
}
}
}
if (!_AD._quiet_mode)
// Write out information we have stored
// // UNIXism == fsync(stderr);
}
//------------------------------parse------------------------------------------
// Each top-level keyword should appear as the first non-whitespace on a line.
//
char *ident;
// Iterate over the lines in the file buffer parsing Level 1 objects
skipws(); // Skip any leading whitespace
ident = get_ident(); // Get first token
if (ident == NULL) { // Empty line
continue; // Get the next line
}
else {
parse_err(SYNERR, "expected one of - instruct, operand, ins_attrib, op_attrib, source, register, pipeline, encode\n Found %s",ident);
}
}
// Add reg_class spill_regs after parsing.
}
// Done with parsing, check consistency.
if (_preproc_depth != 0) {
}
// AttributeForms ins_cost and op_cost must be defined for default behaviour
}
}
}
// ******************** Private Level 1 Parse Functions ********************
//------------------------------instr_parse------------------------------------
// Parse the contents of an instruction definition, build the InstructForm to
// represent that instruction, and add it to the InstructForm list.
char *ident;
int match_rules_cnt = 0;
// First get the name of the instruction
return;
// Debugging Stuff
// Then get the operands
skipws();
if (_curchar != '(') {
}
// Parse the operand list
skipws(); // Skip leading whitespace
// Check for block delimiter
if ( (_curchar != '%')
return;
}
next_char(); // Maintain the invariant
do {
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
continue;
}
else if (!strcmp(ident, "match")) {
// Allow one instruction have several match rules.
// This is first match rule encountered
if (rule) {
// Special case the treatment of Control instructions.
if( instr->is_ideal_control() ) {
// Control instructions return a special result, 'Universe'
}
// Check for commutative operations with tree operands.
}
} else {
// Find the end of the match rule list
// Add the new match rule to the list
if( instr->is_ideal_control() ) {
return;
}
// Check for commutative operations with tree operands.
}
}
}
else if (!strcmp(ident, "encode")) {
}
else if (!strcmp(ident, "constraint")) {
}
else if (!strcmp(ident, "construct")) {
}
else if (!strcmp(ident, "interface")) {
}
else { // Done with staticly defined parts of instruction definition
// Check identifier to see if it is the name of an attribute
// Insert the new attribute into the linked list.
} else {
parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of an instruction attribute at %s\n", ident);
}
}
skipws();
} while(_curchar != '%');
next_char();
if (_curchar != '}') {
return;
}
// Check for "Set" form of chain rule
parse_err(WARN, "ins_pipe and expand rule both specified for instruction \"%s\"; ins_pipe will be unused\n", instr->_ident);
} else {
}
}
// Add instruction to tail of instruction list
// Create instruction form for each additional match rule
// Debugging Stuff
// Check for "Set" form of chain rule
// Add instruction to tail of instruction list
}
}
}
//------------------------------matchrule_clone_and_swap-----------------------
// Check for commutative operations with subtree operands,
// create clones and swap operands.
void ADLParser::matchrule_clone_and_swap(MatchRule* rule, const char* instr_ident, int& match_rules_cnt) {
// Check for commutative operations with tree operands.
int count = 0;
if (count > 0) {
// Clone match rule and swap commutative operation's operands.
}
}
//------------------------------adjust_set_rule--------------------------------
// Check for "Set" form of chain rule
// Previous implementation, which missed leaP*, but worked for loadCon*
unsigned position = 0;
position = 1;
// Can not have additional base operands in right side of match!
// Chain from input _ideal_operand_type_,
// Needed for shared roots of match-trees
}
}
// The ADLC does not support chaining from the ideal operand type
// of a predicated user-defined operand
}
}
// Chain from input _user_defined_operand_type_,
}
}
// It is safe to chain from the top-level user-defined operand even
// if it has a predicate, since the predicate is checked before
// the user-defined type is available.
}
} else {
// May have instruction chain rule if root of right-tree is an ideal
if( rightOp ) {
if( rightRoot->is_instruction() )
if( chain_op ) {
// Look-up the operation in chain rule table
}
// if (!lst->search(instr->_matrule->_lChild->_opType)) {
}
// This chains from a top-level operand whose predicate, if any,
// has been checked.
// }
}
}
}
} // end chain rule from right-tree's ideal root
}
}
}
//------------------------------oper_parse-------------------------------------
char *ident;
// First get the name of the operand
skipws();
return;
// Debugging Stuff
// Get the component operands
skipws();
if (_curchar != '(') {
return;
}
skipws();
// Check for block delimiter
return;
}
do {
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
continue;
}
else if (!strcmp(ident, "match")) {
// Find the end of the match rule list
if (rule) {
// Add the new match rule to the list
}
}
else {
// This is first match rule encountered
}
}
}
else if (!strcmp(ident, "ins_encode")) {
}
else if (!strcmp(ident, "opcode")) {
}
else if (!strcmp(ident, "effect")) {
}
else if (!strcmp(ident, "expand")) {
}
else if (!strcmp(ident, "rewrite")) {
}
// Check identifier to see if it is the name of an attribute
else {
parse_err(SYNERR, "expected one of - constraint, predicate, match, encode, format, construct, or the name of a defined operand attribute at %s\n", ident);
}
skipws();
} while(_curchar != '%');
next_char();
if (_curchar != '}') {
return;
}
// Add operand to tail of operand list
}
//------------------------------opclass_parse----------------------------------
// Operand Classes are a block with a comma delimited list of operand names
char *ident;
// First get the name of the operand class
skipws();
return;
// Debugging Stuff
// Get the list of operands
skipws();
if (_curchar != '(') {
return;
}
do {
next_char(); // Skip past open paren or comma
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
continue;
}
// Check identifier to see if it is the name of an operand
if ( opForm ) {
}
else {
}
skipws(); // skip trailing whitespace
// Check for closing ')'
if (_curchar != ')') {
return;
}
next_char(); // Consume the ')'
skipws();
// Check for closing ';'
if (_curchar != ';') {
return;
}
next_char(); // Consume the ';'
// Add operand to tail of operand list
}
//------------------------------ins_attr_parse---------------------------------
char *ident;
char *aexpr;
// get name for the instruction attribute
skipws(); // Skip leading whitespace
return;
// Debugging Stuff
// Get default value of the instruction attribute
skipws(); // Skip whitespace
return;
}
// Debug Stuff
// Check for terminator
if (_curchar != ';') {
return;
}
next_char(); // Advance past the ';'
// Construct the attribute, record global name, and store in ArchDesc
}
//------------------------------op_attr_parse----------------------------------
char *ident;
char *aexpr;
// get name for the operand attribute
skipws(); // Skip leading whitespace
return;
// Debugging Stuff
// Get default value of the instruction attribute
skipws(); // Skip whitespace
return;
}
// Debug Stuff
// Check for terminator
if (_curchar != ';') {
return;
}
next_char(); // Advance past the ';'
// Construct the attribute, record global name, and store in ArchDesc
}
//------------------------------definitions_parse-----------------------------------
skipws(); // Skip leading whitespace
skipws();
// Process each definition until finding closing string "%}"
return;
}
// if (strcmp(token,"str_def")==0) { str_def_parse(); }
skipws();
}
}
else {
return;
}
}
//------------------------------int_def_parse----------------------------------
// Parse Example:
// int_def MEMORY_REF_COST ( 200, DEFAULT_COST * 2);
// <keyword> <name> ( <int_value>, <description> );
//
// Get definition name
skipws(); // Skip whitespace
return;
}
// Check for value of int_def dname( integer_value [, string_expression ] )
skipws();
if (_curchar == '(') {
// Parse the integer value.
next_char();
return;
}
return;
}
skipws();
// Check for description
if (_curchar == ',') {
next_char(); // skip ','
if (description == NULL) {
return;
}
}
if (_curchar != ')') {
return;
}
next_char();
}
// Check for closing ';'
skipws();
if (_curchar != ';') {
return;
}
next_char(); // move past ';'
// Debug Stuff
}
// Record new definition.
return;
}
return;
}
//------------------------------source_parse-----------------------------------
skipws(); // Skip leading whitespace
return;
}
// Debug Stuff
// skipws();
}
//------------------------------source_hpp_parse-------------------------------
// Parse a source_hpp %{ ... %} block.
// The code gets stuck into the ad_<arch>.hpp file.
// If the source_hpp block appears before the register block in the AD
// file, it goes up at the very top of the ad_<arch>.hpp file, so that
// it can be used by register encodings, etc. Otherwise, it goes towards
// the bottom, where it's useful as a global definition to *.cpp files.
skipws(); // Skip leading whitespace
return;
}
// Debug Stuff
// Very early in the file, before reg_defs, we collect pre-headers.
} else {
// Normally, we collect header info, placed at the bottom of the hpp file.
}
}
//------------------------------reg_parse--------------------------------------
// Create the RegisterForm for the architecture description.
}
skipws(); // Skip leading whitespace
skipws();
return;
}
skipws();
}
}
else {
return;
}
}
//------------------------------encode_parse-----------------------------------
// Create the EncodeForm for the architecture description.
}
skipws(); // Skip leading whitespace
skipws();
return;
}
skipws();
}
}
else {
return;
}
}
//------------------------------enc_class_parse--------------------------------
// Get encoding class name
skipws(); // Skip whitespace
return;
}
skipws(); // Skip leading whitespace
// Check for optional parameter list
if (_curchar == '(') {
do {
next_char(); // skip open paren & comma characters
skipws();
if (_curchar == ')') break;
// Get parameter type
return;
}
skipws();
// Get parameter name
return;
}
// Record parameter type and name
skipws();
} while(_curchar == ',');
else {
next_char(); // Skip ')'
}
} // Done with parameter list
skipws();
// Check for block starting delimiters
return;
}
next_char(); // Skip '%'
next_char(); // Skip '{'
}
skipws_no_preproc(); // Skip leading whitespace
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
if (_AD._adlocation_debug) {
}
// Collect the parts of the encode description
// (1) strings that are passed through to output
// (2) replacement/substitution variable, preceeded by a '$'
// (1)
// Check if there is a string to pass through to output
// If at the start of a comment, skip past it
} else {
// ELSE advance to the next character, or start of the next line
}
}
// If a string was found, terminate it and record in EncClass
}
// (2)
// If we are at a replacement variable,
// copy it and record in EncClass
if (_curchar == '$') {
// Found replacement Variable
// Add flag to _strings list indicating we should check _rep_vars
}
} // end while part of format description
next_char(); // Skip '%'
next_char(); // Skip '}'
skipws();
if (_AD._adlocation_debug) {
}
// Debug Stuff
}
//------------------------------frame_parse-----------------------------------
skipws(); // Skip leading whitespace
// Check for open block sequence
skipws(); // Skip leading whitespace
skipws();
return;
}
}
}
frame_pointer_parse(frame, false);
}
interpreter_frame_pointer_parse(frame, false);
}
inline_cache_parse(frame, false);
}
skipws();
}
interpreter_method_oop_parse(frame, false);
}
cisc_spilling_operand_name_parse(frame, false);
}
}
return_addr_parse(frame, false);
}
}
skipws();
}
}
}
}
frame_pointer_parse(frame, true);
}
return_addr_parse(frame, true);
}
}
}
skipws();
}
}
else {
return;
}
// All Java versions are required, native versions are optional
return;
}
// !!!!! !!!!!
// if(frame->_interpreter_frame_ptr_reg == NULL) {
// parse_err(SYNERR, "missing interpreter frame pointer definition in frame section.\n");
// return;
// }
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
// Fill natives in identically with the Java versions if not present.
}
}
}
}
// Debug Stuff
// Create the EncodeForm for the architecture description.
// skipws();
}
//------------------------------stack_dir_parse--------------------------------
frame->_direction = false;
}
frame->_direction = true;
}
else {
return;
}
}
//------------------------------sync_stack_slots_parse-------------------------
// Assign value into frame form
}
//------------------------------frame_pointer_parse----------------------------
// Assign value into frame form
}
//------------------------------interpreter_frame_pointer_parse----------------------------
}
//------------------------------inline_cache_parse-----------------------------
}
//------------------------------interpreter_method_oop_parse------------------
}
//------------------------------cisc_spilling_operand_parse---------------------
}
//------------------------------stack_alignment_parse--------------------------
// Assign value into frame
}
//------------------------------parse_one_arg-------------------------------
if(_curchar == '(') {
next_char();
skipws();
return NULL;
}
next_char(); // skip the close paren
return NULL;
}
next_char(); // skip the semi-colon
}
else {
return NULL;
}
return token;
}
//------------------------------return_addr_parse------------------------------
bool in_register = true;
if(_curchar == '(') {
next_char();
skipws();
return;
}
in_register = true;
}
in_register = false;
}
else {
return;
}
// Parse expression that specifies register or stack position
skipws();
return;
}
next_char(); // skip the close paren
return;
}
next_char(); // skip the semi-colon
}
else {
}
}
//------------------------------preserve_stack_parse---------------------------
if(_curchar == '(') {
return;
}
next_char(); // skip the semi-colon
}
else {
}
}
//------------------------------calling_convention_parse-----------------------
skipws(); // Skip leading whitespace
}
return desc;
}
//------------------------------return_value_parse-----------------------------
skipws(); // Skip leading whitespace
}
return desc;
}
//------------------------------ins_pipe_parse---------------------------------
char * ident;
skipws();
return;
}
next_char();
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
return;
}
skipws();
return;
}
next_char(); // skip the close paren
return;
}
next_char(); // skip the semi-colon
// Check ident for validity
return;
}
// Add this instruction to the list in the pipeline class
// Set the name of the pipeline class in the instruction
return;
}
//------------------------------pipe_parse-------------------------------------
char * ident;
skipws(); // Skip leading whitespace
// Check for block delimiter
if ( (_curchar != '%')
return;
}
next_char(); // Maintain the invariant
do {
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
continue;
}
else if (!strcmp(ident, "define")) {
skipws();
if ( (_curchar != '%')
return;
}
if (node_class == NULL) {
return;
}
skipws();
break;
}
if (pipe_class == NULL) {
return;
}
if (_curchar != ';' ) {
break;
}
next_char(); // Skip over semi-colon
skipws();
if ( (_curchar != '%')
}
next_char();
// Check ident for validity
return;
}
// Add this machine node to the list in the pipeline class
}
else if (!strcmp(ident, "attributes")) {
bool vsi_seen = false;
skipws();
if ( (_curchar != '%')
return;
}
while (_curchar != '%') {
ident = get_ident();
if (ident == NULL)
break;
if (!strcmp(ident, "variable_size_instructions")) {
skipws();
if (_curchar == ';') {
}
pipeline->_variableSizeInstrs = true;
vsi_seen = true;
continue;
}
if (!strcmp(ident, "fixed_size_instructions")) {
skipws();
if (_curchar == ';') {
}
pipeline->_variableSizeInstrs = false;
vsi_seen = true;
continue;
}
if (!strcmp(ident, "branch_has_delay_slot")) {
skipws();
if (_curchar == ';') {
}
pipeline->_branchHasDelaySlot = true;
continue;
}
if (!strcmp(ident, "max_instructions_per_bundle")) {
skipws();
if (_curchar != '=') {
break;
}
skipws();
if (_curchar == ';') {
}
continue;
}
if (!strcmp(ident, "max_bundles_per_cycle")) {
skipws();
if (_curchar != '=') {
break;
}
skipws();
if (_curchar == ';') {
}
continue;
}
if (!strcmp(ident, "instruction_unit_size")) {
skipws();
if (_curchar != '=') {
break;
}
skipws();
if (_curchar == ';') {
}
continue;
}
if (!strcmp(ident, "bundle_unit_size")) {
skipws();
if (_curchar != '=') {
break;
}
skipws();
if (_curchar == ';') {
}
continue;
}
if (!strcmp(ident, "instruction_fetch_unit_size")) {
skipws();
if (_curchar != '=') {
break;
}
skipws();
if (_curchar == ';') {
}
continue;
}
if (!strcmp(ident, "instruction_fetch_units")) {
skipws();
if (_curchar != '=') {
break;
}
skipws();
if (_curchar == ';') {
}
continue;
}
if (!strcmp(ident, "nops")) {
skipws();
if (_curchar != '(') {
break;
}
while (_curchar != ')') {
ident = get_ident();
if (ident == NULL) {
break;
}
skipws();
if (_curchar == ',') {
}
}
if (_curchar == ';') {
}
continue;
}
}
if ( (_curchar != '%')
}
if (pipeline->_maxInstrsPerBundle == 0)
if (pipeline->_instrFetchUnitSize == 0)
if (pipeline->_instrFetchUnits == 0)
if (!vsi_seen)
}
else { // Done with staticly defined parts of instruction definition
parse_err(SYNERR, "expected one of \"resources\", \"pipe_desc\", \"pipe_class\", found \"%s\"\n", ident);
return;
}
skipws();
if (_curchar == ';')
skipws();
} while(_curchar != '%');
next_char();
if (_curchar != '}') {
return;
}
next_char();
}
//------------------------------resource_parse----------------------------
char * ident;
char * expr;
unsigned mask;
skipws(); // Skip leading whitespace
if (_curchar != '(') {
return;
}
do {
next_char(); // Skip "(" or ","
ident = get_ident(); // Grab next identifier
if (ident != NULL) {
}
}
if (ident == NULL) {
return;
}
skipws();
if (_curchar != '=') {
}
else {
return;
}
return;
}
skipws();
while (_curchar == '|') {
return;
}
return;
}
skipws();
}
}
} while (_curchar == ',');
if (_curchar != ')') {
return;
}
next_char(); // Skip ")"
if (_curchar == ';')
next_char(); // Skip ";"
}
//------------------------------resource_parse----------------------------
char * ident;
skipws(); // Skip leading whitespace
if (_curchar != '(') {
return;
}
do {
next_char(); // Skip "(" or ","
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
return;
}
// Add the name to the list
skipws();
} while (_curchar == ',');
if (_curchar != ')') {
return;
}
next_char(); // Skip ")"
if (_curchar == ';')
next_char(); // Skip ";"
}
//------------------------------pipe_class_parse--------------------------
char * ident;
char * stage;
char * read_or_write;
int is_write;
int is_read;
skipws(); // Skip leading whitespace
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
return;
}
// Create a record for the pipe_class
// Then get the operands
skipws();
if (_curchar != '(') {
}
// Parse the operand list
skipws(); // Skip leading whitespace
// Check for block delimiter
if ( (_curchar != '%')
return;
}
next_char();
do {
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
continue;
}
skipws();
if (!strcmp(ident, "fixed_latency")) {
skipws();
if (_curchar != '(') {
return;
}
return;
}
skipws();
if (_curchar != ')') {
return;
}
if (_curchar != ';') {
return;
}
continue;
}
if (!strcmp(ident, "zero_instructions") ||
!strcmp(ident, "no_instructions")) {
skipws();
if (_curchar != ';') {
return;
}
continue;
}
if (!strcmp(ident, "one_instruction_with_delay_slot") ||
!strcmp(ident, "single_instruction_with_delay_slot")) {
skipws();
if (_curchar != ';') {
return;
}
pipe_class->setBranchDelay(true);
continue;
}
if (!strcmp(ident, "one_instruction") ||
!strcmp(ident, "single_instruction")) {
skipws();
if (_curchar != ';') {
return;
}
continue;
}
if (!strcmp(ident, "instructions_in_first_bundle") ||
!strcmp(ident, "instruction_count")) {
skipws();
if (_curchar != '(') {
continue;
}
skipws();
if (_curchar != ')') {
continue;
}
if (_curchar != ';') {
return;
}
continue;
}
if (!strcmp(ident, "multiple_bundles")) {
skipws();
if (_curchar != ';') {
return;
}
pipe_class->setMultipleBundles(true);
continue;
}
if (!strcmp(ident, "has_delay_slot")) {
skipws();
if (_curchar != ';') {
return;
}
pipe_class->setBranchDelay(true);
continue;
}
if (!strcmp(ident, "force_serialization")) {
skipws();
if (_curchar != ';') {
return;
}
pipe_class->setForceSerialization(true);
continue;
}
if (!strcmp(ident, "may_have_no_code")) {
skipws();
if (_curchar != ';') {
return;
}
pipe_class->setMayHaveNoCode(true);
continue;
}
continue;
}
if (_curchar != ':') {
continue;
}
continue;
}
skipws();
if (_curchar != '(') {
continue;
}
next_char();
read_or_write = get_ident();
if (read_or_write == NULL) {
continue;
}
continue;
}
skipws();
if (_curchar != ')') {
continue;
}
int more_instrs = 0;
if (_curchar == '+') {
continue;
}
more_instrs *= 10;
next_char();
}
skipws();
}
if (_curchar == '%')
continue;
if (_curchar != ';') {
continue;
}
continue;
}
// Scan for Resource Specifier
if (_curchar != ':') {
continue;
}
continue;
}
skipws();
if (_curchar == '(') {
next_char();
skipws();
if (_curchar != ')') {
continue;
}
}
if (_curchar == '%')
continue;
if (_curchar != ';') {
continue;
}
continue;
}
return;
} while(_curchar != '%');
next_char();
if (_curchar != '}') {
return;
}
next_char();
}
//------------------------------peep_parse-------------------------------------
skipws(); // Skip leading whitespace
// Check for open block sequence
skipws(); // Skip leading whitespace
skipws();
return;
}
// check for legal subsections of peephole rule
peep_match_parse(*peep); }
peep_replace_parse(*peep); }
else {
parse_err(SYNERR, "expected peepmatch, peepconstraint, or peepreplace for identifier %s.\n", token);
}
skipws();
}
}
else {
return;
}
next_char(); // Skip past '%'
next_char(); // Skip past '}'
}
// ******************** Private Level 2 Parse Functions ********************
//------------------------------constraint_parse------------------------------
char *func;
char *arg;
// Check for constraint expression
skipws();
if (_curchar != '(') {
return NULL;
}
next_char(); // Skip past '('
// Get constraint function
skipws();
return NULL;
}
// Check for '(' before argument
skipws();
if (_curchar != '(') {
return NULL;
}
next_char();
// Get it's argument
skipws();
return NULL;
}
// Check for ')' after argument
skipws();
if (_curchar != ')') {
return NULL;
}
next_char();
} else {
return NULL;
}
// Check for closing paren and ';'
skipws();
if (_curchar != ')') {
return NULL;
}
next_char();
skipws();
if (_curchar != ';') {
return NULL;
}
next_char();
// Create new "Constraint"
return constraint;
}
//------------------------------constr_parse-----------------------------------
return NULL;
}
//------------------------------reg_def_parse----------------------------------
// Get register name
skipws(); // Skip whitespace
return;
}
// Check for definition of register calling convention (save on call, ...),
// register save type, and register encoding value.
skipws();
if (_curchar == '(') {
next_char();
// Parse the internal calling convention, must be NS, SOC, SOE, or AS.
return;
}
}
skipws();
if (_curchar != ',') {
return;
}
next_char();
// Parse the native calling convention, must be NS, SOC, SOE, AS
return;
}
}
skipws();
if (_curchar != ',') {
return;
}
next_char();
skipws();
// Parse the ideal save type
return;
}
skipws();
if (_curchar != ',') {
return;
}
next_char();
skipws();
// Parse the encoding value
return;
}
if (_curchar != ',') {
return;
}
next_char();
skipws();
// Parse the concrete name type
// concrete = get_ident();
return;
}
if (_curchar != ')') {
return;
}
next_char();
}
// Check for closing ';'
skipws();
if (_curchar != ';') {
return;
}
next_char(); // move past ';'
// Debug Stuff
}
// Record new register definition.
return;
}
//------------------------------reg_class_parse--------------------------------
// Get register class name
skipws(); // Skip leading whitespace
return;
}
// Debug Stuff
// Collect registers in class
skipws();
if (_curchar == '(') {
next_char(); // Skip '('
skipws();
while (_curchar != ')') {
return;
}
if (!regDef) {
} else {
}
// Check for ',' and position to next token.
skipws();
if (_curchar == ',') {
next_char(); // Skip trailing ','
skipws();
}
}
next_char(); // Skip closing ')'
} else if (_curchar == '%') {
return;
}
return;
}
// Check for terminating ';'
skipws();
if (_curchar != ';') {
return;
}
next_char(); // Skip trailing ';'
// Check RegClass size, must be <= 32 registers in class.
return;
}
//------------------------------alloc_class_parse------------------------------
// Get allocation class name
skipws(); // Skip leading whitespace
return;
}
// Debug Stuff
// Collect registers in class
skipws();
if (_curchar == '(') {
next_char(); // Skip '('
skipws();
while (_curchar != ')') {
return;
}
// Check if name is a RegDef
if (regDef) {
} else {
// name must be a RegDef or a RegClass
return;
}
// Check for ',' and position to next token.
skipws();
if (_curchar == ',') {
next_char(); // Skip trailing ','
skipws();
}
}
next_char(); // Skip closing ')'
}
// Check for terminating ';'
skipws();
if (_curchar != ';') {
return;
}
next_char(); // Skip trailing ';'
return;
}
//------------------------------peep_match_child_parse-------------------------
InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, int &position, int input){
// Walk the match tree,
// Record <parent, position, instruction name, input position>
skipws();
// Left paren signals start of an input, collect with recursive call
if (_curchar == '(') {
++lparen;
next_char();
}
// Right paren signals end of an input, may be more
else if (_curchar == ')') {
++rparen;
next_char(); // move past ')'
} else { // ELSE leave ')' for parent
// if an instruction was not specified for this paren-pair
if( ! inst_seen ) { // record signal entry
++position;
}
// ++input; // TEMPORARY
return inst_seen;
}
}
// if no parens, then check for instruction name
// This instruction is the parent of a sub-tree
if (form) {
// Record the first instruction at this level
}
if (inst) {
++position;
} else {
token);
return inst_seen;
}
}
else {
return NULL;
}
}
else {
return NULL;
}
} // end while
assert( false, "ShouldNotReachHere();");
return NULL;
}
//------------------------------peep_match_parse-------------------------------
// Syntax for a peepmatch rule
//
// peepmatch ( root_instr_name [(instruction subtree)] [,(instruction subtree)]* );
//
skipws();
// Check the structure of the rule
// Check for open paren
if (_curchar != '(') {
return;
}
next_char(); // skip '('
// Construct PeepMatch and parse the peepmatch rule.
return;
}
if( _curchar != ')' ) {
return;
}
next_char(); // skip ')'
// Check for closing semicolon
skipws();
if( _curchar != ';' ) {
return;
}
next_char(); // skip ';'
// Store match into peep, and store peep into instruction
}
//------------------------------peep_constraint_parse--------------------------
// Syntax for a peepconstraint rule
// A parenthesized list of relations between operands in peepmatch subtree
//
// peepconstraint %{
// (instruction_number.operand_name
// relational_op
// instruction_number.operand_name OR register_name
// [, ...] );
//
// // instruction numbers are zero-based using topological order in peepmatch
//
skipws();
// Check the structure of the rule
// Check for open paren
if (_curchar != '(') {
return;
}
else {
next_char(); // Skip '('
}
// Check for a constraint
skipws();
while( _curchar != ')' ) {
// Get information on the left instruction and its operand
// left-instructions's number
// Left-instruction's operand
skipws();
if( _curchar != '.' ) {
return;
}
next_char(); // Skip '.'
skipws();
// Collect relational operator
skipws();
// Get information on the right instruction and its operand
right_inst = get_int();
// Right-instruction's operand
skipws();
if( _curchar != '.' ) {
return;
}
next_char(); // Skip '.'
} else {
}
// Construct the next PeepConstraint
right_inst, right_op );
// And append it to the list for this peephole rule
// Check for another constraint, or end of rule
skipws();
if( _curchar == ',' ) {
next_char(); // Skip ','
skipws();
}
else if( _curchar != ')' ) {
return;
}
} // end while( processing constraints )
next_char(); // Skip ')'
// Check for terminating ';'
skipws();
if (_curchar != ';') {
return;
}
next_char(); // Skip trailing ';'
}
//------------------------------peep_replace_parse-----------------------------
// Syntax for a peepreplace rule
// root instruction name followed by a
// parenthesized list of whitespace separated instruction.operand specifiers
//
// peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
//
//
skipws();
// Check for open paren
if (_curchar != '(') {
return;
}
else {
lparen++;
next_char();
}
// Check for root instruction
return;
}
// Store string representation of rule into replace
skipws();
// Start of root's operand-list
if (_curchar != '(') {
return;
}
else {
lparen++;
next_char();
}
skipws();
// Get the list of operands
while( _curchar != ')' ) {
// Get information on an instruction and its operand
// instructions's number
// Left-instruction's operand
skipws();
if( _curchar != '.' ) {
return;
}
next_char(); // Skip '.'
return;
}
// Record this operand's position in peepmatch
skipws();
}
// Check for the end of operands list
skipws();
next_char(); // Skip ')'
skipws();
// Check for end of peepreplace
if( _curchar != ')' ) {
return;
}
next_char(); // Skip ')'
// Check for closing semicolon
skipws();
if( _curchar != ';' ) {
return;
}
next_char(); // skip ';'
// Store replace into peep
}
//------------------------------pred_parse-------------------------------------
skipws(); // Skip leading whitespace
return NULL;
}
// Debug Stuff
if (_curchar != ';') {
return NULL;
}
next_char(); // Point after the terminator
skipws();
return predicate;
}
//------------------------------ins_encode_parse_block-------------------------
// Parse the block form of ins_encode. See ins_encode_parse for more details
// Create a new encoding name based on the name of the instruction
// definition, which should be unique.
// synthesize the arguments list for the enc_class from the
// arguments to the instruct definition.
}
// Define a MacroAssembler instance for use by the encoding. The
// name is chosen to match the __ idiom used for assembly in other
// parts of hotspot and assumes the existence of the standard
// #define __ _masm.
// Parse the following %{ }% block
// Build an encoding rule which invokes the encoding rule we just
// created, passing all arguments that we received.
}
// Check for duplicate ins_encode sections after parsing the block
// so that parsing can continue and find any other errors.
return;
}
// Set encode class of this instruction.
}
void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name) {
skipws_no_preproc(); // Skip leading whitespace
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
if (_AD._adlocation_debug) {
}
// Collect the parts of the encode description
// (1) strings that are passed through to output
// (2) replacement/substitution variable, preceeded by a '$'
// (1)
// Check if there is a string to pass through to output
// If at the start of a comment, skip past it
} else {
// ELSE advance to the next character, or start of the next line
}
}
// If a string was found, terminate it and record in EncClass
}
// (2)
// If we are at a replacement variable,
// copy it and record in EncClass
if (_curchar == '$') {
// Found replacement Variable
// Add flag to _strings list indicating we should check _rep_vars
skipws();
// Check if this instruct is a MachConstantNode.
// This instruct is a MachConstantNode.
inst.set_is_mach_constant(true);
if (_curchar == '(') {
parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument (only constantaddress and constantoffset)", ec_name);
return;
}
}
// This instruct is a MachConstantNode.
inst.set_is_mach_constant(true);
// If the constant keyword has an argument, parse it.
}
}
} // end while part of format description
next_char(); // Skip '%'
next_char(); // Skip '}'
skipws();
if (_AD._adlocation_debug) {
}
// Debug Stuff
}
//------------------------------ins_encode_parse-------------------------------
// Encode rules have the form
// ins_encode( encode_class_name(parameter_list), ... );
//
// The "encode_class_name" must be defined in the encode section
// The parameter list contains $names that are locals.
//
// Alternatively it can be written like this:
//
// ins_encode %{
// ... // body
// %}
//
// which synthesizes a new encoding class taking the same arguments as
// the InstructForm, and automatically prefixes the definition with:
//
// MacroAssembler masm(&cbuf);\n");
//
// making it more compact to take advantage of the MacroAssembler and
// placing the assembly closer to it's use by instructions.
// Parse encode class name
skipws(); // Skip whitespace
if (_curchar != '(') {
// Check for ins_encode %{ form
next_char(); // Skip '%'
next_char(); // Skip '{'
// Parse the block form of ins_encode
return;
}
return;
}
next_char(); // move past '('
skipws();
// identifier is optional.
while (_curchar != ')') {
return;
}
// Check that encoding is defined in the encode section
if (encode_class == NULL) {
// Like to defer checking these till later...
// parse_err(WARN, "Using an undefined encode class '%s' in 'ins_encode'.\n", ec_name);
}
// Get list for encode method's parameters
// Parse the parameters to this encode method.
skipws();
if ( _curchar == '(' ) {
next_char(); // move past '(' for parameters
// Parse the encode method's parameters
while (_curchar != ')') {
// Found a parameter:
// Check it is a local name, add it to the list, then check for more
// New: allow hex constants as parameters to an encode method.
// New: allow parenthesized expressions as parameters.
// New: allow "primary", "secondary", "tertiary" as parameters.
// New: allow user-defined register name as parameter
return;
}
skipws();
if (_curchar == ',' ) {
// More parameters to come
next_char(); // move past ',' between parameters
skipws(); // Skip to next parameter
}
else if (_curchar == ')') {
// Done with parameter list
}
else {
// Only ',' or ')' are valid after a parameter name
ec_name);
return;
}
} else {
skipws();
// Did not find a parameter
if (_curchar == ',') {
return;
}
if (_curchar != ')') {
return;
}
}
} // WHILE loop collecting parameters
next_char(); // move past ')' at end of parameters
} // done with parameter list for encoding
// Check for ',' or ')' after encoding
skipws(); // move to character after parameters
if ( _curchar == ',' ) {
// Found a ','
next_char(); // move past ',' between encode methods
skipws();
}
else if ( _curchar != ')' ) {
// If not a ',' then only a ')' is allowed
return;
}
// Check for ',' separating parameters
// if ( _curchar != ',' && _curchar != ')' ) {
// parse_err(SYNERR, "expected ',' or ')' after encode method inside ins_encode.\n");
// return NULL;
// }
} // done parsing ins_encode methods and their parameters
if (_curchar != ')') {
return;
}
next_char(); // move past ')'
skipws(); // Skip leading whitespace
if ( _curchar != ';' ) {
return;
}
next_char(); // move past ';'
skipws(); // be friendly to oper_parse()
// Check for duplicate ins_encode sections after parsing the block
// so that parsing can continue and find any other errors.
return;
}
// Debug Stuff
// Set encode class of this instruction.
}
//------------------------------constant_parse---------------------------------
// Parse a constant expression.
// Create a new encoding name based on the name of the instruction
// definition, which should be unique.
// synthesize the arguments list for the enc_class from the
// arguments to the instruct definition.
}
// Parse the following ( ) expression.
// Build an encoding rule which invokes the encoding rule we just
// created, passing all arguments that we received.
}
// Set encode class of this instruction.
}
//------------------------------constant_parse_expression----------------------
skipws();
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
if (_AD._adlocation_debug) {
}
// Start code line.
// Parse everything in ( ) expression.
next_char(); // Skip '('
// Collect the parts of the constant expression.
// (1) strings that are passed through to output
// (2) replacement/substitution variable, preceeded by a '$'
while (parens_depth > 0) {
if (_curchar == '(') {
parens_depth++;
next_char();
}
else if (_curchar == ')') {
parens_depth--;
if (parens_depth > 0)
next_char();
}
else {
// (1)
// Check if there is a string to pass through to output
next_char();
}
// If a string was found, terminate it and record in EncClass
}
// (2)
// If we are at a replacement variable, copy it and record in EncClass.
if (_curchar == '$') {
// Found replacement Variable
}
}
}
// Finish code line.
if (_AD._adlocation_debug) {
}
// Debug Stuff
}
//------------------------------size_parse-----------------------------------
// Parse a 'size(<expr>)' attribute which specifies the size of the
// emitted instructions in bytes. <expr> can be a C++ expression,
// e.g. a constant.
// Get value of the instruction's size
skipws();
// Parse size
if (sizeOfInstr == NULL) {
return NULL;
}
skipws();
// Check for terminator
if (_curchar != ';') {
return NULL;
}
next_char(); // Advance past the ';'
skipws(); // necessary for instr_parse()
// Debug Stuff
if (sizeOfInstr != NULL) {
}
}
return sizeOfInstr;
}
//------------------------------opcode_parse-----------------------------------
// Get value of the instruction's opcode
skipws();
return NULL;
}
next_char(); // skip open paren
skipws();
if (_curchar != ')') {
// Parse primary, secondary, and tertiary opcodes, if provided.
return NULL;
}
skipws();
if (_curchar == ',') {
next_char();
skipws();
// Parse secondary opcode
return NULL;
}
skipws();
if (_curchar == ',') {
next_char();
skipws();
// Parse tertiary opcode
return NULL;
}
skipws();
}
}
skipws();
if (_curchar != ')') {
return NULL;
}
}
next_char(); // Skip ')'
skipws();
// Check for terminator
if (_curchar != ';') {
return NULL;
}
next_char(); // Advance past the ';'
skipws(); // necessary for instr_parse()
// Debug Stuff
}
// Generate new object and return
return opcode;
}
//------------------------------interface_parse--------------------------------
// Get interface class name
skipws(); // Skip whitespace
if (_curchar != '(') {
return NULL;
}
next_char(); // move past '('
skipws();
iface_name = get_ident();
if (iface_name == NULL) {
return NULL;
}
skipws();
if (_curchar != ')') {
return NULL;
}
next_char(); // move past ')'
// Get details of the interface,
// for the type of interface indicated by iface_name.
skipws();
if ( _curchar != ';' ) {
inter = mem_interface_parse();
}
}
// The parse routines consume the "%}"
// Check for probable extra ';' after defining block.
if ( _curchar == ';' ) {
next_char(); // Skip ';'
return NULL;
}
} else {
next_char(); // move past ';'
// Create appropriate interface object
inter = new RegInterface();
}
inter = new ConstInterface();
}
}
skipws(); // be friendly to oper_parse()
// Debug Stuff
// Create appropriate interface object and return.
return inter;
}
//------------------------------mem_interface_parse----------------------------
// Fields for MemInterface
if (_curchar != '%') {
return NULL;
}
next_char(); // Skip '%'
if (_curchar != '{') {
return NULL;
}
next_char(); // Skip '{'
skipws();
do {
return NULL;
}
}
}
}
}
else {
return NULL;
}
} while( _curchar != '%' );
next_char(); // Skip '%'
if ( _curchar != '}' ) {
return NULL;
}
next_char(); // Skip '}'
// Construct desired object and return
return inter;
}
//------------------------------cond_interface_parse---------------------------
char *equal;
char *not_equal;
char *less;
char *greater_equal;
char *less_equal;
char *greater;
if (_curchar != '%') {
return NULL;
}
next_char(); // Skip '%'
if (_curchar != '{') {
return NULL;
}
next_char(); // Skip '{'
skipws();
do {
return NULL;
}
}
}
}
}
}
}
else {
return NULL;
}
} while( _curchar != '%' );
next_char(); // Skip '%'
if ( _curchar != '}' ) {
return NULL;
}
next_char(); // Skip '}'
// Construct desired object and return
return inter;
}
//------------------------------interface_field_parse--------------------------
// Get interface field
skipws(); // Skip whitespace
if (_curchar != '(') {
return NULL;
}
next_char(); // move past '('
skipws();
return NULL;
}
if (iface_field == NULL) {
return NULL;
}
skipws();
next_char();
skipws();
if (_curchar != '"') {
return NULL;
}
next_char();
next_char();
}
if (_curchar != '"') {
return NULL;
}
// If a string was found, terminate it and record in FormatRule
}
next_char();
skipws();
}
if (_curchar != ')') {
return NULL;
}
next_char(); // move past ')'
skipws();
if ( _curchar != ';' ) {
return NULL;
}
next_char(); // move past ';'
skipws(); // be friendly to interface_parse()
return iface_field;
}
//------------------------------match_parse------------------------------------
// Parse the match rule tree
// Either there is a block with a constructor, or a ';' here
skipws(); // Skip whitespace
next_char(); // Move past the ';', replaced with '\0'
}
"Missing ';' or invalid '%%{' and '%%}' constructor\n");
return NULL; // No MatchRule to return
}
// Build new MatchRule object
skipws(); // Skip any trailing whitespace
return match; // Return MatchRule object
}
//------------------------------format_parse-----------------------------------
// Without expression form, MUST have a code block;
skipws(); // Skip whitespace
next_char(); // Move past the ';', replaced with '\0'
}
next_char(); // Move past the '%'
next_char(); // Move past the '{'
skipws();
if (_curchar == '$') {
char* ident = get_rep_var_ident();
return NULL;
}
// Check for the opening '"' inside the format description
if ( _curchar == '"' ) {
next_char(); // Move past the initial '"'
}
// Collect the parts of the format description
// (1) strings that are passed through to tty->print
// (2) replacement/substitution variable, preceeded by a '$'
// (3) multi-token ANSIY C style strings
while ( true ) {
if ( _curchar != '"' ) {
return NULL;
}
}
// (1)
// Check if there is a string to pass through to output
if (_curchar == '\\') {
next_char(); // superquote
// hack to avoid % escapes and warnings about undefined \ escapes
}
next_char();
}
// If a string was found, terminate it and record in FormatRule
}
// (2)
// If we are at a replacement variable,
// copy it and record in FormatRule
if ( _curchar == '$' ) {
next_char(); // Move past the '$'
// Add flag to _strings list indicating we should check _rep_vars
}
// (3)
// Allow very long strings to be broken up,
// using the ANSI C syntax "foo\n" <newline> "bar"
if ( _curchar == '"') {
next_char(); // Move past the '"'
skipws(); // Skip white space before next string token
if ( _curchar != '"') {
break;
} else {
// Found one. Skip both " and the whitespace in between.
next_char();
}
}
} // end while part of format description
// Check for closing '"' and '%}' in format description
skipws(); // Move to closing '%}'
if ( _curchar != '%' ) {
return NULL;
}
} // Done with format description inside
skipws();
// Past format description, at '%'
return NULL;
}
next_char(); // Move past the '%'
next_char(); // Move past the '}'
}
else { // parameter list alone must terminate with a ';'
return NULL;
}
// Debug Stuff
skipws();
return format;
}
//------------------------------template_parse-----------------------------------
skipws();
// (1)
// Check if there is a string to pass through to output
{
// If at the start of a comment, skip past it
} else {
// ELSE advance to the next character, or start of the next line
}
}
// If a string was found, terminate it and record in EncClass
// Add flag to _strings list indicating we should check _rep_vars
}
}
// (2)
// If we are at a replacement variable,
// copy it and record in EncClass
if ( _curchar == '$' ) {
// Found replacement Variable
// switch to normal format parsing
next_char();
next_char();
skipws();
// Check for the opening '"' inside the format description
if ( _curchar == '"' ) {
next_char(); // Move past the initial '"'
}
// Collect the parts of the format description
// (1) strings that are passed through to tty->print
// (2) replacement/substitution variable, preceeded by a '$'
// (3) multi-token ANSIY C style strings
while ( true ) {
return NULL;
}
// (1)
// Check if there is a string to pass through to output
next_char();
}
// If a string was found, terminate it and record in FormatRule
}
// (2)
// If we are at a replacement variable,
// copy it and record in FormatRule
if ( _curchar == '$' ) {
next_char(); // Move past the '$'
// Add flag to _strings list indicating we should check _rep_vars
}
// (3)
// Allow very long strings to be broken up,
// using the ANSI C syntax "foo\n" <newline> "bar"
if ( _curchar == '"') {
next_char(); // Move past the '"'
skipws(); // Skip white space before next string token
if ( _curchar != '"') {
break;
} else {
// Found one. Skip both " and the whitespace in between.
next_char();
}
}
} // end while part of format description
}
} else {
// Add flag to _strings list indicating we should check _rep_vars
// Add flag to _strings list indicating we should check _rep_vars
}
} // end while part of format description
}
skipws();
// Past format description, at '%'
return NULL;
}
next_char(); // Move past the '%'
next_char(); // Move past the '}'
// Debug Stuff
skipws();
return format;
}
//------------------------------effect_parse-----------------------------------
skipws(); // Skip whitespace
if (_curchar != '(') {
return;
}
// Get list of effect-operand pairs and insert into dictionary
// Debug Stuff
if (_curchar != ';') {
}
next_char(); // Skip ';'
}
//------------------------------expand_parse-----------------------------------
char *ident, *ident2;
// Expand is a block containing an ordered list of instructions, each of
// which has an ordered list of operands.
// Check for block delimiter
skipws(); // Skip leading whitespace
if ((_curchar != '%')
return(NULL);
}
next_char(); // Maintain the invariant
do {
ident = get_ident(); // Grab next identifier
if (ident == NULL) {
continue;
} // Check that you have a valid instruction
// This is a new operand
continue;
}
// Throw the operand on the _newopers list
skipws();
if (ident == NULL) {
continue;
}
// Add new operand to LocalNames
// Grab any constructor code and save as a string
char *c = NULL;
skipws();
c = find_cpp_block("Operand Constructor");
if (c == NULL) {
continue;
}
// Add constructor to _newopconst Dict
}
continue;
}
else next_char(); // Skip the ;
skipws();
}
else {
// Add instruction to list
instr_and_operands = new NameAndList(ident);
// Grab operands, build nameList of them, and then put into dictionary
skipws();
continue;
}
do {
next_char(); // skip open paren & comma characters
skipws();
if (_curchar == ')') break;
skipws();
continue;
} // Check that you have a valid operand
if (!form2) {
continue;
}
continue;
} // Add operand to list
} while(_curchar == ',');
if (_curchar != ')') {
continue;
}
next_char();
if (_curchar != ';') {
continue;
}
next_char();
// Record both instruction name and its operand list
skipws();
}
} while(_curchar != '%');
next_char();
if (_curchar != '}') {
return(NULL);
}
next_char();
// Debug Stuff
skipws();
return (exp);
}
//------------------------------rewrite_parse----------------------------------
// This feature targeted for second generation description language.
skipws(); // Skip whitespace
// Get parameters for rewrite
return NULL;
}
// Debug Stuff
// For now, grab entire block;
skipws();
return NULL;
}
// Debug Stuff
skipws();
}
//------------------------------attr_parse-------------------------------------
skipws(); // Skip leading whitespace
return NULL;
}
// Debug Stuff
if (_curchar != ';') {
return NULL;
}
next_char(); // Point after the terminator
skipws();
return attrib;
}
//------------------------------matchNode_parse--------------------------------
MatchNode *ADLParser::matchNode_parse(FormDict &operands, int &depth, int &numleaves, bool atroot) {
// Count depth of parenthesis nesting for both left and right children
// MatchNode objects for left, right, and root of subtree.
// Match expression starts with a '('
if (cur_char() != '(')
return NULL;
next_char(); // advance past '('
// Parse the opcode
return NULL;
}
// Take note if we see one of a few special operations - those that are
// treated differently on different architectures in the sense that on
// one architecture there is a match rule and on another there isn't (so
// a call will eventually be generated).
_AD.has_match_rule(i, true);
}
}
// Lookup the root value in the operands dict to perform substitution
// If this token is an entry in the local names table, record its type
if (!opcForm->ideal_only()) {
}
// Otherwise it is an ideal type, and so, has no local name
}
// Parse the operands
skipws();
if (cur_char() != ')') {
// Parse the left child
else
skipws();
if (cur_char() != ')' ) {
else
}
}
// Check for required ')'
skipws();
if (cur_char() != ')') {
return NULL;
}
next_char(); // skip the ')'
// If not the root, reduce this subtree to an internal operand
if (!atroot) {
}
// depth is greater of left and right paths.
return mroot;
}
//------------------------------matchChild_parse-------------------------------
MatchNode *ADLParser::matchChild_parse(FormDict &operands, int &parens, int &numleaves, bool atroot) {
++parens;
}
else { // child is an operand
} else {
return NULL;
}
}
++numleaves;
}
return child;
}
// ******************** Private Utility Functions *************************
next_char();
if (_curchar != '{') {
return NULL;
}
next_char(); // Skip block delimiter
skipws_no_preproc(); // Skip leading whitespace
} // Grab string
if (_curchar == '\0') {
return NULL;
}
// Prepend location descriptor, for debugging.
if (_AD._adlocation_debug) {
}
}
return cppBlock;
}
// Move to the closing token of the expression we are currently at,
// as defined by stop_chars. Match parens and quotes.
int paren = 0;
paren++; // Bump the parenthesis counter
next_char(); // maintain the invariant
}
if (paren == 0) {
// Paren underflow: We didn't encounter the required stop-char.
stop_chars, desc);
return NULL;
}
paren--; // Drop the parenthesis counter
next_char(); // Maintain the invariant
}
while (true) {
next_char();
return NULL;
}
}
}
// Make sure we do not stray into the next ADLC-level form.
return NULL;
}
else if (_curchar == '\0') {
return NULL;
}
else {
// Always walk over whitespace, comments, preprocessor directives, etc.
skipws();
// If the parser declined to make progress on whitespace,
// skip the next character, which is therefore NOT whitespace.
if (pre_skip_ptr == _ptr) {
next_char();
}
}
}
return expr;
}
// Helper function around get_expr
// Sets _curchar to '(' so that get_paren_expr will search for a matching ')'
return NULL;
next_char(); // Skip the required initial paren.
if (_curchar == ')')
next_char(); // Skip required final paren.
int junk = 0;
// Prepend location descriptor, for debugging.
}
return token2;
}
//------------------------------get_ident_common-------------------------------
// Looks for an identifier in the buffer, and turns it into a null terminated
// string(still inside the file buffer). Returns a pointer to the string or
// NULL if some other token is found instead.
register char c;
return NULL;
end--; // unwind end by one to prepare for loop
do {
end++; // Increment end pointer
c = *end; // Grab character to test
} while ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))
|| ((c >= '0') && (c <= '9'))
|| ((c == '_')) || ((c == ':')) || ((c == '#')) );
// It can occur that `start' contains the rest of the input file.
// In this case the output should be truncated.
} else {
}
}
else {
_curchar = c; // Save the first character of next token
}
// Make sure we do not try to use #defined identifiers. If start is
// NULL an error was already reported.
// implement up to 2 levels of #define
}
}
}
}
return start; // Pointer to token in filebuf
}
//------------------------------get_ident_dup----------------------------------
// Looks for an identifier in the buffer, and returns a duplicate
// or NULL if some other token is found instead.
char *ident = get_ident();
// Duplicate an identifier before returning and restore string.
if( ident != NULL ) {
ident = strdup(ident); // Copy the string
}
return ident;
}
//----------------------get_ident_or_literal_constant--------------------------
// Looks for an identifier in the buffer, or a parenthesized expression.
skipws();
if (_curchar == '(') {
// Grab a constant expression.
if (param[0] != '(') {
}
"expr must be recognizable as a constant");
} else {
}
return param;
}
//------------------------------get_rep_var_ident-----------------------------
// Do NOT duplicate,
// Leave nil terminator in buffer
// Preserve initial '$'(s) in string
// Remember starting point
// Check for replacement variable indicator '$' and pass if present
if ( _curchar == '$' ) {
next_char();
}
// Check for a subfield indicator, a second '$', and pass if present
if ( _curchar == '$' ) {
next_char();
}
// Check for a control indicator, a third '$':
if ( _curchar == '$' ) {
next_char();
}
// Check for more than three '$'s in sequence, SYNERR
if( _curchar == '$' ) {
next_char();
return NULL;
}
// Nil terminate the variable name following the '$'
"Missing identifier after replacement variable indicator '$'");
return rep_var;
}
//------------------------------get_rep_var_ident_dup-------------------------
// Return the next replacement variable identifier, skipping first '$'
// given a pointer into a line of the buffer.
// Null terminates string, still inside the file buffer,
// Returns a pointer to a copy of the string, or NULL on failure
next_char(); // Move past the '$'
// Check for a subfield indicator, a second '$':
if ( _curchar == '$' ) {
next_char();
}
// Check for a control indicator, a third '$':
if ( _curchar == '$' ) {
next_char();
}
// Check for more than three '$'s in sequence, SYNERR
if( _curchar == '$' ) {
next_char();
return NULL;
}
// Nil terminate the variable name following the '$'
"Missing identifier after replacement variable indicator '$'");
return rep_var;
}
//------------------------------get_unique_ident------------------------------
// Looks for an identifier in the buffer, terminates it with a NULL,
// and checks that it is unique
char* ident = get_ident();
if (ident == NULL) {
}
else {
ident = NULL;
}
}
return ident;
}
//------------------------------get_int----------------------------------------
// Looks for a character string integer in the buffer, and turns it into an int
// invokes a parse_err if the next token is not an integer.
// This routine does not leave the integer null-terminated.
register char c;
return 0;
skipws(); // Skip whitespace before identifier
c = *end; // Grab character to test
while ((c >= '0') && (c <= '9')
end++; // Increment end pointer
c = *end; // Grab character to test
}
result = 0;
}
else {
_curchar = c; // Save the first character of next token
}
// Reset _ptr to next char after token
return result; // integer
}
//------------------------------get_relation_dup------------------------------
// Looks for a relational operator in the buffer
// invokes a parse_err if the next token is not a relation
// This routine creates a duplicate of the string in the buffer.
return NULL;
skipws(); // Skip whitespace before relation
next_char();
if( (second == '=') ) {
next_char();
} else {
}
} else {
}
return result;
}
//------------------------------get_oplist-------------------------------------
// Looks for identifier pairs where first must be the name of an operand, and
// second must be a name unique in the scope of this instruction. Stores the
// names with a pointer to the OpClassForm of their type in a local name table.
char *ident = NULL;
do {
next_char(); // skip open paren & comma characters
skipws();
if (_curchar == ')') break;
// Get operand type, and check it against global name table
ident = get_ident();
if (ident == NULL) {
return;
}
else {
return;
}
// Check for valid operand type
return;
}
}
// Debugging Stuff
// Get name of operand and add it to local name table
return;
}
// Parameter names must not be global names.
if( _globalNames[ident] != NULL ) {
return;
}
parameters.addName(ident);
// Debugging Stuff
skipws();
} while(_curchar == ',');
else {
next_char(); // set current character position past the close paren
}
}
//------------------------------get_effectlist---------------------------------
// Looks for identifier pairs where first must be the name of a pre-defined,
// effect, and the second must be the name of an operand defined in the
// operand list of this instruction. Stores the names with a pointer to the
// effect form in a local effects table.
char *ident;
do {
next_char(); // skip open paren & comma characters
skipws();
if (_curchar == ')') break;
// Get effect type, and check it against global name table
ident = get_ident();
if (ident == NULL) {
return;
}
else {
// Check for valid effect type
return;
}
else {
return;
}
}
}
// Debugging Stuff
skipws();
has_call = true;
} else {
// Get name of operand and check that it is in the local name table
return;
}
} else {
}
return;
}
// Add the pair to the effects table
// Debugging Stuff
}
skipws();
} while(_curchar == ',');
else {
next_char(); // set current character position past the close paren
}
}
//-------------------------------preproc_line----------------------------------
// A "#line" keyword has been seen, so parse the rest of the line.
if (_curchar == '"') {
next_char(); // Move past the initial '"'
while (true) {
if (_curchar == '\n') {
return;
}
if (_curchar == '"') {
next_char();
break;
}
next_char();
}
}
}
//------------------------------preproc_define---------------------------------
// A "#define" keyword has been seen, so parse the rest of the line.
// only #define x y is supported for now
if (_curchar != '\n') {
}
}
//------------------------------preproc_undef----------------------------------
// An "#undef" keyword has been seen, so parse the rest of the line.
}
//------------------------------parse_err--------------------------------------
// Issue a parser error message, and skip to the end of the current line
if (flag == 1)
else if (flag == 2)
else
_curchar = '\n';
if (flag == 1) {
}
}
//---------------------------ensure_start_of_line------------------------------
// A preprocessor directive has been encountered. Be sure it has fallen at
// the beginning of a line, or else report an error.
"Must be able to find which line we are in" );
if (*s > ' ') {
break;
}
}
}
//---------------------------ensure_end_of_line--------------------------------
// A preprocessor directive has been parsed. Be sure there is no trailing
// garbage at the end of this line. Set the scan point to the beginning of
// the next line.
} else {
}
}
//---------------------------handle_preproc------------------------------------
// The '#' character introducing a preprocessor directive has been found.
// Parse the whole directive name (e.g., #define, #endif) and take appropriate
// action. If we are in an "untaken" span of text, simply keep track of
// #ifdef nesting structure, so we can find out when to start taking text
// again. (In this state, we "sort of support" C's #if directives, enough
// to disregard their associated #else and #endif lines.) If we are in a
// "taken" span of text, there are two cases: "#define" and "#undef"
// directives are preserved and passed up to the caller, which eventually
// passes control to the top-level parser loop, which handles #define and
// #undef directly. (This prevents these directives from occurring in
// arbitrary positions in the AD file--we require better structure than C.)
// In the other case, and #ifdef, #ifndef, #else, or #endif is silently
// processed as whitespace, with the "taken" state of the text correctly
// updated. This routine returns "false" exactly in the case of a "taken"
// #define or #undef, which tells the caller that a preprocessor token
// has appeared which must be handled explicitly by the parse loop.
next_char();
if (ident == NULL) {
} else if (!strcmp(ident, "ifdef") ||
!strcmp(ident, "ifndef")) {
// Test the identifier only if we are already in taken code:
} else if (!strcmp(ident, "if")) {
if (preproc_taken())
next_line();
// Intelligently skip this nested C preprocessor directive:
begin_if_def(true);
} else if (!strcmp(ident, "else")) {
} else if (!strcmp(ident, "endif")) {
end_if_def();
} else if (preproc_taken()) {
// pass this token up to the main parser as "#define" or "#undef"
_ptr = start_ident;
if( _curchar != '#' ) {
}
return false;
}
return true;
}
//---------------------------skipws_common-------------------------------------
// Skip whitespace, including comments and newlines, while keeping an accurate
// line count.
// Maybe handle certain preprocessor constructs: #ifdef, #ifndef, #else, #endif
if (*_ptr == '\0') {
// Check for string terminator
if (_curchar > ' ') return;
if (_curchar == '\n') {
if (!do_preproc) return; // let caller handle the newline
next_line();
}
else if (_curchar == '#' ||
}
}
if (!do_preproc) break; // let caller handle the newline
next_line();
}
do {
next_line(); // skip newlines within comments
break;
}
}
}
// Note that this calls skipws_common(false) recursively!
if (!preproc_handled) {
if (preproc_taken()) {
return; // short circuit
}
++_ptr; // skip the preprocessor character
}
break;
}
// skip untaken quoted string
while (true) {
++_ptr;
break;
}
}
}
}
}
//---------------------------cur_char-----------------------------------------
return (_curchar);
}
//---------------------------next_char-----------------------------------------
// if ( _curchar == '\n' ) {
// next_line();
// }
}
//---------------------------next_char_or_line---------------------------------
if ( _curchar != '\n' ) {
} else {
next_line();
}
}
//---------------------------next_line-----------------------------------------
_curchar = ' ';
}
//------------------------get_line_string--------------------------------------
// Prepended location descriptor, for debugging.
// Must return a malloced string (that can be freed if desired).
return location;
}
//-------------------------is_literal_constant---------------------------------
if (param[0] == 0) return false; // null string
// Make sure it's a hex constant.
int i = 2;
do {
++i;
} while( *(param+i) != 0 );
return true;
}
return false;
}
//---------------------------is_hex_digit--------------------------------------
}
//---------------------------is_int_token--------------------------------------
int ndigit = 0;
return false;
}
return true;
}
while (cp[0]) {
if (cp[0] <= ' ') {
++cp;
} else if (cp[0] == '#') {
++cp;
} else {
break;
}
}
return cp;
}
//-----------------------equivalent_expressions--------------------------------
return true;
return false;
if (!in_quote) {
continue;
}
}
// match one non-space char
// watch for quotes
if (!cp1[0]) break;
}
in_quote = '\0';
}
}
}
//-------------------------------trim------------------------------------------
*end = '\0';
}