| # Copyright (C) 2012-2018 Free Software Foundation, Inc. |
| |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 3 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with GCC; see the file COPYING3. If not see |
| # <http://www.gnu.org/licenses/>. |
| |
| # Test using the DMD testsuite. |
| # Load support procs. |
| load_lib gdc-dg.exp |
| |
| # |
| # Convert DMD arguments to GDC equivalent |
| # |
| |
| proc gdc-convert-args { args } { |
| set out "" |
| |
| foreach arg [split [lindex $args 0] " "] { |
| # List of switches kept in ASCII collated order. |
| if { [regexp -- {^-I([\w+/-]+)} $arg pattern path] } { |
| lappend out "-I$path" |
| |
| } elseif { [regexp -- {^-J([\w+/-]+)} $arg pattern path] } { |
| lappend out "-J$path" |
| |
| } elseif [string match "-allinst" $arg] { |
| lappend out "-fall-instantiations" |
| |
| } elseif { [string match "-boundscheck" $arg] |
| || [string match "-boundscheck=on" $arg] } { |
| lappend out "-fbounds-check" |
| |
| } elseif { [string match "-boundscheck=off" $arg] |
| || [string match "-noboundscheck" $arg] } { |
| lappend out "-fno-bounds-check" |
| |
| } elseif [string match "-boundscheck=safeonly" $arg] { |
| lappend out "-fbounds-check=safeonly" |
| |
| } elseif [string match "-c" $arg] { |
| lappend out "-c" |
| |
| } elseif [string match "-d" $arg] { |
| lappend out "-Wno-deprecated" |
| |
| } elseif [string match "-de" $arg] { |
| lappend out "-Wdeprecated" |
| lappend out "-Werror" |
| |
| } elseif [string match "-debug" $arg] { |
| lappend out "-fdebug" |
| |
| } elseif [regexp -- {^-debug=(\w+)} $arg pattern value] { |
| lappend out "-fdebug=$value" |
| |
| } elseif [string match "-dip1000" $arg] { |
| lappend out "-ftransition=dip1000" |
| |
| } elseif [string match "-dip25" $arg] { |
| lappend out "-ftransition=dip25" |
| |
| } elseif [string match "-dw" $arg] { |
| lappend out "-Wdeprecated" |
| lappend out "-Wno-error" |
| |
| } elseif [string match "-fPIC" $arg] { |
| lappend out "-fPIC" |
| |
| } elseif { [string match "-g" $arg] |
| || [string match "-gc" $arg] } { |
| lappend out "-g" |
| |
| } elseif [string match "-inline" $arg] { |
| lappend out "-finline-functions" |
| |
| } elseif [string match "-main" $arg] { |
| lappend out "-fmain" |
| |
| } elseif [regexp -- {^-mv=([\w+=./-]+)} $arg pattern value] { |
| lappend out "-fmodule-file=$value" |
| |
| } elseif [string match "-O" $arg] { |
| lappend out "-O2" |
| |
| } elseif [string match "-release" $arg] { |
| lappend out "-frelease" |
| |
| } elseif [regexp -- {^-transition=(\w+)} $arg pattern value] { |
| lappend out "-ftransition=$value" |
| |
| } elseif [string match "-unittest" $arg] { |
| lappend out "-funittest" |
| |
| } elseif [string match "-verrors=spec" $arg] { |
| lappend out "-Wspeculative" |
| |
| } elseif [regexp -- {^-verrors=(\d+)} $arg pattern num] { |
| lappend out "-fmax-errors=$num" |
| |
| } elseif [regexp -- {^-version=(\w+)} $arg pattern value] { |
| lappend out "-fversion=$value" |
| |
| } elseif [string match "-vtls" $arg] { |
| lappend out "-ftransition=tls" |
| |
| } elseif [string match "-w" $arg] { |
| lappend out "-Wall" |
| lappend out "-Werror" |
| |
| } elseif [string match "-wi" $arg] { |
| lappend out "-Wall" |
| lappend out "-Wno-error" |
| |
| } else { |
| # print "Unhandled Argument: $arg" |
| } |
| } |
| |
| return $out |
| } |
| |
| proc gdc-copy-extra { base extra } { |
| # Split base, folder/file. |
| set type [file dirname $extra] |
| |
| # print "Filename: $base - $extra" |
| |
| set fdin [open $base/$extra r] |
| fconfigure $fdin -encoding binary |
| |
| file mkdir $type |
| set fdout [open $extra w] |
| fconfigure $fdout -encoding binary |
| |
| while { [gets $fdin copy_line] >= 0 } { |
| set out_line $copy_line |
| puts $fdout $out_line |
| } |
| |
| close $fdin |
| close $fdout |
| |
| return $extra |
| } |
| |
| # |
| # Translate DMD test directives to dejagnu equivalent. |
| # |
| # COMPILE_SEPARATELY: Not handled. |
| # EXECUTE_ARGS: Parameters to add to the execution of the test. |
| # COMPILED_IMPORTS: List of modules files that are imported by the main |
| # source file that should be included in compilation. |
| # Currently handled the same as EXTRA_SOURCES. |
| # EXTRA_SOURCES: List of extra sources to build and link along with |
| # the test. |
| # EXTRA_FILES: List of extra files to copy for the test runs. |
| # PERMUTE_ARGS: The set of arguments to permute in multiple compiler |
| # invocations. An empty set means only one permutation |
| # with no arguments. |
| # TEST_OUTPUT: The output expected from the compilation. |
| # POST_SCRIPT: Not handled. |
| # REQUIRED_ARGS: Arguments to add to the compiler command line. |
| # DISABLED: Not handled. |
| # |
| |
| proc dmd2dg { base test } { |
| global DEFAULT_DFLAGS |
| global PERMUTE_ARGS |
| global GDC_EXECUTE_ARGS |
| |
| set PERMUTE_ARGS $DEFAULT_DFLAGS |
| set GDC_EXECUTE_ARGS "" |
| |
| # Split base, folder/file. |
| set type [file dirname $test] |
| |
| # print "Filename: $base - $test" |
| |
| set fdin [open $base/$test r] |
| #fconfigure $fdin -encoding binary |
| |
| file mkdir $type |
| set fdout [open $test w] |
| #fconfigure $fdout -encoding binary |
| |
| while { [gets $fdin copy_line] >= 0 } { |
| set out_line $copy_line |
| |
| if [regexp -- {COMPILE_SEPARATELY} $copy_line] { |
| # COMPILE_SEPARATELY is not handled. |
| regsub -- {COMPILE_SEPARATELY.*$} $copy_line "" out_line |
| |
| } elseif [regexp -- {DISABLED} $copy_line] { |
| # DISABLED is not handled. |
| regsub -- {DISABLED.*$} $copy_line "" out_line |
| |
| } elseif [regexp -- {POST_SCRIPT} $copy_line] { |
| # POST_SCRIPT is not handled |
| regsub -- {POST_SCRIPT.*$} $copy_line "" out_line |
| |
| } elseif [regexp -- {PERMUTE_ARGS\s*:\s*(.*)} $copy_line match args] { |
| # PERMUTE_ARGS is handled by gdc-do-test. |
| set PERMUTE_ARGS [gdc-convert-args $args] |
| regsub -- {PERMUTE_ARGS.*$} $copy_line "" out_line |
| |
| } elseif [regexp -- {EXECUTE_ARGS\s*:\s*(.*)} $copy_line match args] { |
| # EXECUTE_ARGS is handled by gdc_load. |
| foreach arg $args { |
| lappend GDC_EXECUTE_ARGS $arg |
| } |
| regsub -- {EXECUTE_ARGS.*$} $copy_line "" out_line |
| |
| } elseif [regexp -- {REQUIRED_ARGS\s*:\s*(.*)} $copy_line match args] { |
| # Convert all listed arguments to from dmd to gdc-style. |
| set new_option "{ dg-additional-options \"[gdc-convert-args $args]\" }" |
| regsub -- {REQUIRED_ARGS.*$} $copy_line $new_option out_line |
| |
| } elseif [regexp -- {EXTRA_SOURCES\s*:\s*(.*)} $copy_line match sources] { |
| # Copy all sources to the testsuite build directory. |
| foreach import $sources { |
| # print "Import: $base $type/$import" |
| gdc-copy-extra $base "$type/$import" |
| } |
| set new_option "{ dg-additional-sources \"$sources\" }" |
| regsub -- {EXTRA_SOURCES.*$} $copy_line $new_option out_line |
| |
| } elseif [regexp -- {EXTRA_CPP_SOURCES\s*:\s*(.*)} $copy_line match sources] { |
| # Copy all sources to the testsuite build directory. |
| foreach import $sources { |
| # print "Import: $base $type/$import" |
| gdc-copy-extra $base "$type/$import" |
| } |
| set new_option "{ dg-additional-sources \"$sources\" }" |
| regsub -- {EXTRA_CPP_SOURCES.*$} $copy_line $new_option out_line |
| |
| } elseif [regexp -- {EXTRA_FILES\s*:\s*(.*)} $copy_line match files] { |
| # Copy all files to the testsuite build directory. |
| foreach import $files { |
| # print "Import: $base $type/$import" |
| gdc-copy-extra $base "$type/$import" |
| } |
| set new_option "{ dg-additional-files \"$files\" }" |
| regsub -- {EXTRA_FILES.*$} $copy_line $new_option out_line |
| |
| } elseif [regexp -- {COMPILED_IMPORTS\s*:\s*(.*)} $copy_line match sources] { |
| # Copy all sources to the testsuite build directory. |
| foreach import $sources { |
| # print "Import: $base $type/$import" |
| gdc-copy-extra $base "$type/$import" |
| } |
| set new_option "{ dg-additional-sources \"$sources\" }" |
| regsub -- {COMPILED_IMPORTS.*$} $copy_line $new_option out_line |
| |
| } |
| |
| puts $fdout $out_line |
| } |
| |
| # Add specific options for test type |
| |
| # DMD's testsuite is extremely verbose, compiler messages from constructs |
| # such as pragma(msg, ...) would otherwise cause tests to fail. |
| set out_line "// { dg-prune-output .* }" |
| puts $fdout $out_line |
| |
| # Since GCC 6-20160131 blank lines are not allowed in the output by default. |
| dg-allow-blank-lines-in-output { 1 } |
| |
| # Compilable files are successful if an output is generated. |
| # Fail compilable are successful if an output is not generated. |
| # Runnable must compile, link, and return 0 to be successful by default. |
| switch [file dirname $test] { |
| runnable { |
| if ![isnative] { |
| set out_line "// { dg-final { output-exists } }" |
| puts $fdout $out_line |
| } |
| } |
| |
| compilable { |
| set out_line "// { dg-final { output-exists } }" |
| puts $fdout $out_line |
| } |
| |
| fail_compilation { |
| set out_line "// { dg-final { output-exists-not } }" |
| puts $fdout $out_line |
| } |
| } |
| |
| close $fdin |
| close $fdout |
| |
| return $test |
| } |
| |
| proc gdc-permute-options { options } { |
| set result { } |
| set n [expr 1<<[llength $options]] |
| for { set i 0 } { $i<$n } { incr i } { |
| set option "" |
| for { set j 0 } { $j<[llength $options] } { incr j } { |
| if [expr $i & 1 << $j] { |
| append option [lindex $options $j] |
| append option " " |
| } |
| } |
| lappend result $option |
| |
| } |
| return $result |
| } |
| |
| |
| proc gdc-do-test { } { |
| global srcdir subdir |
| global dg-do-what-default |
| global verbose |
| |
| # If a testcase doesn't have special options, use these. |
| global DEFAULT_DFLAGS |
| if ![info exists DEFAULT_DFLAGS] then { |
| set DEFAULT_DFLAGS "-g -O2 -frelease" |
| #set DEFAULT_DFLAGS "-O2" |
| } |
| |
| # These are special options to use on testcase, and override DEFAULT_DFLAGS |
| global PERMUTE_ARGS |
| |
| # Set if an extra option should be passed to link to shared druntime. |
| global SHARED_OPTION |
| |
| # Additional arguments for gdc_load |
| global GDC_EXECUTE_ARGS |
| |
| # Initialize `dg'. |
| dg-init |
| |
| # Main loop. |
| |
| # set verbose 1 |
| # set dg-final-code "" |
| # Find all tests and pass to routine. |
| foreach test [lsort [find $srcdir/$subdir *]] { |
| regexp -- "(.*)/(.+)/(.+)\.(.+)$" $test match base dir name ext |
| |
| # Skip invalid test directory |
| if { [lsearch "runnable compilable fail_compilation" $dir] == -1 } { |
| continue |
| } |
| |
| # Skip invalid test extensions |
| if { [lsearch "d" $ext] == -1 } { |
| continue |
| } |
| |
| # Convert to DG test. |
| set imports [format "-I%s/%s" $base $dir] |
| set filename [dmd2dg $base $dir/$name.$ext] |
| |
| if { $dir == "runnable" } { |
| append PERMUTE_ARGS " $SHARED_OPTION" |
| } |
| set options [gdc-permute-options $PERMUTE_ARGS] |
| |
| switch $dir { |
| runnable { |
| for { set i 0 } { $i<[llength $options] } { incr i } { |
| set flags [lindex $options $i] |
| if [isnative] { |
| set dg-do-what-default "run" |
| } else { |
| set dg-do-what-default "link" |
| } |
| gdc-dg-runtest $filename $flags $imports |
| } |
| } |
| |
| compilable { |
| for { set i 0 } { $i<[llength $options] } { incr i } { |
| set flags [lindex $options $i] |
| #set dg-do-what-default "compile" |
| set dg-do-what-default "assemble" |
| gdc-dg-runtest $filename $flags $imports |
| } |
| } |
| |
| fail_compilation { |
| for { set i 0 } { $i<[llength $options] } { incr i } { |
| set flags [lindex $options $i] |
| set dg-do-what-default "assemble" |
| gdc-dg-runtest $filename $flags $imports |
| } |
| } |
| } |
| |
| # Cleanup |
| #file delete $filename |
| } |
| |
| # All done. |
| dg-finish |
| } |
| |
| gdc-do-test |
| |