PATCH 01: Testsuite: compare outputs of a testcase compiled and run with 2 flags
Harsha Jagasia
harsha.jagasia@amd.com
Thu May 1 18:36:00 GMT 2008
* gcc.dg/tree-ssa/runcmp-example.c: New testcase.
* lib/gcc-dg.exp (gcc-get-options, gcc-options-runcmp,
chk_compile_time_err, chk_run_time_status): New.
(gcc-dg-test-1): Find the gcc-* command comments in the testcase.
Execute each of these gcc-* commands. Implements the runcmp command.
Index: gcc.dg/tree-ssa/runcmp-example.c
===================================================================
--- gcc.dg/tree-ssa/runcmp-example.c (revision 0)
+++ gcc.dg/tree-ssa/runcmp-example.c (revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { gcc-options-runcmp "-O2" "-O3" } */
+
+#include <stdio.h>
+double u[178];
+int foo(int N)
+{
+ int i;
+ int sum = 0;
+ for (i = 0; i < 178; i++)
+ {
+ u[i] = rand();
+ sum += u[i];
+
+ }
+ sum = sum + N;
+ return sum;
+}
+
+int main()
+{
+ int sum = 0;
+ sum = foo (10);
+ printf("sum:%d\n", sum);
+ return 0;
+}
Index: lib/gcc-dg.exp
===================================================================
--- lib/gcc-dg.exp (revision 134836)
+++ lib/gcc-dg.exp (working copy)
@@ -27,6 +27,7 @@ load_lib prune.exp
load_lib libgloss.exp
load_lib target-libpath.exp
+
# We set LC_ALL and LANG to C so that we get the same error messages as expected.
setenv LC_ALL C
setenv LANG C
@@ -75,12 +76,105 @@ foreach option $TORTURE_OPTIONS {
}
}
+proc gcc-get-options { prog } {
+ set result ""
+
+ set tmp [grep $prog "{\[ \t\]\+gcc-\[-a-z\]\+\[ \t\]\+.*\[ \t\]\+}" line]
+ if ![string match "" $tmp] {
+ foreach i $tmp {
+ regexp "(\[0-9\]\+)\[ \t\]\+{\[ \t\]+(gcc-\[-a-z\]+)\[ \t\]\+(.*)\[ \t\]+}\[^\}\]*(\n|$)" $i i line cmd args
+ append result " { $cmd $line $args }"
+ }
+ }
+
+ return $result
+}
+
+proc gcc-options-runcmp { args } {
+
+ upvar flags1 flags1
+ upvar flags2 flags2
+
+ if { [llength $args] > 4 } {
+ error "[lindex $args 0]: too many arguments"
+ return
+ }
+ # FIXME: For now no target filter. Add support for target filter
+ # specified in test case
+ set flags1 [lindex $args 1]
+ set flags2 [lindex $args 2]
+}
+
+proc chk_compile_time_err { comp_output name flags } {
+ if [string match "*internal compiler error*" $comp_output] {
+ fail "$name (internal compiler error) $flags"
+ }
+}
+
+proc chk_run_time_status { output_file flags do_exp dg-output-text name} {
+
+ global tool
+
+ if ![file exists $output_file] {
+ warning "$name compilation with $flags failed to produce executable"
+ } else {
+ set status -1
+ set result [${tool}_load $output_file]
+ set status [lindex $result 0]
+ set output [lindex $result 1]
+
+ if { $do_exp == "F" } {
+ setup_xfail "*-*-*"
+ }
+ if { "$status" == "pass" } {
+ pass "$name with $flags execution test"
+ verbose "Exec with $flags succeeded." 3
+
+ if { [llength ${dg-output-text}] > 1 } {
+ if { [lindex ${dg-output-text} 0] == "F" } {
+ setup_xfail "*-*-*"
+ }
+ set texttmp [lindex ${dg-output-text} 1]
+ if { ![regexp $texttmp ${output}] } {
+ fail "$name with $flags output pattern test, is ${output}, should match $texttmp"
+ verbose "Failed test with $flags for output pattern $texttmp" 3
+ } else {
+ pass "$name with $flags output pattern test, $texttmp"
+ verbose "Passed test with $flags for output pattern $texttmp" 3
+ }
+ unset texttmp
+ }
+ } elseif { "$status" == "fail" } {
+ # It would be nice to get some info out of errorCode.
+ if [info exists errorCode] {
+ verbose "Exec failed with $flags, errorCode: $errorCode" 3
+ } else {
+ verbose "Exec failed with $flags, errorCode not defined!" 3
+ }
+ fail "$name with $flags execution test"
+ } else {
+ $status "$name with $flags execution test"
+ }
+ }
+
+ return $result
+}
+
+
# Define gcc callbacks for dg.exp.
proc gcc-dg-test-1 { target_compile prog do_what extra_tool_flags } {
# Set up the compiler flags, based on what we're going to do.
+ global srcdir
+ global dg-do-what-default
+ # `dg-output-text' is a list of two elements: pass/fail and text.
+ # Leave second element off for now (indicates "don't perform test")
+ # FIXME: For now dg-output-text is a constant. Handle dg-output-text
+ # specified in test case.
+ set dg-output-text "P"
set options [list]
+ set dg-do-what [list ${dg-do-what-default} "" P]
# Tests should be able to use "dg-do repo". However, the dg test
# driver checks the argument to dg-do against a list of acceptable
@@ -90,6 +184,49 @@ proc gcc-dg-test-1 { target_compile prog
set do_what "repo"
}
+ # Define our own "special function" `unknown' so we catch spelling errors.
+ # But first rename the existing one so we can restore it afterwards.
+ catch {rename dg-save-unknown ""}
+ rename unknown dg-save-unknown
+ proc unknown { args } {
+ return -code error "unknown dg option: $args"
+ }
+
+ set name [dg-trim-dirname $srcdir $prog]
+ # If we couldn't rip $srcdir out of `prog' then just do the best we can.
+ # The point is to reduce the unnecessary noise in the logs. Don't strip
+ # out too much because different testcases with the same name can confuse
+ # `test-tool'.
+ if [string match "/*" $name] {
+ set name "[file tail [file dirname $prog]]/[file tail $prog]"
+ }
+
+ # Retreive flags to compare from testcase
+ set tmp [gcc-get-options $prog]
+ foreach op $tmp {
+ verbose "Processing option: $op" 3
+ set status [catch "$op" errmsg]
+ if { $status != 0 } {
+ if ![info exists errorInfo] {
+ perror "$name: $errmsg for \"$op\"\n"
+ }
+ unresolved "$errmsg for \"$op\""
+ return
+ }
+ }
+
+ # Restore normal error handling.
+ rename unknown ""
+ rename dg-save-unknown unknown
+
+ # Tests should be able to use "dg-do runcmp". However, the dg test
+ # driver checks the argument to dg-do against a list of acceptable
+ # options, and "runcmp" is not among them. Therefore, we resort to
+ # this ugly approach.
+ if { [info exists flags1] && [info exists flags2] && [string length $flags1] > 1 && [string length $flags2] > 1} {
+ set do_what "runcmp"
+ }
+
switch $do_what {
"preprocess" {
set compile_type "preprocess"
@@ -127,36 +264,100 @@ proc gcc-dg-test-1 { target_compile prog
# created or not. If it was, dg.exp will try to run it.
catch { remote_file build delete $output_file }
}
+ "runcmp" {
+
+ set compile_type "executable"
+
+ set output_file_1 "./[file rootname [file tail $prog]]-a.exe"
+ catch { remote_file build delete $output_file_1 }
+
+ set output_file_2 "./[file rootname [file tail $prog]]-b.exe"
+ catch { remote_file build delete $output_file_2 }
+ }
default {
perror "$do_what: not a valid dg-do keyword"
return ""
}
}
- if { $extra_tool_flags != "" } {
- lappend options "additional_flags=$extra_tool_flags"
- }
+ if { $do_what != "runcmp" } {
+ if { $extra_tool_flags != "" } {
+ lappend options "additional_flags=$extra_tool_flags"
+ }
- set comp_output [$target_compile "$prog" "$output_file" "$compile_type" $options]
+ set comp_output [$target_compile "$prog" "$output_file" "$compile_type" $options]
- # Look for an internal compiler error, which sometimes masks the fact
- # that we didn't get an expected error message. An ICE always fails,
- # there's no way to XFAIL it.
- if [string match "*internal compiler error*" $comp_output] {
- upvar 2 name name
- fail "$name (internal compiler error)"
- }
+ # Look for an internal compiler error, which sometimes masks the fact
+ # that we didn't get an expected error message. An ICE always fails,
+ # there's no way to XFAIL it.
+ if [string match "*internal compiler error*" $comp_output] {
+ upvar 2 name name
+ fail "$name (internal compiler error)"
+ }
- if { $do_what == "repo" } {
- set object_file "$output_file"
- set output_file "[file rootname [file tail $prog]].exe"
- set comp_output \
- [ concat $comp_output \
- [$target_compile "$object_file" "$output_file" \
- "executable" $options] ]
- }
+ if { $do_what == "repo" } {
+ set object_file "$output_file"
+ set output_file "[file rootname [file tail $prog]].exe"
+ set comp_output \
+ [ concat $comp_output \
+ [$target_compile "$object_file" "$output_file" \
+ "executable" $options] ]
+ }
- return [list $comp_output $output_file]
+ return [list $comp_output $output_file]
+
+ } else {
+
+ global dg-interpreter-batch-mode
+ upvar output_1 output_1
+ upvar output_2 output_2
+ upvar status_1 status_1
+ upvar status_2 status_2
+
+ set comp_output_1 [$target_compile "$prog" "$output_file_1" "$compile_type" additional_flags=$flags1]
+ set comp_output_2 [$target_compile "$prog" "$output_file_2" $compile_type additional_flags=$flags2]
+
+ chk_compile_time_err $comp_output_1 $name $flags1
+ chk_compile_time_err $comp_output_2 $name $flags2
+
+ # Compare the compilation output of 2 compiles
+ if [string compare $comp_output_1 $comp_output_2] {
+ fail "$name comparing output of compilation with $flags1 and $flags2"
+ }
+
+ set results_1 [chk_run_time_status $output_file_1 $flags1 [lindex ${dg-do-what} 2] ${dg-output-text} $name]
+ set results_2 [chk_run_time_status $output_file_2 $flags2 [lindex ${dg-do-what} 2] ${dg-output-text} $name]
+
+ set status_1 [lindex $results_1 0]
+ set output_1 [lindex $results_1 1]
+
+ set status_2 [lindex $results_2 0]
+ set output_2 [lindex $results_2 1]
+
+ # Compare the status of 2 runs
+ if [string compare $status_1 $status_2] {
+ fail "$name comparing status of runs with $flags1 and $flags2"
+ }
+
+ # Compare the output 2 runs
+ set message "$name comparing output of runs with $flags1 and $flags2"
+ if [string compare $output_1 $output_2] {
+ fail $message
+ } else {
+ pass $message
+ }
+
+ # Do some final clean up.
+ # When testing an interpreter, we don't compile something and leave an
+ # output file.
+ if { ${dg-interpreter-batch-mode} == 0 } {
+ #We only delete one output_file, the other is deleted in
+ #the dejagnu caller.
+ catch "exec rm -f $output_file_2"
+ }
+
+ return [list $comp_output_1 $output_file_1]
+ }
}
proc gcc-dg-test { prog do_what extra_tool_flags } {
More information about the Gcc-patches
mailing list