Mercurial > hg > graal-jvmci-8
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; |