comparison 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
comparison
equal deleted inserted replaced
474:7a018855d2f0 475:284d0af00d53
106 else if (!strcmp(ident, "frame")) frame_parse(); 106 else if (!strcmp(ident, "frame")) frame_parse();
107 else if (!strcmp(ident, "encode")) encode_parse(); 107 else if (!strcmp(ident, "encode")) encode_parse();
108 else if (!strcmp(ident, "pipeline")) pipe_parse(); 108 else if (!strcmp(ident, "pipeline")) pipe_parse();
109 else if (!strcmp(ident, "definitions")) definitions_parse(); 109 else if (!strcmp(ident, "definitions")) definitions_parse();
110 else if (!strcmp(ident, "peephole")) peep_parse(); 110 else if (!strcmp(ident, "peephole")) peep_parse();
111 else if (!strcmp(ident, "#line")) preproc_line();
111 else if (!strcmp(ident, "#define")) preproc_define(); 112 else if (!strcmp(ident, "#define")) preproc_define();
112 else if (!strcmp(ident, "#undef")) preproc_undef(); 113 else if (!strcmp(ident, "#undef")) preproc_undef();
113 else { 114 else {
114 parse_err(SYNERR, "expected one of - instruct, operand, ins_attrib, op_attrib, source, register, pipeline, encode\n Found %s",ident); 115 parse_err(SYNERR, "expected one of - instruct, operand, ins_attrib, op_attrib, source, register, pipeline, encode\n Found %s",ident);
115 } 116 }
784 char *token = get_ident(); 785 char *token = get_ident();
785 if (token == NULL) { 786 if (token == NULL) {
786 parse_err(SYNERR, "missing identifier inside register block.\n"); 787 parse_err(SYNERR, "missing identifier inside register block.\n");
787 return; 788 return;
788 } 789 }
789 if (strcmp(token,"reg_def")==0) { reg_def_parse(); } 790 if (strcmp(token,"reg_def")==0) { reg_def_parse(); }
790 if (strcmp(token,"reg_class")==0) { reg_class_parse(); } 791 else if (strcmp(token,"reg_class")==0) { reg_class_parse(); }
791 if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); } 792 else if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); }
793 else if (strcmp(token,"#define")==0) { preproc_define(); }
794 else { parse_err(SYNERR, "bad token %s inside register block.\n", token); break; }
792 skipws(); 795 skipws();
793 } 796 }
794 } 797 }
795 else { 798 else {
796 parse_err(SYNERR, "Missing %c{ ... %c} block after register keyword.\n",'%','%'); 799 parse_err(SYNERR, "Missing %c{ ... %c} block after register keyword.\n",'%','%');
901 904
902 void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) { 905 void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
903 skipws_no_preproc(); // Skip leading whitespace 906 skipws_no_preproc(); // Skip leading whitespace
904 // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block 907 // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
905 if (_AD._adlocation_debug) { 908 if (_AD._adlocation_debug) {
906 const char* file = _AD._ADL_file._name; 909 encoding->add_code(get_line_string());
907 int line = linenum();
908 char* location = (char *)malloc(strlen(file) + 100);
909 sprintf(location, "#line %d \"%s\"\n", line, file);
910 encoding->add_code(location);
911 } 910 }
912 911
913 // Collect the parts of the encode description 912 // Collect the parts of the encode description
914 // (1) strings that are passed through to output 913 // (1) strings that are passed through to output
915 // (2) replacement/substitution variable, preceeded by a '$' 914 // (2) replacement/substitution variable, preceeded by a '$'
945 } // end while part of format description 944 } // end while part of format description
946 next_char(); // Skip '%' 945 next_char(); // Skip '%'
947 next_char(); // Skip '}' 946 next_char(); // Skip '}'
948 947
949 skipws(); 948 skipws();
949
950 if (_AD._adlocation_debug) {
951 encoding->add_code(end_line_marker());
952 }
950 953
951 // Debug Stuff 954 // Debug Stuff
952 if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name); 955 if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
953 } 956 }
954 957
2347 if (rname==NULL) { 2350 if (rname==NULL) {
2348 parse_err(SYNERR, "missing identifier inside reg_class list.\n"); 2351 parse_err(SYNERR, "missing identifier inside reg_class list.\n");
2349 return; 2352 return;
2350 } 2353 }
2351 RegDef *regDef = _AD._register->getRegDef(rname); 2354 RegDef *regDef = _AD._register->getRegDef(rname);
2352 reg_class->addReg(regDef); // add regDef to regClass 2355 if (!regDef) {
2356 parse_err(SEMERR, "unknown identifier %s inside reg_class list.\n", rname);
2357 } else {
2358 reg_class->addReg(regDef); // add regDef to regClass
2359 }
2353 2360
2354 // Check for ',' and position to next token. 2361 // Check for ',' and position to next token.
2355 skipws(); 2362 skipws();
2356 if (_curchar == ',') { 2363 if (_curchar == ',') {
2357 next_char(); // Skip trailing ',' 2364 next_char(); // Skip trailing ','
2744 Predicate *ADLParser::pred_parse(void) { 2751 Predicate *ADLParser::pred_parse(void) {
2745 Predicate *predicate; // Predicate class for operand 2752 Predicate *predicate; // Predicate class for operand
2746 char *rule = NULL; // String representation of predicate 2753 char *rule = NULL; // String representation of predicate
2747 2754
2748 skipws(); // Skip leading whitespace 2755 skipws(); // Skip leading whitespace
2749 if ( (rule = get_paren_expr("pred expression")) == NULL ) { 2756 int line = linenum();
2757 if ( (rule = get_paren_expr("pred expression", true)) == NULL ) {
2750 parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n"); 2758 parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
2751 return NULL; 2759 return NULL;
2752 } 2760 }
2753 // Debug Stuff 2761 // Debug Stuff
2754 if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule); 2762 if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule);
3405 3413
3406 // (1) 3414 // (1)
3407 // Check if there is a string to pass through to output 3415 // Check if there is a string to pass through to output
3408 char *start = _ptr; // Record start of the next string 3416 char *start = _ptr; // Record start of the next string
3409 while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) { 3417 while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
3410 if (_curchar == '\\') next_char(); // superquote 3418 if (_curchar == '\\') {
3419 next_char(); // superquote
3420 if ((_curchar == '$') || (_curchar == '%'))
3421 // hack to avoid % escapes and warnings about undefined \ escapes
3422 *(_ptr-1) = _curchar;
3423 }
3411 if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! 3424 if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
3412 next_char(); 3425 next_char();
3413 } 3426 }
3414 // If a string was found, terminate it and record in FormatRule 3427 // If a string was found, terminate it and record in FormatRule
3415 if ( start != _ptr ) { 3428 if ( start != _ptr ) {
3940 return NULL; 3953 return NULL;
3941 } 3954 }
3942 next_char(); // Skip block delimiter 3955 next_char(); // Skip block delimiter
3943 skipws_no_preproc(); // Skip leading whitespace 3956 skipws_no_preproc(); // Skip leading whitespace
3944 cppBlock = _ptr; // Point to start of expression 3957 cppBlock = _ptr; // Point to start of expression
3945 const char* file = _AD._ADL_file._name; 3958 int line = linenum();
3946 int line = linenum();
3947 next = _ptr + 1; 3959 next = _ptr + 1;
3948 while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) { 3960 while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
3949 next_char_or_line(); 3961 next_char_or_line();
3950 next = _ptr+1; // Maintain the next pointer 3962 next = _ptr+1; // Maintain the next pointer
3951 } // Grab string 3963 } // Grab string
3956 *_ptr = '\0'; // Terminate string 3968 *_ptr = '\0'; // Terminate string
3957 _ptr += 2; // Skip block delimiter 3969 _ptr += 2; // Skip block delimiter
3958 _curchar = *_ptr; // Maintain invariant 3970 _curchar = *_ptr; // Maintain invariant
3959 3971
3960 // Prepend location descriptor, for debugging. 3972 // Prepend location descriptor, for debugging.
3961 char* location = (char *)malloc(strlen(file) + 100); 3973 if (_AD._adlocation_debug) {
3962 *location = '\0'; 3974 char* location = get_line_string(line);
3963 if (_AD._adlocation_debug) 3975 char* end_loc = end_line_marker();
3964 sprintf(location, "#line %d \"%s\"\n", line, file); 3976 char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1);
3965 char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1); 3977 strcpy(result, location);
3966 strcpy(result, location); 3978 strcat(result, cppBlock);
3967 strcat(result, cppBlock); 3979 strcat(result, end_loc);
3968 cppBlock = result; 3980 cppBlock = result;
3969 free(location); 3981 free(location);
3982 }
3970 } 3983 }
3971 3984
3972 return cppBlock; 3985 return cppBlock;
3973 } 3986 }
3974 3987
4034 return expr; 4047 return expr;
4035 } 4048 }
4036 4049
4037 // Helper function around get_expr 4050 // Helper function around get_expr
4038 // Sets _curchar to '(' so that get_paren_expr will search for a matching ')' 4051 // Sets _curchar to '(' so that get_paren_expr will search for a matching ')'
4039 char *ADLParser::get_paren_expr(const char *description) { 4052 char *ADLParser::get_paren_expr(const char *description, bool include_location) {
4053 int line = linenum();
4040 if (_curchar != '(') // Escape if not valid starting position 4054 if (_curchar != '(') // Escape if not valid starting position
4041 return NULL; 4055 return NULL;
4042 next_char(); // Skip the required initial paren. 4056 next_char(); // Skip the required initial paren.
4043 char *token2 = get_expr(description, ")"); 4057 char *token2 = get_expr(description, ")");
4044 if (_curchar == ')') 4058 if (_curchar == ')')
4045 next_char(); // Skip required final paren. 4059 next_char(); // Skip required final paren.
4060 int junk = 0;
4061 if (include_location && _AD._adlocation_debug && !is_int_token(token2, junk)) {
4062 // Prepend location descriptor, for debugging.
4063 char* location = get_line_string(line);
4064 char* end_loc = end_line_marker();
4065 char* result = (char *)malloc(strlen(location) + strlen(token2) + strlen(end_loc) + 1);
4066 strcpy(result, location);
4067 strcat(result, token2);
4068 strcat(result, end_loc);
4069 token2 = result;
4070 free(location);
4071 }
4046 return token2; 4072 return token2;
4047 } 4073 }
4048 4074
4049 //------------------------------get_ident_common------------------------------- 4075 //------------------------------get_ident_common-------------------------------
4050 // Looks for an identifier in the buffer, and turns it into a null terminated 4076 // Looks for an identifier in the buffer, and turns it into a null terminated
4080 // Make sure we do not try to use #defined identifiers. If start is 4106 // Make sure we do not try to use #defined identifiers. If start is
4081 // NULL an error was already reported. 4107 // NULL an error was already reported.
4082 if (do_preproc && start != NULL) { 4108 if (do_preproc && start != NULL) {
4083 const char* def = _AD.get_preproc_def(start); 4109 const char* def = _AD.get_preproc_def(start);
4084 if (def != NULL && strcmp(def, start)) { 4110 if (def != NULL && strcmp(def, start)) {
4085 const char* def2 = _AD.get_preproc_def(def); 4111 const char* def1 = def;
4086 if (def2 != NULL && strcmp(def2, def)) { 4112 const char* def2 = _AD.get_preproc_def(def1);
4087 parse_err(SYNERR, "unimplemented: using %s defined as %s => %s", 4113 // implement up to 2 levels of #define
4088 start, def, def2); 4114 if (def2 != NULL && strcmp(def2, def1)) {
4115 def = def2;
4116 const char* def3 = _AD.get_preproc_def(def2);
4117 if (def3 != NULL && strcmp(def3, def2) && strcmp(def3, def1)) {
4118 parse_err(SYNERR, "unimplemented: using %s defined as %s => %s => %s",
4119 start, def1, def2, def3);
4120 }
4089 } 4121 }
4090 start = strdup(def); 4122 start = strdup(def);
4091 } 4123 }
4092 } 4124 }
4093 4125
4429 next_char(); // set current character position past the close paren 4461 next_char(); // set current character position past the close paren
4430 } 4462 }
4431 } 4463 }
4432 4464
4433 4465
4466 //-------------------------------preproc_line----------------------------------
4467 // A "#line" keyword has been seen, so parse the rest of the line.
4468 void ADLParser::preproc_line(void) {
4469 int line = get_int();
4470 skipws_no_preproc();
4471 const char* file = NULL;
4472 if (_curchar == '"') {
4473 next_char(); // Move past the initial '"'
4474 file = _ptr;
4475 while (true) {
4476 if (_curchar == '\n') {
4477 parse_err(SYNERR, "missing '\"' at end of #line directive");
4478 return;
4479 }
4480 if (_curchar == '"') {
4481 *_ptr = '\0'; // Terminate the string
4482 next_char();
4483 skipws_no_preproc();
4484 break;
4485 }
4486 next_char();
4487 }
4488 }
4489 ensure_end_of_line();
4490 if (file != NULL)
4491 _AD._ADL_file._name = file;
4492 _buf.set_linenum(line);
4493 }
4494
4434 //------------------------------preproc_define--------------------------------- 4495 //------------------------------preproc_define---------------------------------
4435 // A "#define" keyword has been seen, so parse the rest of the line. 4496 // A "#define" keyword has been seen, so parse the rest of the line.
4436 void ADLParser::preproc_define(void) { 4497 void ADLParser::preproc_define(void) {
4437 char* flag = get_ident_no_preproc(); 4498 char* flag = get_ident_no_preproc();
4438 skipws_no_preproc(); 4499 skipws_no_preproc();
4492 4553
4493 //---------------------------ensure_start_of_line------------------------------ 4554 //---------------------------ensure_start_of_line------------------------------
4494 // A preprocessor directive has been encountered. Be sure it has fallen at 4555 // A preprocessor directive has been encountered. Be sure it has fallen at
4495 // the begining of a line, or else report an error. 4556 // the begining of a line, or else report an error.
4496 void ADLParser::ensure_start_of_line(void) { 4557 void ADLParser::ensure_start_of_line(void) {
4558 if (_curchar == '\n') { next_line(); return; }
4497 assert( _ptr >= _curline && _ptr < _curline+strlen(_curline), 4559 assert( _ptr >= _curline && _ptr < _curline+strlen(_curline),
4498 "Must be able to find which line we are in" ); 4560 "Must be able to find which line we are in" );
4499 4561
4500 for (char *s = _curline; s < _ptr; s++) { 4562 for (char *s = _curline; s < _ptr; s++) {
4501 if (*s > ' ') { 4563 if (*s > ' ') {
4660 return (_curchar); 4722 return (_curchar);
4661 } 4723 }
4662 4724
4663 //---------------------------next_char----------------------------------------- 4725 //---------------------------next_char-----------------------------------------
4664 void ADLParser::next_char() { 4726 void ADLParser::next_char() {
4727 if (_curchar == '\n') parse_err(WARN, "must call next_line!");
4665 _curchar = *++_ptr; 4728 _curchar = *++_ptr;
4666 // if ( _curchar == '\n' ) { 4729 // if ( _curchar == '\n' ) {
4667 // next_line(); 4730 // next_line();
4668 // } 4731 // }
4669 } 4732 }
4680 } 4743 }
4681 4744
4682 //---------------------------next_line----------------------------------------- 4745 //---------------------------next_line-----------------------------------------
4683 void ADLParser::next_line() { 4746 void ADLParser::next_line() {
4684 _curline = _buf.get_line(); 4747 _curline = _buf.get_line();
4748 _curchar = ' ';
4749 }
4750
4751 //------------------------get_line_string--------------------------------------
4752 // Prepended location descriptor, for debugging.
4753 // Must return a malloced string (that can be freed if desired).
4754 char* ADLParser::get_line_string(int linenum) {
4755 const char* file = _AD._ADL_file._name;
4756 int line = linenum ? linenum : this->linenum();
4757 char* location = (char *)malloc(strlen(file) + 100);
4758 sprintf(location, "\n#line %d \"%s\"\n", line, file);
4759 return location;
4685 } 4760 }
4686 4761
4687 //-------------------------is_literal_constant--------------------------------- 4762 //-------------------------is_literal_constant---------------------------------
4688 bool ADLParser::is_literal_constant(const char *param) { 4763 bool ADLParser::is_literal_constant(const char *param) {
4689 if (param[0] == 0) return false; // null string 4764 if (param[0] == 0) return false; // null string
4720 } 4795 }
4721 intval = atoi(token); 4796 intval = atoi(token);
4722 return true; 4797 return true;
4723 } 4798 }
4724 4799
4800 static const char* skip_expr_ws(const char* str) {
4801 const char * cp = str;
4802 while (cp[0]) {
4803 if (cp[0] <= ' ') {
4804 ++cp;
4805 } else if (cp[0] == '#') {
4806 ++cp;
4807 while (cp[0] == ' ') ++cp;
4808 assert(0 == strncmp(cp, "line", 4), "must be a #line directive");
4809 const char* eol = strchr(cp, '\n');
4810 assert(eol != NULL, "must find end of line");
4811 if (eol == NULL) eol = cp + strlen(cp);
4812 cp = eol;
4813 } else {
4814 break;
4815 }
4816 }
4817 return cp;
4818 }
4819
4820 //-----------------------equivalent_expressions--------------------------------
4821 bool ADLParser::equivalent_expressions(const char* str1, const char* str2) {
4822 if (str1 == str2)
4823 return true;
4824 else if (str1 == NULL || str2 == NULL)
4825 return false;
4826 const char* cp1 = str1;
4827 const char* cp2 = str2;
4828 char in_quote = '\0';
4829 while (cp1[0] && cp2[0]) {
4830 if (!in_quote) {
4831 // skip spaces and/or cpp directives
4832 const char* cp1a = skip_expr_ws(cp1);
4833 const char* cp2a = skip_expr_ws(cp2);
4834 if (cp1a > cp1 && cp2a > cp2) {
4835 cp1 = cp1a; cp2 = cp2a;
4836 continue;
4837 }
4838 if (cp1a > cp1 || cp2a > cp2) break; // fail
4839 }
4840 // match one non-space char
4841 if (cp1[0] != cp2[0]) break; // fail
4842 char ch = cp1[0];
4843 cp1++; cp2++;
4844 // watch for quotes
4845 if (in_quote && ch == '\\') {
4846 if (cp1[0] != cp2[0]) break; // fail
4847 if (!cp1[0]) break;
4848 cp1++; cp2++;
4849 }
4850 if (in_quote && ch == in_quote) {
4851 in_quote = '\0';
4852 } else if (!in_quote && (ch == '"' || ch == '\'')) {
4853 in_quote = ch;
4854 }
4855 }
4856 return (!cp1[0] && !cp2[0]);
4857 }
4858
4859
4725 //-------------------------------trim------------------------------------------ 4860 //-------------------------------trim------------------------------------------
4726 void ADLParser::trim(char* &token) { 4861 void ADLParser::trim(char* &token) {
4727 while (*token <= ' ') token++; 4862 while (*token <= ' ') token++;
4728 char* end = token + strlen(token); 4863 char* end = token + strlen(token);
4729 while (end > token && *(end-1) <= ' ') --end; 4864 while (end > token && *(end-1) <= ' ') --end;