Mercurial > hg > truffle
diff src/share/vm/adlc/adlparse.cpp @ 475:284d0af00d53
6771309: debugging AD files is difficult without #line directives in generated code
Summary: more and better #line and #define directives in the generated code; ADLC itself accepts #line directives
Reviewed-by: never, kvn
author | jrose |
---|---|
date | Tue, 09 Dec 2008 12:41:26 -0800 |
parents | 4d9884b01ba6 |
children | 569b3b226089 |
line wrap: on
line diff
--- a/src/share/vm/adlc/adlparse.cpp Mon Dec 08 17:15:02 2008 -0800 +++ b/src/share/vm/adlc/adlparse.cpp Tue Dec 09 12:41:26 2008 -0800 @@ -108,6 +108,7 @@ else if (!strcmp(ident, "pipeline")) pipe_parse(); else if (!strcmp(ident, "definitions")) definitions_parse(); else if (!strcmp(ident, "peephole")) peep_parse(); + else if (!strcmp(ident, "#line")) preproc_line(); else if (!strcmp(ident, "#define")) preproc_define(); else if (!strcmp(ident, "#undef")) preproc_undef(); else { @@ -786,9 +787,11 @@ parse_err(SYNERR, "missing identifier inside register block.\n"); return; } - if (strcmp(token,"reg_def")==0) { reg_def_parse(); } - if (strcmp(token,"reg_class")==0) { reg_class_parse(); } - if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); } + if (strcmp(token,"reg_def")==0) { reg_def_parse(); } + else if (strcmp(token,"reg_class")==0) { reg_class_parse(); } + else if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); } + else if (strcmp(token,"#define")==0) { preproc_define(); } + else { parse_err(SYNERR, "bad token %s inside register block.\n", token); break; } skipws(); } } @@ -903,11 +906,7 @@ skipws_no_preproc(); // Skip leading whitespace // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block if (_AD._adlocation_debug) { - const char* file = _AD._ADL_file._name; - int line = linenum(); - char* location = (char *)malloc(strlen(file) + 100); - sprintf(location, "#line %d \"%s\"\n", line, file); - encoding->add_code(location); + encoding->add_code(get_line_string()); } // Collect the parts of the encode description @@ -948,6 +947,10 @@ skipws(); + if (_AD._adlocation_debug) { + encoding->add_code(end_line_marker()); + } + // Debug Stuff if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name); } @@ -2349,7 +2352,11 @@ return; } RegDef *regDef = _AD._register->getRegDef(rname); - reg_class->addReg(regDef); // add regDef to regClass + if (!regDef) { + parse_err(SEMERR, "unknown identifier %s inside reg_class list.\n", rname); + } else { + reg_class->addReg(regDef); // add regDef to regClass + } // Check for ',' and position to next token. skipws(); @@ -2746,7 +2753,8 @@ char *rule = NULL; // String representation of predicate skipws(); // Skip leading whitespace - if ( (rule = get_paren_expr("pred expression")) == NULL ) { + int line = linenum(); + if ( (rule = get_paren_expr("pred expression", true)) == NULL ) { parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n"); return NULL; } @@ -3407,7 +3415,12 @@ // 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 == '\\') { + next_char(); // superquote + if ((_curchar == '$') || (_curchar == '%')) + // hack to avoid % escapes and warnings about undefined \ escapes + *(_ptr-1) = _curchar; + } if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! next_char(); } @@ -3942,8 +3955,7 @@ next_char(); // Skip block delimiter 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(); @@ -3958,15 +3970,16 @@ _curchar = *_ptr; // Maintain invariant // Prepend location descriptor, for debugging. - char* location = (char *)malloc(strlen(file) + 100); - *location = '\0'; - if (_AD._adlocation_debug) - sprintf(location, "#line %d \"%s\"\n", line, file); - char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1); - strcpy(result, location); - strcat(result, cppBlock); - cppBlock = result; - free(location); + if (_AD._adlocation_debug) { + char* location = get_line_string(line); + char* end_loc = end_line_marker(); + char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1); + strcpy(result, location); + strcat(result, cppBlock); + strcat(result, end_loc); + cppBlock = result; + free(location); + } } return cppBlock; @@ -4036,13 +4049,26 @@ // Helper function around get_expr // Sets _curchar to '(' so that get_paren_expr will search for a matching ')' -char *ADLParser::get_paren_expr(const char *description) { +char *ADLParser::get_paren_expr(const char *description, bool include_location) { + int line = linenum(); if (_curchar != '(') // Escape if not valid starting position return NULL; next_char(); // Skip the required initial paren. char *token2 = get_expr(description, ")"); if (_curchar == ')') next_char(); // Skip required final paren. + int junk = 0; + if (include_location && _AD._adlocation_debug && !is_int_token(token2, junk)) { + // Prepend location descriptor, for debugging. + char* location = get_line_string(line); + char* end_loc = end_line_marker(); + char* result = (char *)malloc(strlen(location) + strlen(token2) + strlen(end_loc) + 1); + strcpy(result, location); + strcat(result, token2); + strcat(result, end_loc); + token2 = result; + free(location); + } return token2; } @@ -4082,10 +4108,16 @@ if (do_preproc && start != NULL) { const char* def = _AD.get_preproc_def(start); if (def != NULL && strcmp(def, start)) { - const char* def2 = _AD.get_preproc_def(def); - if (def2 != NULL && strcmp(def2, def)) { - parse_err(SYNERR, "unimplemented: using %s defined as %s => %s", - start, def, def2); + const char* def1 = def; + const char* def2 = _AD.get_preproc_def(def1); + // implement up to 2 levels of #define + if (def2 != NULL && strcmp(def2, def1)) { + def = def2; + const char* def3 = _AD.get_preproc_def(def2); + if (def3 != NULL && strcmp(def3, def2) && strcmp(def3, def1)) { + parse_err(SYNERR, "unimplemented: using %s defined as %s => %s => %s", + start, def1, def2, def3); + } } start = strdup(def); } @@ -4431,6 +4463,35 @@ } +//-------------------------------preproc_line---------------------------------- +// A "#line" keyword has been seen, so parse the rest of the line. +void ADLParser::preproc_line(void) { + int line = get_int(); + skipws_no_preproc(); + const char* file = NULL; + if (_curchar == '"') { + next_char(); // Move past the initial '"' + file = _ptr; + while (true) { + if (_curchar == '\n') { + parse_err(SYNERR, "missing '\"' at end of #line directive"); + return; + } + if (_curchar == '"') { + *_ptr = '\0'; // Terminate the string + next_char(); + skipws_no_preproc(); + break; + } + next_char(); + } + } + ensure_end_of_line(); + if (file != NULL) + _AD._ADL_file._name = file; + _buf.set_linenum(line); +} + //------------------------------preproc_define--------------------------------- // A "#define" keyword has been seen, so parse the rest of the line. void ADLParser::preproc_define(void) { @@ -4494,6 +4555,7 @@ // A preprocessor directive has been encountered. Be sure it has fallen at // the begining of a line, or else report an error. void ADLParser::ensure_start_of_line(void) { + if (_curchar == '\n') { next_line(); return; } assert( _ptr >= _curline && _ptr < _curline+strlen(_curline), "Must be able to find which line we are in" ); @@ -4662,6 +4724,7 @@ //---------------------------next_char----------------------------------------- void ADLParser::next_char() { + if (_curchar == '\n') parse_err(WARN, "must call next_line!"); _curchar = *++_ptr; // if ( _curchar == '\n' ) { // next_line(); @@ -4682,6 +4745,18 @@ //---------------------------next_line----------------------------------------- void ADLParser::next_line() { _curline = _buf.get_line(); + _curchar = ' '; +} + +//------------------------get_line_string-------------------------------------- +// Prepended location descriptor, for debugging. +// Must return a malloced string (that can be freed if desired). +char* ADLParser::get_line_string(int linenum) { + const char* file = _AD._ADL_file._name; + int line = linenum ? linenum : this->linenum(); + char* location = (char *)malloc(strlen(file) + 100); + sprintf(location, "\n#line %d \"%s\"\n", line, file); + return location; } //-------------------------is_literal_constant--------------------------------- @@ -4722,6 +4797,66 @@ return true; } +static const char* skip_expr_ws(const char* str) { + const char * cp = str; + while (cp[0]) { + if (cp[0] <= ' ') { + ++cp; + } else if (cp[0] == '#') { + ++cp; + while (cp[0] == ' ') ++cp; + assert(0 == strncmp(cp, "line", 4), "must be a #line directive"); + const char* eol = strchr(cp, '\n'); + assert(eol != NULL, "must find end of line"); + if (eol == NULL) eol = cp + strlen(cp); + cp = eol; + } else { + break; + } + } + return cp; +} + +//-----------------------equivalent_expressions-------------------------------- +bool ADLParser::equivalent_expressions(const char* str1, const char* str2) { + if (str1 == str2) + return true; + else if (str1 == NULL || str2 == NULL) + return false; + const char* cp1 = str1; + const char* cp2 = str2; + char in_quote = '\0'; + while (cp1[0] && cp2[0]) { + if (!in_quote) { + // skip spaces and/or cpp directives + const char* cp1a = skip_expr_ws(cp1); + const char* cp2a = skip_expr_ws(cp2); + if (cp1a > cp1 && cp2a > cp2) { + cp1 = cp1a; cp2 = cp2a; + continue; + } + if (cp1a > cp1 || cp2a > cp2) break; // fail + } + // match one non-space char + if (cp1[0] != cp2[0]) break; // fail + char ch = cp1[0]; + cp1++; cp2++; + // watch for quotes + if (in_quote && ch == '\\') { + if (cp1[0] != cp2[0]) break; // fail + if (!cp1[0]) break; + cp1++; cp2++; + } + if (in_quote && ch == in_quote) { + in_quote = '\0'; + } else if (!in_quote && (ch == '"' || ch == '\'')) { + in_quote = ch; + } + } + return (!cp1[0] && !cp2[0]); +} + + //-------------------------------trim------------------------------------------ void ADLParser::trim(char* &token) { while (*token <= ' ') token++;