6754519: don't emit flag fixup for NaN when condition being tested doesn't need it

Reviewed-by: kvn, rasbold
This commit is contained in:
Tom Rodriguez 2008-10-28 09:31:30 -07:00
parent f3a403d0d4
commit 429a95440a
16 changed files with 1125 additions and 253 deletions

View file

@ -33,7 +33,6 @@ ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc)
_globalNames(archDesc.globalNames()) {
_AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file
_AD._warnings = 0; // No warnings either
_linenum = 0; // Will increment to first line
_curline = _ptr = NULL; // No pointers into buffer yet
_preproc_depth = 0;
@ -76,7 +75,7 @@ ADLParser::~ADLParser() {
}
if (!_AD._quiet_mode)
fprintf(stderr,"-----------------------------------------------------------------------------\n");
_AD._TotalLines += _linenum-1; // -1 for overshoot in "nextline" routine
_AD._TotalLines += linenum()-1; // -1 for overshoot in "nextline" routine
// Write out information we have stored
// // UNIXism == fsync(stderr);
@ -148,7 +147,7 @@ void ADLParser::instr_parse(void) {
if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL )
return;
instr = new InstructForm(ident); // Create new instruction form
instr->_linenum = _linenum;
instr->_linenum = linenum();
_globalNames.Insert(ident, instr); // Add name to the name table
// Debugging Stuff
if (_AD._adl_debug > 1)
@ -404,7 +403,7 @@ void ADLParser::oper_parse(void) {
if( (ident = get_unique_ident(_globalNames,"operand")) == NULL )
return;
oper = new OperandForm(ident); // Create new operand form
oper->_linenum = _linenum;
oper->_linenum = linenum();
_globalNames.Insert(ident, oper); // Add name to the name table
// Debugging Stuff
@ -774,7 +773,7 @@ void ADLParser::reg_parse(void) {
// Create the RegisterForm for the architecture description.
RegisterForm *regBlock = new RegisterForm(); // Build new Source object
regBlock->_linenum = _linenum;
regBlock->_linenum = linenum();
_AD.addForm(regBlock);
skipws(); // Skip leading whitespace
@ -847,7 +846,7 @@ void ADLParser::enc_class_parse(void) {
}
EncClass *encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = _linenum;
encoding->_linenum = linenum();
skipws(); // Skip leading whitespace
// Check for optional parameter list
@ -905,7 +904,7 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
if (_AD._adlocation_debug) {
const char* file = _AD._ADL_file._name;
int line = _linenum;
int line = linenum();
char* location = (char *)malloc(strlen(file) + 100);
sprintf(location, "#line %d \"%s\"\n", line, file);
encoding->add_code(location);
@ -2776,7 +2775,7 @@ InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
EncClass *encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = _linenum;
encoding->_linenum = linenum();
// synthesize the arguments list for the enc_class from the
// arguments to the instruct definition.
@ -2852,7 +2851,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
skipws();
InsEncode *encrule = new InsEncode(); // Encode class for instruction
encrule->_linenum = _linenum;
encrule->_linenum = linenum();
char *ec_name = NULL; // String representation of encode rule
// identifier is optional.
while (_curchar != ')') {
@ -3203,6 +3202,12 @@ Interface *ADLParser::cond_interface_parse(void) {
char *greater_equal;
char *less_equal;
char *greater;
const char *equal_format = "eq";
const char *not_equal_format = "ne";
const char *less_format = "lt";
const char *greater_equal_format = "ge";
const char *less_equal_format = "le";
const char *greater_format = "gt";
if (_curchar != '%') {
parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
@ -3222,22 +3227,22 @@ Interface *ADLParser::cond_interface_parse(void) {
return NULL;
}
if ( strcmp(field,"equal") == 0 ) {
equal = interface_field_parse();
equal = interface_field_parse(&equal_format);
}
else if ( strcmp(field,"not_equal") == 0 ) {
not_equal = interface_field_parse();
not_equal = interface_field_parse(&not_equal_format);
}
else if ( strcmp(field,"less") == 0 ) {
less = interface_field_parse();
less = interface_field_parse(&less_format);
}
else if ( strcmp(field,"greater_equal") == 0 ) {
greater_equal = interface_field_parse();
greater_equal = interface_field_parse(&greater_equal_format);
}
else if ( strcmp(field,"less_equal") == 0 ) {
less_equal = interface_field_parse();
less_equal = interface_field_parse(&less_equal_format);
}
else if ( strcmp(field,"greater") == 0 ) {
greater = interface_field_parse();
greater = interface_field_parse(&greater_format);
}
else {
parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n");
@ -3252,14 +3257,18 @@ Interface *ADLParser::cond_interface_parse(void) {
next_char(); // Skip '}'
// Construct desired object and return
Interface *inter = new CondInterface(equal, not_equal, less, greater_equal,
less_equal, greater);
Interface *inter = new CondInterface(equal, equal_format,
not_equal, not_equal_format,
less, less_format,
greater_equal, greater_equal_format,
less_equal, less_equal_format,
greater, greater_format);
return inter;
}
//------------------------------interface_field_parse--------------------------
char *ADLParser::interface_field_parse(void) {
char *ADLParser::interface_field_parse(const char ** format) {
char *iface_field = NULL;
// Get interface field
@ -3280,6 +3289,32 @@ char *ADLParser::interface_field_parse(void) {
return NULL;
}
skipws();
if (format != NULL && _curchar == ',') {
next_char();
skipws();
if (_curchar != '"') {
parse_err(SYNERR, "Missing '\"' in field format .\n");
return NULL;
}
next_char();
char *start = _ptr; // Record start of the next string
while ((_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
if (_curchar == '\\') next_char(); // superquote
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
next_char();
}
if (_curchar != '"') {
parse_err(SYNERR, "Missing '\"' at end of field format .\n");
return NULL;
}
// If a string was found, terminate it and record in FormatRule
if ( start != _ptr ) {
*_ptr = '\0'; // Terminate the string
*format = start;
}
next_char();
skipws();
}
if (_curchar != ')') {
parse_err(SYNERR, "Missing ')' after interface field.\n");
return NULL;
@ -3342,6 +3377,12 @@ FormatRule* ADLParser::format_parse(void) {
next_char(); // Move past the '{'
skipws();
if (_curchar == '$') {
char* ident = get_rep_var_ident();
if (strcmp(ident, "$$template") == 0) return template_parse();
parse_err(SYNERR, "Unknown \"%s\" directive in format", ident);
return NULL;
}
// Check for the opening '"' inside the format description
if ( _curchar == '"' ) {
next_char(); // Move past the initial '"'
@ -3433,6 +3474,131 @@ FormatRule* ADLParser::format_parse(void) {
}
//------------------------------template_parse-----------------------------------
FormatRule* ADLParser::template_parse(void) {
char *desc = NULL;
FormatRule *format = (new FormatRule(desc));
skipws();
while ( (_curchar != '%') && (*(_ptr+1) != '}') ) {
// (1)
// Check if there is a string to pass through to output
char *start = _ptr; // Record start of the next string
while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
// If at the start of a comment, skip past it
if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
skipws_no_preproc();
} else {
// ELSE advance to the next character, or start of the next line
next_char_or_line();
}
}
// If a string was found, terminate it and record in EncClass
if ( start != _ptr ) {
*_ptr = '\0'; // Terminate the string
// Add flag to _strings list indicating we should check _rep_vars
format->_strings.addName(NameList::_signal2);
format->_strings.addName(start);
}
// (2)
// If we are at a replacement variable,
// copy it and record in EncClass
if ( _curchar == '$' ) {
// Found replacement Variable
char *rep_var = get_rep_var_ident_dup();
if (strcmp(rep_var, "$emit") == 0) {
// 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 '"'
if( _curchar == '"' ) { // Handle empty format string case
*_ptr = '\0'; // Terminate empty string
format->_strings.addName(_ptr);
}
// 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 == '%' || _curchar == '\n' ) {
parse_err(SYNERR, "missing '\"' at end of format block");
return NULL;
}
// (1)
// Check if there is a string to pass through to output
char *start = _ptr; // Record start of the next string
while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
if (_curchar == '\\') next_char(); // superquote
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
next_char();
}
// If a string was found, terminate it and record in FormatRule
if ( start != _ptr ) {
*_ptr = '\0'; // Terminate the string
format->_strings.addName(start);
}
// (2)
// If we are at a replacement variable,
// copy it and record in FormatRule
if ( _curchar == '$' ) {
next_char(); // Move past the '$'
char* rep_var = get_ident(); // Nil terminate the variable name
rep_var = strdup(rep_var);// Copy the string
*_ptr = _curchar; // and replace Nil with original character
format->_rep_vars.addName(rep_var);
// Add flag to _strings list indicating we should check _rep_vars
format->_strings.addName(NameList::_signal);
}
// (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
format->_rep_vars.addName(rep_var);
// Add flag to _strings list indicating we should check _rep_vars
format->_strings.addName(NameList::_signal3);
}
} // end while part of format description
}
skipws();
// Past format description, at '%'
if ( _curchar != '%' || *(_ptr+1) != '}' ) {
parse_err(SYNERR, "missing '%}' at end of format block");
return NULL;
}
next_char(); // Move past the '%'
next_char(); // Move past the '}'
// Debug Stuff
if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc);
skipws();
return format;
}
//------------------------------effect_parse-----------------------------------
void ADLParser::effect_parse(InstructForm *instr) {
char* desc = NULL;
@ -3777,7 +3943,7 @@ char* ADLParser::find_cpp_block(const char* description) {
skipws_no_preproc(); // Skip leading whitespace
cppBlock = _ptr; // Point to start of expression
const char* file = _AD._ADL_file._name;
int line = _linenum;
int line = linenum();
next = _ptr + 1;
while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
next_char_or_line();
@ -4297,11 +4463,11 @@ void ADLParser::parse_err(int flag, const char *fmt, ...) {
va_start(args, fmt);
if (flag == 1)
_AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
_AD._syntax_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
else if (flag == 2)
_AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
_AD._semantic_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
else
_AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args);
_AD._warnings += _AD.emit_msg(0, flag, linenum(), fmt, args);
int error_char = _curchar;
char* error_ptr = _ptr+1;
@ -4515,7 +4681,7 @@ void ADLParser::next_char_or_line() {
//---------------------------next_line-----------------------------------------
void ADLParser::next_line() {
_curline = _buf.get_line(); _linenum++;
_curline = _buf.get_line();
}
//-------------------------is_literal_constant---------------------------------