diff --git a/Makefile b/Makefile index 55eeb019..54734f39 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,6 @@ CLANG_LIBS = -lclangFrontend -lclangDriver \ ISPC_LIBS=$(shell llvm-config --ldflags) $(CLANG_LIBS) $(LLVM_LIBS) \ -lpthread -ldl -ISPC_TEST_LIBS=$(shell llvm-config --ldflags) $(LLVM_LIBS) \ - -lpthread -ldl LLVM_CXXFLAGS=$(shell llvm-config --cppflags) LLVM_VERSION=LLVM_$(shell llvm-config --version | sed s/\\./_/) @@ -73,7 +71,7 @@ OBJS=$(addprefix objs/, $(CXX_SRC:.cpp=.o) $(BUILTINS_SRC:.ll=.o) \ builtins-c-32.o builtins-c-64.o stdlib_ispc.o $(BISON_SRC:.yy=.o) \ $(FLEX_SRC:.ll=.o)) -default: ispc ispc_test +default: ispc .PHONY: dirs clean depend doxygen print_llvm_src .PRECIOUS: objs/builtins-%.cpp @@ -92,7 +90,7 @@ print_llvm_src: @echo Using LLVM `llvm-config --version` from `llvm-config --libdir` clean: - /bin/rm -rf objs ispc ispc_test + /bin/rm -rf objs ispc doxygen: /bin/rm -rf docs/doxygen @@ -102,10 +100,6 @@ ispc: print_llvm_src dirs $(OBJS) @echo Creating ispc executable @$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(ISPC_LIBS) -ispc_test: dirs ispc_test.cpp - @echo Creating ispc_test executable - @$(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ ispc_test.cpp $(ISPC_TEST_LIBS) - objs/%.o: %.cpp @echo Compiling $< @$(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/ispc.sln b/ispc.sln index 0f48203a..8febee18 100755 --- a/ispc.sln +++ b/ispc.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ispc", "ispc.vcxproj", "{9861F490-F516-480C-B63C-D62A77AFA9D5}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ispc_test", "ispc_test.vcxproj", "{92547BA8-BE86-4E78-8799-1D72A70E5831}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -15,9 +13,6 @@ Global {9861F490-F516-480C-B63C-D62A77AFA9D5}.Debug|Win32.Build.0 = Debug|Win32 {9861F490-F516-480C-B63C-D62A77AFA9D5}.Release|Win32.ActiveCfg = Release|Win32 {9861F490-F516-480C-B63C-D62A77AFA9D5}.Release|Win32.Build.0 = Release|Win32 - {92547BA8-BE86-4E78-8799-1D72A70E5831}.Debug|Win32.ActiveCfg = Debug|Win32 - {92547BA8-BE86-4E78-8799-1D72A70E5831}.Debug|Win32.Build.0 = Debug|Win32 - {92547BA8-BE86-4E78-8799-1D72A70E5831}.Release|Win32.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ispc_test.cpp b/ispc_test.cpp deleted file mode 100644 index a72081c4..00000000 --- a/ispc_test.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* - Copyright (c) 2010-2011, Intel Corporation - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#define _CRT_SECURE_NO_WARNINGS - -#if defined(_WIN32) || defined(_WIN64) -#define ISPC_IS_WINDOWS -#elif defined(__linux__) -#define ISPC_IS_LINUX -#elif defined(__APPLE__) -#define ISPC_IS_APPLE -#endif - -#ifdef ISPC_IS_WINDOWS -#define NOMINMAX -#include -#endif -#include -#include -#include -#include -#ifdef ISPC_IS_LINUX -#include -#endif - -#ifdef ISPC_HAVE_SVML -#include -extern "C" { - extern __m128 __svml_sinf4(__m128); - extern __m128 __svml_cosf4(__m128); - extern __m128 __svml_sincosf4(__m128 *,__m128); - extern __m128 __svml_tanf4(__m128); - extern __m128 __svml_atanf4(__m128); - extern __m128 __svml_atan2f4(__m128, __m128); - extern __m128 __svml_expf4(__m128); - extern __m128 __svml_logf4(__m128); - extern __m128 __svml_powf4(__m128, __m128); -} -#endif - -#include -#include -#include -#include -#include -#include -#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) - #include - #include -#else - #include - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -bool shouldFail = false; - -extern "C" { - void ISPCLaunch(void **, void *, void *, int32_t); - void ISPCSync(void *); - void *ISPCAlloc(void **, int64_t size, int32_t alignment); -} - -void ISPCLaunch(void **handle, void *func, void *data, int32_t count) { - *handle = (void *)0xdeadbeef; - typedef void (*TaskFuncType)(void *, int, int, int, int); - TaskFuncType tft = (TaskFuncType)(func); - for (int i = 0; i < count; ++i) - tft(data, 0, 1, i, count); -} - - -void ISPCSync(void *) { -} - - -void *ISPCAlloc(void **handle, int64_t size, int32_t alignment) { - *handle = (void *)0xdeadbeef; - // leak time! -#ifdef ISPC_IS_WINDOWS - return _aligned_malloc((size_t)size, alignment); -#endif -#ifdef ISPC_IS_LINUX - return memalign(alignment, size); -#endif -#ifdef ISPC_IS_APPLE - void *mem = malloc(size + (alignment-1) + sizeof(void*)); - char *amem = ((char*)mem) + sizeof(void*); - amem = amem + uint32_t(alignment - (reinterpret_cast(amem) & - (alignment - 1))); - ((void**)amem)[-1] = mem; - return amem; -#endif -} - - -static void usage(int ret) { - fprintf(stderr, "usage: ispc_test\n"); - fprintf(stderr, "\t[-h/--help]\tprint help\n"); - fprintf(stderr, "\t[-f]\t\tindicates that test is expected to fail\n"); - fprintf(stderr, "\t\n"); - exit(ret); -} - -static void svml_missing() { - fprintf(stderr, "Program called unavailable SVML function!\n"); - exit(1); -} - -// On Windows, sin() is an overloaded function, so we need an unambiguous -// function we can take the address of when wiring up the external references -// below. - -double Sin(double x) { return sin(x); } -double Cos(double x) { return cos(x); } -double Tan(double x) { return tan(x); } -double Atan(double x) { return atan(x); } -double Atan2(double y, double x) { return atan2(y, x); } -double Pow(double a, double b) { return pow(a, b); } -double Exp(double x) { return exp(x); } -double Log(double x) { return log(x); } - -static bool lRunTest(const char *fn) { - llvm::LLVMContext *ctx = new llvm::LLVMContext; - - llvm::OwningPtr buf; - llvm::error_code err = llvm::MemoryBuffer::getFileOrSTDIN(fn, buf); - if (err) { - fprintf(stderr, "Unable to open file \"%s\": %s\n", fn, err.message().c_str()); - delete ctx; - return false; - } - std::string bcErr; - llvm::Module *module = llvm::ParseBitcodeFile(buf.get(), *ctx, &bcErr); - - if (!module) { - fprintf(stderr, "Bitcode reader failed for \"%s\": %s\n", fn, bcErr.c_str()); - delete ctx; - return false; - } - - std::string eeError; -#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) - llvm::EngineBuilder engineBuilder(module); - engineBuilder.setErrorStr(&eeError); - engineBuilder.setEngineKind(llvm::EngineKind::JIT); -#if 0 - std::vector attributes; - if (target != NULL && !strcmp(target, "avx")) - attributes.push_back("+avx"); - engineBuilder.setMAttrs(attributes); - engineBuilder.setUseMCJIT(true); -#endif - llvm::ExecutionEngine *ee = engineBuilder.create(); -#else - llvm::ExecutionEngine *ee = llvm::ExecutionEngine::createJIT(module, &eeError); -#endif - if (!ee) { - fprintf(stderr, "Unable to create ExecutionEngine: %s\n", eeError.c_str()); - return false; - } - - llvm::Function *func; -#define DO_FUNC(FUNC ,FUNCNAME) \ - if ((func = module->getFunction(FUNCNAME)) != NULL) \ - ee->addGlobalMapping(func, (void *)FUNC) - DO_FUNC(ISPCLaunch, "ISPCLaunch"); - DO_FUNC(ISPCSync, "ISPCSync"); - DO_FUNC(ISPCAlloc, "ISPCAlloc"); - DO_FUNC(putchar, "putchar"); - DO_FUNC(printf, "printf"); - DO_FUNC(fflush, "fflush"); - DO_FUNC(sinf, "sinf"); - DO_FUNC(cosf, "cosf"); - DO_FUNC(tanf, "tanf"); - DO_FUNC(atanf, "atanf"); - DO_FUNC(atan2f, "atan2f"); - DO_FUNC(powf, "powf"); - DO_FUNC(expf, "expf"); - DO_FUNC(logf, "logf"); - DO_FUNC(Sin, "sin"); - DO_FUNC(Cos, "cos"); - DO_FUNC(Tan, "tan"); - DO_FUNC(Atan, "atan"); - DO_FUNC(Atan2, "atan2"); - DO_FUNC(Pow, "pow"); - DO_FUNC(Exp, "exp"); - DO_FUNC(Log, "log"); - DO_FUNC(memset, "memset"); -#ifdef ISPC_IS_APPLE - DO_FUNC(memset_pattern4, "memset_pattern4"); - DO_FUNC(memset_pattern8, "memset_pattern8"); - DO_FUNC(memset_pattern16, "memset_pattern16"); -#endif - -#ifdef ISPC_HAVE_SVML -#define DO_SVML(FUNC ,FUNCNAME) \ - if ((func = module->getFunction(FUNCNAME)) != NULL) \ - ee->addGlobalMapping(func, (void *)FUNC) -#else -#define DO_SVML(FUNC, FUNCNAME) \ - if ((func = module->getFunction(FUNCNAME)) != NULL) \ - ee->addGlobalMapping(func, (void *)svml_missing) -#endif - - DO_SVML(__svml_sinf4, "__svml_sinf4"); - DO_SVML(__svml_cosf4, "__svml_cosf4"); - DO_SVML(__svml_sincosf4, "__svml_sincosf4"); - DO_SVML(__svml_tanf4, "__svml_tanf4"); - DO_SVML(__svml_atanf4, "__svml_atanf4"); - DO_SVML(__svml_atan2f4, "__svml_atan2f4"); - DO_SVML(__svml_expf4, "__svml_expf4"); - DO_SVML(__svml_logf4, "__svml_logf4"); - DO_SVML(__svml_powf4, "__svml_powf4"); - - // figure out the vector width in the compiled code - func = module->getFunction("width"); - if (!func) { - fprintf(stderr, "No width() function found!\n"); - return false; - } - int width; - { - typedef int (*PFN)(); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - width = pfn(); - assert(width == 4 || width == 8 || width == 12 || width == 16); - } - - // find the value that returns the desired result - func = module->getFunction("result"); - bool foundResult = (func != NULL); - float result[16]; - for (int i = 0; i < 16; ++i) - result[i] = 0; - if (foundResult) { - typedef void (*PFN)(float *); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - pfn(result); - } - else - fprintf(stderr, "Warning: no result() function found.\n"); - - // try to find a function to run - float returned[16]; - for (int i = 0; i < 16; ++i) - returned[i] = 0; - float vfloat[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; - double vdouble[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; - int vint[16] = { 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32 }; - int vint2[16] = { 5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; - - if ((func = module->getFunction("f_v")) != NULL) { - typedef void (*PFN)(float *); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - pfn(returned); - } - else if ((func = module->getFunction("f_f")) != NULL) { - typedef void (*PFN)(float *, float *); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - llvm::verifyFunction(*func); - pfn(returned, vfloat); - } - else if ((func = module->getFunction("f_fu")) != NULL) { - typedef void (*PFN)(float *, float *, float fu); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - llvm::verifyFunction(*func); - pfn(returned, vfloat, 5.); - } - else if ((func = module->getFunction("f_fi")) != NULL) { - typedef void (*PFN)(float *, float *, int *); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - pfn(returned, vfloat, vint); - } - else if ((func = module->getFunction("f_du")) != NULL) { - typedef void (*PFN)(float *, double *, double); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - pfn(returned, vdouble, 5.); - } - else if ((func = module->getFunction("f_duf")) != NULL) { - typedef void (*PFN)(float *, double *, float); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - pfn(returned, vdouble, 5.f); - } - else if ((func = module->getFunction("f_di")) != NULL) { - typedef void (*PFN)(float *, double *, int *); - PFN pfn = reinterpret_cast(ee->getPointerToFunction(func)); - pfn(returned, vdouble, vint2); - } - else { - fprintf(stderr, "Unable to find runnable function in file \"%s\"\n", fn); - return false; - } - - // see if we got the right result - bool resultsMatch = true; - if (foundResult) { - for (int i = 0; i < width; ++i) - if (returned[i] != result[i]) { - resultsMatch = false; - fprintf(stderr, "Test \"%s\" RETURNED %d: %g / %a EXPECTED %g / %a\n", - fn, i, returned[i], returned[i], result[i], result[i]); - } - } - else { - for (int i = 0; i < width; ++i) - fprintf(stderr, "Test \"%s\" returned %d: %g / %a\n", - fn, i, returned[i], returned[i]); - } - if (foundResult && shouldFail && resultsMatch) - fprintf(stderr, "Test %s unexpectedly passed\n", fn); - - delete ee; - delete ctx; - - return foundResult && resultsMatch; -} - - -int main(int argc, char *argv[]) { - llvm::InitializeNativeTarget(); -#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) - LLVMLinkInJIT(); -#endif - - const char *filename = NULL; - for (int i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) - usage(0); - if (!strcmp(argv[i], "-f")) - shouldFail = true; - else - filename = argv[i]; - } - - return (lRunTest(filename) == true) ? 0 : 1; -} diff --git a/ispc_test.vcxproj b/ispc_test.vcxproj deleted file mode 100755 index 1dd885bb..00000000 --- a/ispc_test.vcxproj +++ /dev/null @@ -1,90 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - {92547BA8-BE86-4E78-8799-1D72A70E5831} - Win32Proj - ispc_test - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - LLVM_3_0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(LLVM_INSTALL_DIR)/include - 4146;4355;4800 - - - Console - true - $(LLVM_INSTALL_DIR)/lib - LLVMAnalysis.lib;LLVMArchive.lib;LLVMAsmPrinter.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMExecutionEngine.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipa.lib;LLVMipo.lib;LLVMJIT.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCParser.lib;LLVMObject.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSupport.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMX86ASMPrinter.lib;LLVMX86ASMParser.lib;LLVMX86Utils.lib;LLVMX86CodeGen.lib;LLVMX86Disassembler.lib;LLVMX86Desc.lib;LLVMX86Info.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - LLVM_3_0;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(LLVM_INSTALL_DIR)/include - 4146;4355;4800 - - - Console - true - true - true - $(LLVM_INSTALL_DIR)/lib - LLVMAnalysis.lib;LLVMArchive.lib;LLVMAsmPrinter.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMExecutionEngine.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipa.lib;LLVMipo.lib;LLVMJIT.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCParser.lib;LLVMObject.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSupport.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMX86ASMPrinter.lib;LLVMX86ASMParser.lib;LLVMX86Utils.lib;LLVMX86CodeGen.lib;LLVMX86Disassembler.lib;LLVMX86Desc.lib;LLVMX86Info.lib;%(AdditionalDependencies) - - - - - - diff --git a/run_tests.py b/run_tests.py index a487a9de..8997d13c 100755 --- a/run_tests.py +++ b/run_tests.py @@ -2,9 +2,6 @@ # test-running driver for ispc -# TODO: windows support (mostly should be calling CL.exe rather than gcc -# for static linking?) - from optparse import OptionParser import multiprocessing from ctypes import c_int @@ -23,9 +20,6 @@ import platform parser = OptionParser() parser.add_option("-r", "--random-shuffle", dest="random", help="Randomly order tests", default=False, action="store_true") -parser.add_option("-s", "--static-exe", dest="static_exe", - help="Create and run a regular executable for each test (rather than using the LLVM JIT).", - default=False, action="store_true") parser.add_option('-t', '--target', dest='target', help='Set compilation target (sse2, sse2-x2, sse4, sse4-x2, avx, avx-x2)', default="sse4") @@ -52,7 +46,6 @@ if (options.random): # counter total_tests = 0 -finished_tests_counter = multiprocessing.Value(c_int) # We'd like to use the Lock class from the multiprocessing package to # serialize accesses to finished_tests_counter. Unfortunately, the version of @@ -60,7 +53,10 @@ finished_tests_counter = multiprocessing.Value(c_int) # http://bugs.python.org/issue5261. Therefore, we use the (deprecated but # still available) mutex class. #finished_tests_counter_lock = multiprocessing.Lock() -finished_tests_mutex = mutex.mutex() +if not (platform.system() == 'Windows' or + 'CYGWIN_NT' in platform.system()): + finished_tests_mutex = mutex.mutex() + finished_tests_counter = multiprocessing.Value(c_int) # utility routine to print an update on the number of tests that have been # finished. Should be called with the mutex (or lock) held.. @@ -80,20 +76,118 @@ fnull = open(os.devnull, 'w') # run the commands in cmd_list def run_cmds(cmd_list, filename, expect_failure): for cmd in cmd_list: - if expect_failure: - failed = (subprocess.call(cmd, shell = True, stdout = fnull, stderr = fnull) != 0) - else: - failed = (os.system(cmd) != 0) + sp = subprocess.Popen(shlex.split(cmd), stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + output = sp.communicate()[0] + failed = (sp.returncode != 0) if failed: break - surprise = ((expect_failure and not failed) or (not expect_failure and failed)) + surprise = ((expect_failure and not failed) or + (not expect_failure and failed)) if surprise == True: print "Test %s %s " % \ (filename, "unexpectedly passed" if expect_failure else "failed") + print "Output %s" % output return surprise +def run_test(filename): + # is this a test to make sure an error is issued? + error_count = 0 + want_error = (filename.find("tests_errors") != -1) + if want_error == True: + ispc_cmd = "ispc --werror --nowrap %s --arch=%s --target=%s" % \ + (filename, options.arch, options.target) + sp = subprocess.Popen(shlex.split(ispc_cmd), stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + output = sp.communicate()[1] + got_error = (sp.returncode != 0) + + # figure out the error message we're expecting + file = open(filename, 'r') + firstline = file.readline() + firstline = string.replace(firstline, "//", "") + firstline = string.lstrip(firstline) + firstline = string.rstrip(firstline) + file.close() + + if (output.find(firstline) == -1): + print "Didn't see expected error message \"%s\" from " + \ + "test %s.\nActual outout: %s" % \ + (firstline, filename, output) + error_count += 1 + elif got_error == False: + print "Unexpectedly no errors issued from test %s" % filename + error_count += 1 + else: + # do we expect this test to fail? + should_fail = (filename.find("failing_") != -1) + + # We need to figure out the signature of the test + # function that this test has. + sig2def = { "f_v(" : 0, "f_f(" : 1, "f_fu(" : 2, "f_fi(" : 3, + "f_du(" : 4, "f_duf(" : 5, "f_di(" : 6 } + file = open(filename, 'r') + match = -1 + for line in file: + # look for lines with 'export'... + if line.find("export") == -1: + continue + # one of them should have a function with one of the + # declarations in sig2def + for pattern, ident in sig2def.items(): + if line.find(pattern) != -1: + match = ident + break + file.close() + if match == -1: + print "Fatal error: unable to find function signature " + \ + "in test %s" % filename + error_count += 1 + else: + if (platform.system() == 'Windows' or + 'CYGWIN_NT' in platform.system()): + obj_name = "%s.obj" % filename + exe_name = "%s.exe" % filename + cc_cmd = "cl /nologo test_static.cpp /DTEST_SIG=%d %s.obj /Fe%s" % \ + (match, filename, exe_name) + if should_fail: + cc_cmd += " /DEXPECT_FAILURE" + else: + obj_name = "%s.o" % filename + exe_name = "%s.run" % filename + if options.arch == 'x86': + gcc_arch = '-m32' + else: + gcc_arch = '-m64' + cc_cmd = "g++ %s test_static.cpp -DTEST_SIG=%d %s.o -o %s" % \ + (gcc_arch, match, filename, exe_name) + if platform.system() == 'Darwin': + cc_cmd += ' -Wl,-no_pie' + if should_fail: + cc_cmd += " -DEXPECT_FAILURE" + + ispc_cmd = "ispc --woff %s -o %s --arch=%s --target=%s" % \ + (filename, obj_name, options.arch, options.target) + if options.no_opt: + ispc_cmd += " -O0" + + # compile the ispc code, make the executable, and run it... + error_count += run_cmds([ispc_cmd, cc_cmd, exe_name], \ + filename, should_fail) + + # clean up after running the test + try: + os.unlink(exe_name) + os.unlink(obj_name) + except: + None + + return error_count + # pull tests to run from the given queue and run them. Multiple copies of # this function will be running in parallel across all of the CPU cores of # the system. @@ -104,100 +198,7 @@ def run_tasks_from_queue(queue): if (filename == 'STOP'): sys.exit(error_count) - # is this a test to make sure an error is issued? - want_error = (filename.find("tests_errors") != -1) - if want_error == True: - ispc_cmd = "ispc --werror --nowrap %s --arch=%s --target=%s" % \ - (filename, options.arch, options.target) - sp = subprocess.Popen(shlex.split(ispc_cmd), stdin=None, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - output = sp.communicate()[1] - got_error = (sp.returncode != 0) - - # figure out the error message we're expecting - file = open(filename, 'r') - firstline = file.readline() - firstline = string.replace(firstline, "//", "") - firstline = string.lstrip(firstline) - firstline = string.rstrip(firstline) - file.close() - - if (output.find(firstline) == -1): - print "Didn't see expected error message \"%s\" from test %s.\nActual outout: %s" % \ - (firstline, filename, output) - error_count += 1 - elif got_error == False: - print "Unexpectedly no errors issued from test %s" % filename - error_count += 1 - continue - - # do we expect this test to fail? - should_fail = (filename.find("failing_") != -1) - - if options.static_exe == True: - # if the user wants us to build a static executable to run for - # this test, we need to figure out the signature of the test - # function that this test has. - sig2def = { "f_v(" : 0, "f_f(" : 1, "f_fu(" : 2, "f_fi(" : 3, - "f_du(" : 4, "f_duf(" : 5, "f_di(" : 6 } - file = open(filename, 'r') - match = -1 - for line in file: - # look for lines with 'export'... - if line.find("export") == -1: - continue - # one of them should have a function with one of the - # declarations in sig2def - for pattern, ident in sig2def.items(): - if line.find(pattern) != -1: - match = ident - break - file.close() - if match == -1: - print "Fatal error: unable to find function signature in test %s" % filename - error_count += 1 - else: - obj_name = "%s.o" % filename - exe_name = "%s.run" % filename - ispc_cmd = "ispc --woff %s -o %s --arch=%s --target=%s" % \ - (filename, obj_name, options.arch, options.target) - if options.no_opt: - ispc_cmd += " -O0" - if options.arch == 'x86': - gcc_arch = '-m32' - else: - gcc_arch = '-m64' - gcc_cmd = "g++ %s test_static.cpp -DTEST_SIG=%d %s.o -o %s" % \ - (gcc_arch, match, filename, exe_name) - if platform.system() == 'Darwin': - gcc_cmd += ' -Wl,-no_pie' - if should_fail: - gcc_cmd += " -DEXPECT_FAILURE" - - # compile the ispc code, make the executable, and run it... - error_count += run_cmds([ispc_cmd, gcc_cmd, exe_name], filename, should_fail) - - # clean up after running the test - try: - os.unlink(exe_name) - os.unlink(obj_name) - except: - None - else: - # otherwise we'll use ispc_test + the LLVM JIT to run the test - bitcode_file = "%s.bc" % filename - compile_cmd = "ispc --woff --emit-llvm %s --target=%s -o %s" % \ - (filename, options.target, bitcode_file) - if options.no_opt: - compile_cmd += " -O0" - test_cmd = "ispc_test %s" % bitcode_file - - error_count += run_cmds([compile_cmd, test_cmd], filename, should_fail) - - try: - os.unlink(bitcode_file) - except: - None + error_count += run_test(filename) # If not for http://bugs.python.org/issue5261 on OSX, we'd like to do this: #with finished_tests_counter_lock: @@ -214,34 +215,58 @@ def sigint(signum, frame): sys.exit(1) if __name__ == '__main__': - nthreads = multiprocessing.cpu_count() total_tests = len(files) - print "Found %d CPUs. Running %d tests." % (nthreads, total_tests) - - # put each of the test filenames into a queue - q = multiprocessing.Queue() - for fn in files: - q.put(fn) - for x in range(nthreads): - q.put('STOP') - - # need to catch sigint so that we can terminate all of the tasks if - # we're interrupted - signal.signal(signal.SIGINT, sigint) - - # launch jobs to run tests - for x in range(nthreads): - t = multiprocessing.Process(target=run_tasks_from_queue, args=(q,)) - task_threads.append(t) - t.start() - - # wait for them to all finish and then return the number that failed - # (i.e. return 0 if all is ok) error_count = 0 - for t in task_threads: - t.join() - error_count += t.exitcode - print + + if (platform.system() == 'Windows' or + 'CYGWIN_NT' in platform.system()): + # cl.exe gets itself all confused if we have multiple instances of + # it running concurrently and operating on the same .cpp file + # (test_static.cpp), even if we are generating a differently-named + # exe in the end. So run serially. :-( + nthreads = 1 + num_done = 0 + print "Running %d tests." % (total_tests) + for fn in files: + error_count += run_test(fn) + + num_done += 1 + progress_str = " Done %d / %d [%s]" % (num_done, total_tests, fn) + # spaces to clear out detrius from previous printing... + for x in range(30): + progress_str += ' ' + progress_str += '\r' + sys.stdout.write(progress_str) + sys.stdout.flush() + else: + nthreads = multiprocessing.cpu_count() + print "Found %d CPUs. Running %d tests." % (nthreads, total_tests) + + # put each of the test filenames into a queue + q = multiprocessing.Queue() + for fn in files: + q.put(fn) + for x in range(nthreads): + q.put('STOP') + + # need to catch sigint so that we can terminate all of the tasks if + # we're interrupted + signal.signal(signal.SIGINT, sigint) + + # launch jobs to run tests + for x in range(nthreads): + t = multiprocessing.Process(target=run_tasks_from_queue, args=(q,)) + task_threads.append(t) + t.start() + + # wait for them to all finish and then return the number that failed + # (i.e. return 0 if all is ok) + error_count = 0 + for t in task_threads: + t.join() + error_count += t.exitcode + print + if error_count > 0: print "%d / %d tests FAILED!" % (error_count, total_tests) sys.exit(error_count) diff --git a/run_tests.sh b/run_tests.sh deleted file mode 100755 index 60b6e4a2..00000000 --- a/run_tests.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash - -surprises=0 -verbose=false -number=$(ls -1 tests/*.ispc|wc -l) -counter=1 -target=sse4 - -while getopts ":vt:h" opt;do - case $opt in - v) verbose=true - ;; - t) target=$OPTARG - ;; - h) cat < 0 ]]; then - while [[ "$1" > 0 ]]; do - i=$1 - shift - echo Running test $i - - bc=${i%%ispc}bc - ispc $ISPC_ARGS $i -o $bc --emit-llvm - if [[ $? != 0 ]]; then - surprises=1 - echo Test $i FAILED ispc compile - echo - else - ispc_test $bc - if [[ $? != 0 ]]; then - surprises=1 - echo Test $i FAILED ispc_test - echo - fi - fi - /bin/rm -f $bc - done -else - echo Running all correctness tests - - for i in tests/*.ispc; do - if $verbose; then - echo -en "Running test $counter of $number.\r" - fi - (( counter++ )) - bc=${i%%ispc}bc - ispc $ISPC_ARGS $i -o $bc --emit-llvm - if [[ $? != 0 ]]; then - surprises=1 - echo Test $i FAILED ispc compile - echo - else - ispc_test $bc - if [[ $? != 0 ]]; then - surprises=1 - echo Test $i FAILED ispc_test - echo - fi - fi - /bin/rm -f $bc - done - - echo -e "\nRunning failing tests" - for i in failing_tests/*.ispc; do - (ispc -O2 $i -woff -o - --emit-llvm | ispc_test -) 2>/dev/null 1>/dev/null - if [[ $? == 0 ]]; then - surprises=1 - echo Test $i UNEXPECTEDLY PASSED - echo - fi - done -fi - -if [[ $surprises == 0 ]]; then - echo No surprises. -fi - -exit $surprises diff --git a/test_static.cpp b/test_static.cpp index 9deb1a9f..f56d0506 100644 --- a/test_static.cpp +++ b/test_static.cpp @@ -39,6 +39,10 @@ #define ISPC_IS_APPLE #endif +#ifdef ISPC_IS_WINDOWS +#include +#endif // ISPC_IS_WINDOWS + #include #include #include