6771309: debugging AD files is difficult without #line directives in generated code
More and better #line and #define directives in the generated code; ADLC itself accepts #line directives Reviewed-by: never, kvn
This commit is contained in:
parent
e50f766540
commit
67464baa7a
@ -7,5 +7,13 @@
|
|||||||
#
|
#
|
||||||
# adlc-updater <file> <source-dir> <target-dir>
|
# adlc-updater <file> <source-dir> <target-dir>
|
||||||
#
|
#
|
||||||
[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \
|
fix_lines() {
|
||||||
( [ -f $3/$1 ]; echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
# repair bare #line directives in $1 to refer to $2
|
||||||
|
awk < $1 > $1+ '
|
||||||
|
/^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next}
|
||||||
|
{print}
|
||||||
|
' F2=$2
|
||||||
|
mv $1+ $1
|
||||||
|
}
|
||||||
|
[ -f $3/$1 ] && (fix_lines $2/$1 $3/$1; cmp -s $2/$1 $3/$1) || \
|
||||||
|
( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
||||||
|
@ -54,10 +54,12 @@ VPATH += $(Src_Dirs_V:%=%:)
|
|||||||
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
|
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
|
||||||
INCLUDES += $(Src_Dirs_I:%=-I%)
|
INCLUDES += $(Src_Dirs_I:%=-I%)
|
||||||
|
|
||||||
# Force assertions on.
|
# set flags for adlc compilation
|
||||||
SYSDEFS += -DASSERT
|
|
||||||
CPPFLAGS = $(SYSDEFS) $(INCLUDES)
|
CPPFLAGS = $(SYSDEFS) $(INCLUDES)
|
||||||
|
|
||||||
|
# Force assertions on.
|
||||||
|
CPPFLAGS += -DASSERT
|
||||||
|
|
||||||
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
||||||
# Suppress warnings (for now)
|
# Suppress warnings (for now)
|
||||||
CFLAGS_WARN = -w
|
CFLAGS_WARN = -w
|
||||||
@ -125,7 +127,15 @@ $(GENERATEDFILES): refresh_adfiles
|
|||||||
# Note that product files are updated via "mv", which is atomic.
|
# Note that product files are updated via "mv", which is atomic.
|
||||||
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
|
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
|
||||||
|
|
||||||
ADLCFLAGS = -q -T
|
# Pass -D flags into ADLC.
|
||||||
|
ADLCFLAGS += $(SYSDEFS)
|
||||||
|
|
||||||
|
# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
|
||||||
|
ADLCFLAGS += -q -T
|
||||||
|
|
||||||
|
# Normally, debugging is done directly on the ad_<arch>*.cpp files.
|
||||||
|
# But -g will put #line directives in those files pointing back to <arch>.ad.
|
||||||
|
#ADLCFLAGS += -g
|
||||||
|
|
||||||
ifdef LP64
|
ifdef LP64
|
||||||
ADLCFLAGS += -D_LP64
|
ADLCFLAGS += -D_LP64
|
||||||
@ -140,6 +150,8 @@ endif
|
|||||||
#
|
#
|
||||||
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
|
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
|
||||||
ADLC_UPDATER = adlc_updater
|
ADLC_UPDATER = adlc_updater
|
||||||
|
$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER)
|
||||||
|
$(QUIETLY) cp $< $@; chmod +x $@
|
||||||
|
|
||||||
# This action refreshes all generated adlc files simultaneously.
|
# This action refreshes all generated adlc files simultaneously.
|
||||||
# The way it works is this:
|
# The way it works is this:
|
||||||
@ -149,9 +161,8 @@ ADLC_UPDATER = adlc_updater
|
|||||||
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
|
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
|
||||||
# 5) If we actually updated any files, echo a notice.
|
# 5) If we actually updated any files, echo a notice.
|
||||||
#
|
#
|
||||||
refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER)
|
||||||
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
|
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
|
||||||
$(QUIETLY) [ -f $(ADLC_UPDATER) ] || ( cp $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) . ; chmod +x $(ADLC_UPDATER) )
|
|
||||||
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
|
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
|
||||||
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|
||||||
|| { rm -rf $(TEMPDIR); exit 1; }
|
|| { rm -rf $(TEMPDIR); exit 1; }
|
||||||
@ -174,7 +185,15 @@ refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
|||||||
# #########################################################################
|
# #########################################################################
|
||||||
|
|
||||||
$(SOURCE.AD): $(SOURCES.AD)
|
$(SOURCE.AD): $(SOURCES.AD)
|
||||||
$(QUIETLY) cat $(SOURCES.AD) > $(SOURCE.AD)
|
$(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD)
|
||||||
|
|
||||||
|
#PROCESS_AD_FILES = cat
|
||||||
|
# Pass through #line directives, in case user enables -g option above:
|
||||||
|
PROCESS_AD_FILES = awk '{ \
|
||||||
|
if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \
|
||||||
|
if (need_lineno && $$0 !~ /\/\//) \
|
||||||
|
{ print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \
|
||||||
|
print }'
|
||||||
|
|
||||||
$(OUTDIR)/%.o: %.cpp
|
$(OUTDIR)/%.o: %.cpp
|
||||||
@echo Compiling $<
|
@echo Compiling $<
|
||||||
|
@ -7,5 +7,13 @@
|
|||||||
#
|
#
|
||||||
# adlc-updater <file> <source-dir> <target-dir>
|
# adlc-updater <file> <source-dir> <target-dir>
|
||||||
#
|
#
|
||||||
[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \
|
fix_lines() {
|
||||||
( [ -f $3/$1 ]; echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
# repair bare #line directives in $1 to refer to $2
|
||||||
|
awk < $1 > $1+ '
|
||||||
|
/^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next}
|
||||||
|
{print}
|
||||||
|
' F2=$2
|
||||||
|
mv $1+ $1
|
||||||
|
}
|
||||||
|
[ -f $3/$1 ] && (fix_lines $2/$1 $3/$1; cmp -s $2/$1 $3/$1) || \
|
||||||
|
( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
||||||
|
@ -54,10 +54,12 @@ VPATH += $(Src_Dirs_V:%=%:)
|
|||||||
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
|
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
|
||||||
INCLUDES += $(Src_Dirs_I:%=-I%)
|
INCLUDES += $(Src_Dirs_I:%=-I%)
|
||||||
|
|
||||||
# Force assertions on.
|
# set flags for adlc compilation
|
||||||
SYSDEFS += -DASSERT
|
|
||||||
CPPFLAGS = $(SYSDEFS) $(INCLUDES)
|
CPPFLAGS = $(SYSDEFS) $(INCLUDES)
|
||||||
|
|
||||||
|
# Force assertions on.
|
||||||
|
CPPFLAGS += -DASSERT
|
||||||
|
|
||||||
ifndef USE_GCC
|
ifndef USE_GCC
|
||||||
# We need libCstd.so for adlc
|
# We need libCstd.so for adlc
|
||||||
CFLAGS += -library=Cstd -g
|
CFLAGS += -library=Cstd -g
|
||||||
@ -141,7 +143,15 @@ $(GENERATEDFILES): refresh_adfiles
|
|||||||
# Note that product files are updated via "mv", which is atomic.
|
# Note that product files are updated via "mv", which is atomic.
|
||||||
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
|
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
|
||||||
|
|
||||||
ADLCFLAGS = -q -T
|
# Pass -D flags into ADLC.
|
||||||
|
ADLCFLAGS += $(SYSDEFS)
|
||||||
|
|
||||||
|
# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
|
||||||
|
ADLCFLAGS += -q -T
|
||||||
|
|
||||||
|
# Normally, debugging is done directly on the ad_<arch>*.cpp files.
|
||||||
|
# But -g will put #line directives in those files pointing back to <arch>.ad.
|
||||||
|
#ADLCFLAGS += -g
|
||||||
|
|
||||||
ifdef LP64
|
ifdef LP64
|
||||||
ADLCFLAGS += -D_LP64
|
ADLCFLAGS += -D_LP64
|
||||||
@ -156,6 +166,8 @@ endif
|
|||||||
#
|
#
|
||||||
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
|
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
|
||||||
ADLC_UPDATER = adlc_updater
|
ADLC_UPDATER = adlc_updater
|
||||||
|
$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER)
|
||||||
|
$(QUIETLY) cp $< $@; chmod +x $@
|
||||||
|
|
||||||
# This action refreshes all generated adlc files simultaneously.
|
# This action refreshes all generated adlc files simultaneously.
|
||||||
# The way it works is this:
|
# The way it works is this:
|
||||||
@ -165,9 +177,8 @@ ADLC_UPDATER = adlc_updater
|
|||||||
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
|
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
|
||||||
# 5) If we actually updated any files, echo a notice.
|
# 5) If we actually updated any files, echo a notice.
|
||||||
#
|
#
|
||||||
refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER)
|
||||||
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
|
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
|
||||||
$(QUIETLY) [ -f $(ADLC_UPDATER) ] || ( cp $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) . ; chmod +x $(ADLC_UPDATER) )
|
|
||||||
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
|
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
|
||||||
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|
||||||
|| { rm -rf $(TEMPDIR); exit 1; }
|
|| { rm -rf $(TEMPDIR); exit 1; }
|
||||||
@ -190,7 +201,15 @@ refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
|||||||
# #########################################################################
|
# #########################################################################
|
||||||
|
|
||||||
$(SOURCE.AD): $(SOURCES.AD)
|
$(SOURCE.AD): $(SOURCES.AD)
|
||||||
$(QUIETLY) cat $(SOURCES.AD) > $(SOURCE.AD)
|
$(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD)
|
||||||
|
|
||||||
|
#PROCESS_AD_FILES = cat
|
||||||
|
# Pass through #line directives, in case user enables -g option above:
|
||||||
|
PROCESS_AD_FILES = awk '{ \
|
||||||
|
if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \
|
||||||
|
if (need_lineno && $$0 !~ /\/\//) \
|
||||||
|
{ print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \
|
||||||
|
print }'
|
||||||
|
|
||||||
$(OUTDIR)/%.o: %.cpp
|
$(OUTDIR)/%.o: %.cpp
|
||||||
@echo Compiling $<
|
@echo Compiling $<
|
||||||
|
@ -108,6 +108,7 @@ void ADLParser::parse() {
|
|||||||
else if (!strcmp(ident, "pipeline")) pipe_parse();
|
else if (!strcmp(ident, "pipeline")) pipe_parse();
|
||||||
else if (!strcmp(ident, "definitions")) definitions_parse();
|
else if (!strcmp(ident, "definitions")) definitions_parse();
|
||||||
else if (!strcmp(ident, "peephole")) peep_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, "#define")) preproc_define();
|
||||||
else if (!strcmp(ident, "#undef")) preproc_undef();
|
else if (!strcmp(ident, "#undef")) preproc_undef();
|
||||||
else {
|
else {
|
||||||
@ -786,9 +787,11 @@ void ADLParser::reg_parse(void) {
|
|||||||
parse_err(SYNERR, "missing identifier inside register block.\n");
|
parse_err(SYNERR, "missing identifier inside register block.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(token,"reg_def")==0) { reg_def_parse(); }
|
if (strcmp(token,"reg_def")==0) { reg_def_parse(); }
|
||||||
if (strcmp(token,"reg_class")==0) { reg_class_parse(); }
|
else if (strcmp(token,"reg_class")==0) { reg_class_parse(); }
|
||||||
if (strcmp(token,"alloc_class")==0) { alloc_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();
|
skipws();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -903,11 +906,7 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
|
|||||||
skipws_no_preproc(); // Skip leading whitespace
|
skipws_no_preproc(); // Skip leading whitespace
|
||||||
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
|
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
|
||||||
if (_AD._adlocation_debug) {
|
if (_AD._adlocation_debug) {
|
||||||
const char* file = _AD._ADL_file._name;
|
encoding->add_code(get_line_string());
|
||||||
int line = linenum();
|
|
||||||
char* location = (char *)malloc(strlen(file) + 100);
|
|
||||||
sprintf(location, "#line %d \"%s\"\n", line, file);
|
|
||||||
encoding->add_code(location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect the parts of the encode description
|
// Collect the parts of the encode description
|
||||||
@ -948,6 +947,10 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
|
|||||||
|
|
||||||
skipws();
|
skipws();
|
||||||
|
|
||||||
|
if (_AD._adlocation_debug) {
|
||||||
|
encoding->add_code(end_line_marker());
|
||||||
|
}
|
||||||
|
|
||||||
// Debug Stuff
|
// Debug Stuff
|
||||||
if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
|
if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
|
||||||
}
|
}
|
||||||
@ -2349,7 +2352,11 @@ void ADLParser::reg_class_parse(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RegDef *regDef = _AD._register->getRegDef(rname);
|
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.
|
// Check for ',' and position to next token.
|
||||||
skipws();
|
skipws();
|
||||||
@ -2746,7 +2753,8 @@ Predicate *ADLParser::pred_parse(void) {
|
|||||||
char *rule = NULL; // String representation of predicate
|
char *rule = NULL; // String representation of predicate
|
||||||
|
|
||||||
skipws(); // Skip leading whitespace
|
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");
|
parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -3407,7 +3415,12 @@ FormatRule* ADLParser::format_parse(void) {
|
|||||||
// Check if there is a string to pass through to output
|
// Check if there is a string to pass through to output
|
||||||
char *start = _ptr; // Record start of the next string
|
char *start = _ptr; // Record start of the next string
|
||||||
while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
|
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!
|
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
|
||||||
next_char();
|
next_char();
|
||||||
}
|
}
|
||||||
@ -3942,8 +3955,7 @@ char* ADLParser::find_cpp_block(const char* description) {
|
|||||||
next_char(); // Skip block delimiter
|
next_char(); // Skip block delimiter
|
||||||
skipws_no_preproc(); // Skip leading whitespace
|
skipws_no_preproc(); // Skip leading whitespace
|
||||||
cppBlock = _ptr; // Point to start of expression
|
cppBlock = _ptr; // Point to start of expression
|
||||||
const char* file = _AD._ADL_file._name;
|
int line = linenum();
|
||||||
int line = linenum();
|
|
||||||
next = _ptr + 1;
|
next = _ptr + 1;
|
||||||
while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
|
while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
|
||||||
next_char_or_line();
|
next_char_or_line();
|
||||||
@ -3958,15 +3970,16 @@ char* ADLParser::find_cpp_block(const char* description) {
|
|||||||
_curchar = *_ptr; // Maintain invariant
|
_curchar = *_ptr; // Maintain invariant
|
||||||
|
|
||||||
// Prepend location descriptor, for debugging.
|
// Prepend location descriptor, for debugging.
|
||||||
char* location = (char *)malloc(strlen(file) + 100);
|
if (_AD._adlocation_debug) {
|
||||||
*location = '\0';
|
char* location = get_line_string(line);
|
||||||
if (_AD._adlocation_debug)
|
char* end_loc = end_line_marker();
|
||||||
sprintf(location, "#line %d \"%s\"\n", line, file);
|
char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1);
|
||||||
char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1);
|
strcpy(result, location);
|
||||||
strcpy(result, location);
|
strcat(result, cppBlock);
|
||||||
strcat(result, cppBlock);
|
strcat(result, end_loc);
|
||||||
cppBlock = result;
|
cppBlock = result;
|
||||||
free(location);
|
free(location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cppBlock;
|
return cppBlock;
|
||||||
@ -4036,13 +4049,26 @@ char* ADLParser::get_expr(const char *desc, const char *stop_chars) {
|
|||||||
|
|
||||||
// Helper function around get_expr
|
// Helper function around get_expr
|
||||||
// Sets _curchar to '(' so that get_paren_expr will search for a matching ')'
|
// 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
|
if (_curchar != '(') // Escape if not valid starting position
|
||||||
return NULL;
|
return NULL;
|
||||||
next_char(); // Skip the required initial paren.
|
next_char(); // Skip the required initial paren.
|
||||||
char *token2 = get_expr(description, ")");
|
char *token2 = get_expr(description, ")");
|
||||||
if (_curchar == ')')
|
if (_curchar == ')')
|
||||||
next_char(); // Skip required final paren.
|
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;
|
return token2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4082,10 +4108,16 @@ char *ADLParser::get_ident_common(bool do_preproc) {
|
|||||||
if (do_preproc && start != NULL) {
|
if (do_preproc && start != NULL) {
|
||||||
const char* def = _AD.get_preproc_def(start);
|
const char* def = _AD.get_preproc_def(start);
|
||||||
if (def != NULL && strcmp(def, start)) {
|
if (def != NULL && strcmp(def, start)) {
|
||||||
const char* def2 = _AD.get_preproc_def(def);
|
const char* def1 = def;
|
||||||
if (def2 != NULL && strcmp(def2, def)) {
|
const char* def2 = _AD.get_preproc_def(def1);
|
||||||
parse_err(SYNERR, "unimplemented: using %s defined as %s => %s",
|
// implement up to 2 levels of #define
|
||||||
start, def, def2);
|
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);
|
start = strdup(def);
|
||||||
}
|
}
|
||||||
@ -4431,6 +4463,35 @@ void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------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---------------------------------
|
//------------------------------preproc_define---------------------------------
|
||||||
// A "#define" keyword has been seen, so parse the rest of the line.
|
// A "#define" keyword has been seen, so parse the rest of the line.
|
||||||
void ADLParser::preproc_define(void) {
|
void ADLParser::preproc_define(void) {
|
||||||
@ -4494,6 +4555,7 @@ void ADLParser::parse_err(int flag, const char *fmt, ...) {
|
|||||||
// A preprocessor directive has been encountered. Be sure it has fallen at
|
// A preprocessor directive has been encountered. Be sure it has fallen at
|
||||||
// the begining of a line, or else report an error.
|
// the begining of a line, or else report an error.
|
||||||
void ADLParser::ensure_start_of_line(void) {
|
void ADLParser::ensure_start_of_line(void) {
|
||||||
|
if (_curchar == '\n') { next_line(); return; }
|
||||||
assert( _ptr >= _curline && _ptr < _curline+strlen(_curline),
|
assert( _ptr >= _curline && _ptr < _curline+strlen(_curline),
|
||||||
"Must be able to find which line we are in" );
|
"Must be able to find which line we are in" );
|
||||||
|
|
||||||
@ -4662,6 +4724,7 @@ char ADLParser::cur_char() {
|
|||||||
|
|
||||||
//---------------------------next_char-----------------------------------------
|
//---------------------------next_char-----------------------------------------
|
||||||
void ADLParser::next_char() {
|
void ADLParser::next_char() {
|
||||||
|
if (_curchar == '\n') parse_err(WARN, "must call next_line!");
|
||||||
_curchar = *++_ptr;
|
_curchar = *++_ptr;
|
||||||
// if ( _curchar == '\n' ) {
|
// if ( _curchar == '\n' ) {
|
||||||
// next_line();
|
// next_line();
|
||||||
@ -4682,6 +4745,18 @@ void ADLParser::next_char_or_line() {
|
|||||||
//---------------------------next_line-----------------------------------------
|
//---------------------------next_line-----------------------------------------
|
||||||
void ADLParser::next_line() {
|
void ADLParser::next_line() {
|
||||||
_curline = _buf.get_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---------------------------------
|
//-------------------------is_literal_constant---------------------------------
|
||||||
@ -4722,6 +4797,66 @@ bool ADLParser::is_int_token(const char* token, int& intval) {
|
|||||||
return true;
|
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------------------------------------------
|
//-------------------------------trim------------------------------------------
|
||||||
void ADLParser::trim(char* &token) {
|
void ADLParser::trim(char* &token) {
|
||||||
while (*token <= ' ') token++;
|
while (*token <= ' ') token++;
|
||||||
|
@ -93,6 +93,7 @@ protected:
|
|||||||
void pipe_parse(void); // Parse pipeline section
|
void pipe_parse(void); // Parse pipeline section
|
||||||
void definitions_parse(void); // Parse definitions section
|
void definitions_parse(void); // Parse definitions section
|
||||||
void peep_parse(void); // Parse peephole rule definitions
|
void peep_parse(void); // Parse peephole rule definitions
|
||||||
|
void preproc_line(void); // Parse a #line statement
|
||||||
void preproc_define(void); // Parse a #define statement
|
void preproc_define(void); // Parse a #define statement
|
||||||
void preproc_undef(void); // Parse an #undef statement
|
void preproc_undef(void); // Parse an #undef statement
|
||||||
|
|
||||||
@ -226,7 +227,7 @@ protected:
|
|||||||
void get_effectlist(FormDict &effects, FormDict &operands); // Parse effect-operand pairs
|
void get_effectlist(FormDict &effects, FormDict &operands); // Parse effect-operand pairs
|
||||||
// Return the contents of a parenthesized expression.
|
// Return the contents of a parenthesized expression.
|
||||||
// Requires initial '(' and consumes final ')', which is replaced by '\0'.
|
// Requires initial '(' and consumes final ')', which is replaced by '\0'.
|
||||||
char *get_paren_expr(const char *description);
|
char *get_paren_expr(const char *description, bool include_location = false);
|
||||||
// Return expression up to next stop-char, which terminator replaces.
|
// Return expression up to next stop-char, which terminator replaces.
|
||||||
// Does not require initial '('. Does not consume final stop-char.
|
// Does not require initial '('. Does not consume final stop-char.
|
||||||
// Final stop-char is left in _curchar, but is also is replaced by '\0'.
|
// Final stop-char is left in _curchar, but is also is replaced by '\0'.
|
||||||
@ -234,6 +235,11 @@ protected:
|
|||||||
char *find_cpp_block(const char *description); // Parse a C++ code block
|
char *find_cpp_block(const char *description); // Parse a C++ code block
|
||||||
// Issue parser error message & go to EOL
|
// Issue parser error message & go to EOL
|
||||||
void parse_err(int flag, const char *fmt, ...);
|
void parse_err(int flag, const char *fmt, ...);
|
||||||
|
// Create a location marker for this file and line.
|
||||||
|
char *get_line_string(int linenum = 0);
|
||||||
|
// Return a location marker which tells the C preprocessor to
|
||||||
|
// forget the previous location marker. (Requires awk postprocessing.)
|
||||||
|
char *end_line_marker() { return (char*)"\n#line 999999\n"; }
|
||||||
|
|
||||||
// Return pointer to current character
|
// Return pointer to current character
|
||||||
inline char cur_char(void);
|
inline char cur_char(void);
|
||||||
@ -268,5 +274,6 @@ public:
|
|||||||
static bool is_literal_constant(const char *hex_string);
|
static bool is_literal_constant(const char *hex_string);
|
||||||
static bool is_hex_digit(char digit);
|
static bool is_hex_digit(char digit);
|
||||||
static bool is_int_token(const char* token, int& intval);
|
static bool is_int_token(const char* token, int& intval);
|
||||||
|
static bool equivalent_expressions(const char* str1, const char* str2);
|
||||||
static void trim(char* &token); // trim leading & trailing spaces
|
static void trim(char* &token); // trim leading & trailing spaces
|
||||||
};
|
};
|
||||||
|
@ -140,7 +140,7 @@ bool MatchList::search(const char *opc, const char *res, const char *lch,
|
|||||||
if ((rch == _rchild) || (rch && _rchild && !strcmp(rch, _rchild))) {
|
if ((rch == _rchild) || (rch && _rchild && !strcmp(rch, _rchild))) {
|
||||||
char * predStr = get_pred();
|
char * predStr = get_pred();
|
||||||
char * prStr = pr?pr->_pred:NULL;
|
char * prStr = pr?pr->_pred:NULL;
|
||||||
if ((prStr == predStr) || (prStr && predStr && !strcmp(prStr, predStr))) {
|
if (ADLParser::equivalent_expressions(prStr, predStr)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ void ArchDesc::buildDFA(FILE* fp) {
|
|||||||
|
|
||||||
|
|
||||||
class dfa_shared_preds {
|
class dfa_shared_preds {
|
||||||
enum { count = 2 };
|
enum { count = 4 };
|
||||||
|
|
||||||
static bool _found[count];
|
static bool _found[count];
|
||||||
static const char* _type [count];
|
static const char* _type [count];
|
||||||
@ -479,12 +479,15 @@ class dfa_shared_preds {
|
|||||||
char c = *prev;
|
char c = *prev;
|
||||||
switch( c ) {
|
switch( c ) {
|
||||||
case ' ':
|
case ' ':
|
||||||
|
case '\n':
|
||||||
return dfa_shared_preds::valid_loc(pred, prev);
|
return dfa_shared_preds::valid_loc(pred, prev);
|
||||||
case '!':
|
case '!':
|
||||||
case '(':
|
case '(':
|
||||||
case '<':
|
case '<':
|
||||||
case '=':
|
case '=':
|
||||||
return true;
|
return true;
|
||||||
|
case '"': // such as: #line 10 "myfile.ad"\n mypredicate
|
||||||
|
return true;
|
||||||
case '|':
|
case '|':
|
||||||
if( prev != pred && *(prev-1) == '|' ) return true;
|
if( prev != pred && *(prev-1) == '|' ) return true;
|
||||||
case '&':
|
case '&':
|
||||||
@ -564,10 +567,14 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// shared predicates, _var and _pred entry should be the same length
|
// shared predicates, _var and _pred entry should be the same length
|
||||||
bool dfa_shared_preds::_found[dfa_shared_preds::count] = { false, false };
|
bool dfa_shared_preds::_found[dfa_shared_preds::count]
|
||||||
const char* dfa_shared_preds::_type[dfa_shared_preds::count] = { "int", "bool" };
|
= { false, false, false, false };
|
||||||
const char* dfa_shared_preds::_var [dfa_shared_preds::count] = { "_n_get_int__", "Compile__current____select_24_bit_instr__" };
|
const char* dfa_shared_preds::_type[dfa_shared_preds::count]
|
||||||
const char* dfa_shared_preds::_pred[dfa_shared_preds::count] = { "n->get_int()", "Compile::current()->select_24_bit_instr()" };
|
= { "int", "jlong", "intptr_t", "bool" };
|
||||||
|
const char* dfa_shared_preds::_var [dfa_shared_preds::count]
|
||||||
|
= { "_n_get_int__", "_n_get_long__", "_n_get_intptr_t__", "Compile__current____select_24_bit_instr__" };
|
||||||
|
const char* dfa_shared_preds::_pred[dfa_shared_preds::count]
|
||||||
|
= { "n->get_int()", "n->get_long()", "n->get_intptr_t()", "Compile::current()->select_24_bit_instr()" };
|
||||||
|
|
||||||
|
|
||||||
void ArchDesc::gen_dfa_state_body(FILE* fp, Dict &minimize, ProductionState &status, Dict &operands_chained_from, int i) {
|
void ArchDesc::gen_dfa_state_body(FILE* fp, Dict &minimize, ProductionState &status, Dict &operands_chained_from, int i) {
|
||||||
|
@ -68,6 +68,7 @@ class FileBuff {
|
|||||||
// and increments bufeol and filepos to point at the end of that line.
|
// and increments bufeol and filepos to point at the end of that line.
|
||||||
char *get_line(void);
|
char *get_line(void);
|
||||||
int linenum() const { return _linenum; }
|
int linenum() const { return _linenum; }
|
||||||
|
void set_linenum(int line) { _linenum = line; }
|
||||||
|
|
||||||
// This converts a pointer into the buffer to a file offset. It only works
|
// This converts a pointer into the buffer to a file offset. It only works
|
||||||
// when the pointer is valid (i.e. just obtained from getline()).
|
// when the pointer is valid (i.e. just obtained from getline()).
|
||||||
|
@ -1102,10 +1102,7 @@ bool equivalent_predicates( const InstructForm *instr1, const InstructForm *inst
|
|||||||
}
|
}
|
||||||
if( pred1 != NULL && pred2 != NULL ) {
|
if( pred1 != NULL && pred2 != NULL ) {
|
||||||
// compare the predicates
|
// compare the predicates
|
||||||
const char *str1 = pred1->_pred;
|
if (ADLParser::equivalent_expressions(pred1->_pred, pred2->_pred)) {
|
||||||
const char *str2 = pred2->_pred;
|
|
||||||
if( (str1 == NULL && str2 == NULL)
|
|
||||||
|| (str1 != NULL && str2 != NULL && strcmp(str1,str2) == 0) ) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user