Update run_tests.py to work on Windows. Removed JIT-based testing path entirely.

This commit is contained in:
Matt Pharr
2011-12-06 13:45:11 -08:00
parent d59131d670
commit 04df63d955
7 changed files with 164 additions and 710 deletions

View File

@@ -27,8 +27,6 @@ CLANG_LIBS = -lclangFrontend -lclangDriver \
ISPC_LIBS=$(shell llvm-config --ldflags) $(CLANG_LIBS) $(LLVM_LIBS) \ ISPC_LIBS=$(shell llvm-config --ldflags) $(CLANG_LIBS) $(LLVM_LIBS) \
-lpthread -ldl -lpthread -ldl
ISPC_TEST_LIBS=$(shell llvm-config --ldflags) $(LLVM_LIBS) \
-lpthread -ldl
LLVM_CXXFLAGS=$(shell llvm-config --cppflags) LLVM_CXXFLAGS=$(shell llvm-config --cppflags)
LLVM_VERSION=LLVM_$(shell llvm-config --version | sed s/\\./_/) 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) \ builtins-c-32.o builtins-c-64.o stdlib_ispc.o $(BISON_SRC:.yy=.o) \
$(FLEX_SRC:.ll=.o)) $(FLEX_SRC:.ll=.o))
default: ispc ispc_test default: ispc
.PHONY: dirs clean depend doxygen print_llvm_src .PHONY: dirs clean depend doxygen print_llvm_src
.PRECIOUS: objs/builtins-%.cpp .PRECIOUS: objs/builtins-%.cpp
@@ -92,7 +90,7 @@ print_llvm_src:
@echo Using LLVM `llvm-config --version` from `llvm-config --libdir` @echo Using LLVM `llvm-config --version` from `llvm-config --libdir`
clean: clean:
/bin/rm -rf objs ispc ispc_test /bin/rm -rf objs ispc
doxygen: doxygen:
/bin/rm -rf docs/doxygen /bin/rm -rf docs/doxygen
@@ -102,10 +100,6 @@ ispc: print_llvm_src dirs $(OBJS)
@echo Creating ispc executable @echo Creating ispc executable
@$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(ISPC_LIBS) @$(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 objs/%.o: %.cpp
@echo Compiling $< @echo Compiling $<
@$(CXX) $(CXXFLAGS) -o $@ -c $< @$(CXX) $(CXXFLAGS) -o $@ -c $<

View File

@@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010 # Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ispc", "ispc.vcxproj", "{9861F490-F516-480C-B63C-D62A77AFA9D5}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ispc", "ispc.vcxproj", "{9861F490-F516-480C-B63C-D62A77AFA9D5}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ispc_test", "ispc_test.vcxproj", "{92547BA8-BE86-4E78-8799-1D72A70E5831}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 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}.Debug|Win32.Build.0 = Debug|Win32
{9861F490-F516-480C-B63C-D62A77AFA9D5}.Release|Win32.ActiveCfg = Release|Win32 {9861F490-F516-480C-B63C-D62A77AFA9D5}.Release|Win32.ActiveCfg = Release|Win32
{9861F490-F516-480C-B63C-D62A77AFA9D5}.Release|Win32.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -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 <windows.h>
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <memory.h>
#ifdef ISPC_IS_LINUX
#include <malloc.h>
#endif
#ifdef ISPC_HAVE_SVML
#include <xmmintrin.h>
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 <llvm/LLVMContext.h>
#include <llvm/Module.h>
#include <llvm/Type.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Instructions.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn)
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#else
#include <llvm/Target/TargetRegistry.h>
#include <llvm/Target/TargetSelect.h>
#endif
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/Target/TargetOptions.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/PassManager.h>
#include <llvm/Support/CFG.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/system_error.h>
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<uint64_t>(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<files>\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<llvm::MemoryBuffer> 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<std::string> 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<PFN>(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<PFN>(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<PFN>(ee->getPointerToFunction(func));
pfn(returned);
}
else if ((func = module->getFunction("f_f")) != NULL) {
typedef void (*PFN)(float *, float *);
PFN pfn = reinterpret_cast<PFN>(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<PFN>(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<PFN>(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<PFN>(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<PFN>(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<PFN>(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;
}

View File

@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ispc_test.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{92547BA8-BE86-4E78-8799-1D72A70E5831}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ispc_test</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>LLVM_3_0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(LLVM_INSTALL_DIR)/include</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4146;4355;4800</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(LLVM_INSTALL_DIR)/lib</AdditionalLibraryDirectories>
<AdditionalDependencies>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)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>LLVM_3_0;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(LLVM_INSTALL_DIR)/include</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4146;4355;4800</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(LLVM_INSTALL_DIR)/lib</AdditionalLibraryDirectories>
<AdditionalDependencies>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)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -2,9 +2,6 @@
# test-running driver for ispc # test-running driver for ispc
# TODO: windows support (mostly should be calling CL.exe rather than gcc
# for static linking?)
from optparse import OptionParser from optparse import OptionParser
import multiprocessing import multiprocessing
from ctypes import c_int from ctypes import c_int
@@ -23,9 +20,6 @@ import platform
parser = OptionParser() parser = OptionParser()
parser.add_option("-r", "--random-shuffle", dest="random", help="Randomly order tests", parser.add_option("-r", "--random-shuffle", dest="random", help="Randomly order tests",
default=False, action="store_true") 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', parser.add_option('-t', '--target', dest='target',
help='Set compilation target (sse2, sse2-x2, sse4, sse4-x2, avx, avx-x2)', help='Set compilation target (sse2, sse2-x2, sse4, sse4-x2, avx, avx-x2)',
default="sse4") default="sse4")
@@ -52,7 +46,6 @@ if (options.random):
# counter # counter
total_tests = 0 total_tests = 0
finished_tests_counter = multiprocessing.Value(c_int)
# We'd like to use the Lock class from the multiprocessing package to # We'd like to use the Lock class from the multiprocessing package to
# serialize accesses to finished_tests_counter. Unfortunately, the version of # 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 # http://bugs.python.org/issue5261. Therefore, we use the (deprecated but
# still available) mutex class. # still available) mutex class.
#finished_tests_counter_lock = multiprocessing.Lock() #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 # utility routine to print an update on the number of tests that have been
# finished. Should be called with the mutex (or lock) held.. # 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 # run the commands in cmd_list
def run_cmds(cmd_list, filename, expect_failure): def run_cmds(cmd_list, filename, expect_failure):
for cmd in cmd_list: for cmd in cmd_list:
if expect_failure: sp = subprocess.Popen(shlex.split(cmd), stdin=None,
failed = (subprocess.call(cmd, shell = True, stdout = fnull, stderr = fnull) != 0) stdout=subprocess.PIPE,
else: stderr=subprocess.PIPE)
failed = (os.system(cmd) != 0) output = sp.communicate()[0]
failed = (sp.returncode != 0)
if failed: if failed:
break 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: if surprise == True:
print "Test %s %s " % \ print "Test %s %s " % \
(filename, "unexpectedly passed" if expect_failure else "failed") (filename, "unexpectedly passed" if expect_failure else "failed")
print "Output %s" % output
return surprise 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 # 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 # this function will be running in parallel across all of the CPU cores of
# the system. # the system.
@@ -104,100 +198,7 @@ def run_tasks_from_queue(queue):
if (filename == 'STOP'): if (filename == 'STOP'):
sys.exit(error_count) sys.exit(error_count)
# is this a test to make sure an error is issued? error_count += run_test(filename)
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
# If not for http://bugs.python.org/issue5261 on OSX, we'd like to do this: # If not for http://bugs.python.org/issue5261 on OSX, we'd like to do this:
#with finished_tests_counter_lock: #with finished_tests_counter_lock:
@@ -214,34 +215,58 @@ def sigint(signum, frame):
sys.exit(1) sys.exit(1)
if __name__ == '__main__': if __name__ == '__main__':
nthreads = multiprocessing.cpu_count()
total_tests = len(files) 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 error_count = 0
for t in task_threads:
t.join() if (platform.system() == 'Windows' or
error_count += t.exitcode 'CYGWIN_NT' in platform.system()):
print # 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: if error_count > 0:
print "%d / %d tests FAILED!" % (error_count, total_tests) print "%d / %d tests FAILED!" % (error_count, total_tests)
sys.exit(error_count) sys.exit(error_count)

View File

@@ -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 <<EOF
usage: run_tests.sh [-v] [-t target] [filenames]
-v # verbose output
-t # specify compilation target (SSE4 is the default).
[filenames] # (optional) files to run through testing infrastructure
# if none are provided, all in tests/ will be run.
EOF
exit 1
esac
done
ISPC_ARCH=x86-64
if [[ $OS == "Windows_NT" ]]; then
ISPC_ARCH=x86
fi
ISPC_ARGS="--target=$target --arch=$ISPC_ARCH -O2 --woff"
shift $(( $OPTIND - 1 ))
if [[ "$1" > 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

View File

@@ -39,6 +39,10 @@
#define ISPC_IS_APPLE #define ISPC_IS_APPLE
#endif #endif
#ifdef ISPC_IS_WINDOWS
#include <windows.h>
#endif // ISPC_IS_WINDOWS
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>