From: Nicolas Capens Date: Mon, 6 Aug 2018 18:20:45 +0000 (-0400) Subject: Make Reactor build stand-alone. X-Git-Tag: android-x86-9.0-r1~586 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=c07dc4be1f78ce54ed800d59fed9103687f4f4f3;p=android-x86%2Fexternal-swiftshader.git Make Reactor build stand-alone. This is accomplished by duplicating files from the Common directory that Reactor (both with LLVM and Subzero back-end) depended on. They will be minimized in the next change. Bug b/115344057 Bug swiftshader:16 Change-Id: I2dc087e91b761cc4402ed8594022551e9246b855 Reviewed-on: https://swiftshader-review.googlesource.com/c/20108 Tested-by: Nicolas Capens Reviewed-by: Alexis Hétu --- diff --git a/.travis.yml b/.travis.yml index 25a651f8a..684873401 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,9 @@ compiler: - gcc env: - - REACTOR_BACKEND=LLVM - REACTOR_BACKEND=Subzero + - REACTOR_BACKEND=LLVM SWIFTSHADER_LLVM_VERSION=3 + - REACTOR_BACKEND=LLVM SWIFTSHADER_LLVM_VERSION=7 script: - $CXX --version @@ -22,6 +23,7 @@ script: - cmake -DREACTOR_BACKEND=$REACTOR_BACKEND .. - make - ./unittests + - ./ReactorUnitTests notifications: email: @@ -39,4 +41,4 @@ deploy: skip_cleanup: true acl: public-read upload-dir: OpenGL_ES/Latest - local-dir: $TRAVIS_BUILD_DIR/out \ No newline at end of file + local-dir: $TRAVIS_BUILD_DIR/out diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c2684e6f..8f1e1c270 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1724,14 +1724,17 @@ if(${REACTOR_BACKEND} STREQUAL "Subzero") ${SOURCE_DIR}/Reactor/Optimizer.cpp ${SOURCE_DIR}/Reactor/Nucleus.hpp ${SOURCE_DIR}/Reactor/Routine.hpp + ${SOURCE_DIR}/Reactor/Debug.cpp + ${SOURCE_DIR}/Reactor/Debug.hpp + ${SOURCE_DIR}/Reactor/Memory.cpp + ${SOURCE_DIR}/Reactor/Memory.hpp ) set(SUBZERO_INCLUDE_DIR - ${SOURCE_DIR}/ ${SUBZERO_DIR}/ ${SUBZERO_LLVM_DIR}/include/ ${SUBZERO_DIR}/pnacl-llvm/include/ - ) + ) if(WIN32) list(APPEND SUBZERO_INCLUDE_DIR ${SUBZERO_LLVM_DIR}/build/Windows/include/) @@ -1817,6 +1820,12 @@ set(REACTOR_LLVM_LIST ${SOURCE_DIR}/Reactor/LLVMRoutine.hpp ${SOURCE_DIR}/Reactor/LLVMRoutineManager.cpp ${SOURCE_DIR}/Reactor/LLVMRoutineManager.hpp + ${SOURCE_DIR}/Reactor/CPUID.cpp + ${SOURCE_DIR}/Reactor/CPUID.hpp + ${SOURCE_DIR}/Reactor/Debug.cpp + ${SOURCE_DIR}/Reactor/Debug.hpp + ${SOURCE_DIR}/Reactor/Memory.cpp + ${SOURCE_DIR}/Reactor/Memory.hpp ) file(GLOB_RECURSE EGL_LIST @@ -2113,26 +2122,27 @@ if(BUILD_SAMPLES) endif() endif() -if(BUILD_TESTS AND ${REACTOR_BACKEND} STREQUAL "Subzero") - set(SUBZERO_TEST_LIST - ${SOURCE_DIR}/Reactor/Main.cpp +if(BUILD_TESTS) + set(REACTOR_UNIT_TESTS_LIST + ${SOURCE_DIR}/Reactor/ReactorUnitTests.cpp ${CMAKE_SOURCE_DIR}/third_party/googletest/googletest/src/gtest-all.cc ) - set(SUBZERO_TEST_INCLUDE_DIR + set(REACTOR_UNIT_TESTS_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/third_party/googletest/googletest/include ${CMAKE_SOURCE_DIR}/third_party/googletest/googletest/ ) - add_executable(SubzeroTest ${SUBZERO_TEST_LIST}) - set_target_properties(SubzeroTest PROPERTIES - INCLUDE_DIRECTORIES "${SUBZERO_TEST_INCLUDE_DIR}" + add_executable(ReactorUnitTests ${REACTOR_UNIT_TESTS_LIST}) + set_target_properties(ReactorUnitTests PROPERTIES + INCLUDE_DIRECTORIES "${REACTOR_UNIT_TESTS_INCLUDE_DIR}" FOLDER "Tests" ) - if(WIN32) - target_link_libraries(SubzeroTest ReactorSubzero) + + if(NOT WIN32 AND ${REACTOR_BACKEND} STREQUAL "Subzero") + target_link_libraries(ReactorUnitTests ${Reactor} pthread dl) else() - target_link_libraries(SubzeroTest ReactorSubzero pthread dl) + target_link_libraries(ReactorUnitTests ${Reactor}) endif() endif() diff --git a/SwiftShader.sln b/SwiftShader.sln index 4e436f4b2..5a11a1598 100644 --- a/SwiftShader.sln +++ b/SwiftShader.sln @@ -253,11 +253,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D8", "src\D3D8\D3D8.vcxpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Subzero", "src\Reactor\Subzero.vcxproj", "{0EB31AEC-B020-46AB-BA05-730F6D01C29B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SubzeroTest", "src\Reactor\SubzeroTest.vcxproj", "{4EC107AB-89E8-4A0B-8366-B3E81085AE07}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SubzeroLLVMDependencies", "src\Reactor\SubzeroLLVMDependencies.vcxproj", "{E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittests", "tests\unittests\unittests.vcxproj", "{CF8EBC89-8762-49DC-9440-6C82B3499913}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GLESUnitTests", "tests\unittests\GLESUnitTests.vcxproj", "{CF8EBC89-8762-49DC-9440-6C82B3499913}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VertexRoutineFuzzer", "tests\fuzzers\VertexRoutineFuzzer.vcxproj", "{FBDCFF88-0CE1-43C3-B694-8F45946FAFE3}" ProjectSection(ProjectDependencies) = postProject @@ -267,6 +265,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VertexRoutineFuzzer", "test EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vulkan", "src\Vulkan\vulkan.vcxproj", "{E1C34B66-C942-4B9A-B8C3-9A12625650D3}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactorUnitTests", "src\Reactor\ReactorUnitTests.vcxproj", "{4EC107AB-89E8-4A0B-8366-B3E81085AE07}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -754,18 +754,6 @@ Global {0EB31AEC-B020-46AB-BA05-730F6D01C29B}.Release|Win32.Build.0 = Release|Win32 {0EB31AEC-B020-46AB-BA05-730F6D01C29B}.Release|x64.ActiveCfg = Release|x64 {0EB31AEC-B020-46AB-BA05-730F6D01C29B}.Release|x64.Build.0 = Release|x64 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|Win32.ActiveCfg = Debug|Win32 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|Win32.Build.0 = Debug|Win32 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|x64.ActiveCfg = Debug|x64 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|x64.Build.0 = Debug|x64 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|Win32.ActiveCfg = Release|Win32 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|Win32.Build.0 = Release|Win32 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|x64.ActiveCfg = Release|x64 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|x64.Build.0 = Release|x64 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|Win32.ActiveCfg = Release|Win32 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|Win32.Build.0 = Release|Win32 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|x64.ActiveCfg = Release|x64 - {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|x64.Build.0 = Release|x64 {E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}.Debug|Win32.ActiveCfg = Debug|Win32 {E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}.Debug|Win32.Build.0 = Debug|Win32 {E3BBD7DA-45C1-43EF-9C87-3F411031BDE4}.Debug|x64.ActiveCfg = Debug|x64 @@ -814,6 +802,18 @@ Global {E1C34B66-C942-4B9A-B8C3-9A12625650D3}.Release|Win32.Build.0 = Release|Win32 {E1C34B66-C942-4B9A-B8C3-9A12625650D3}.Release|x64.ActiveCfg = Release|x64 {E1C34B66-C942-4B9A-B8C3-9A12625650D3}.Release|x64.Build.0 = Release|x64 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|Win32.ActiveCfg = Debug|Win32 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|Win32.Build.0 = Debug|Win32 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|x64.ActiveCfg = Debug|x64 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Debug|x64.Build.0 = Debug|x64 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|Win32.ActiveCfg = Release|Win32 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|Win32.Build.0 = Release|Win32 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|x64.ActiveCfg = Release|x64 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Profile|x64.Build.0 = Release|x64 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|Win32.ActiveCfg = Release|Win32 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|Win32.Build.0 = Release|Win32 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|x64.ActiveCfg = Release|x64 + {4EC107AB-89E8-4A0B-8366-B3E81085AE07}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -855,9 +855,9 @@ Global {04FC5430-3F1B-42A2-A18A-D8BB7E5B2733} = {ED25C308-5BDB-43A7-BED6-C2C059FC2D7D} {09ABE661-9BC0-4152-A820-1FB0522CAC01} = {B7E24D8E-6BE9-4DEF-A8B9-6A6E60CA60E9} {9088FC9E-9843-4E0D-85D0-1B657AFC480A} = {B7E24D8E-6BE9-4DEF-A8B9-6A6E60CA60E9} - {4EC107AB-89E8-4A0B-8366-B3E81085AE07} = {ED25C308-5BDB-43A7-BED6-C2C059FC2D7D} {CF8EBC89-8762-49DC-9440-6C82B3499913} = {ED25C308-5BDB-43A7-BED6-C2C059FC2D7D} {FBDCFF88-0CE1-43C3-B694-8F45946FAFE3} = {ED25C308-5BDB-43A7-BED6-C2C059FC2D7D} + {4EC107AB-89E8-4A0B-8366-B3E81085AE07} = {ED25C308-5BDB-43A7-BED6-C2C059FC2D7D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4DF423D2-8425-48A7-9CEC-835C4C3CA957} diff --git a/src/Android.mk b/src/Android.mk index b25ef9150..d418b3564 100644 --- a/src/Android.mk +++ b/src/Android.mk @@ -60,17 +60,22 @@ COMMON_SRC_FILES += \ Main/FrameBufferAndroid.cpp \ Main/SwiftConfig.cpp +COMMON_SRC_FILES += \ + Reactor/Routine.cpp \ + Reactor/Debug.cpp \ + Reactor/DebugAndroid.cpp \ + Reactor/Memory.cpp + ifdef SWIFTSHADER_USE_SUBZERO COMMON_SRC_FILES += \ Reactor/SubzeroReactor.cpp \ - Reactor/Routine.cpp \ Reactor/Optimizer.cpp else COMMON_SRC_FILES += \ Reactor/LLVMReactor.cpp \ - Reactor/Routine.cpp \ Reactor/LLVMRoutine.cpp \ - Reactor/LLVMRoutineManager.cpp + Reactor/LLVMRoutineManager.cpp \ + Reactor/CPUID.cpp endif COMMON_SRC_FILES += \ diff --git a/src/Common/Version.h b/src/Common/Version.h index 72bd15d5f..bf1701edf 100644 --- a/src/Common/Version.h +++ b/src/Common/Version.h @@ -15,7 +15,7 @@ #define MAJOR_VERSION 4 #define MINOR_VERSION 1 #define BUILD_VERSION 0 -#define BUILD_REVISION 2 +#define BUILD_REVISION 3 #define STRINGIFY(x) #x #define MACRO_STRINGIFY(x) STRINGIFY(x) diff --git a/src/Reactor/BUILD.gn b/src/Reactor/BUILD.gn index 1084f27e1..c63e35935 100644 --- a/src/Reactor/BUILD.gn +++ b/src/Reactor/BUILD.gn @@ -267,6 +267,8 @@ swiftshader_source_set("swiftshader_reactor") { sources = [ "Routine.cpp", + "Debug.cpp", + "Memory.cpp", ] if (use_swiftshader_with_subzero) { @@ -283,7 +285,6 @@ swiftshader_source_set("swiftshader_reactor") { ] include_dirs = [ - "..", ] } else { deps += [ "../../third_party/LLVM:swiftshader_llvm" ] @@ -292,13 +293,12 @@ swiftshader_source_set("swiftshader_reactor") { "LLVMReactor.cpp", "LLVMRoutine.cpp", "LLVMRoutineManager.cpp", + "CPUID.cpp", ] configs = [ ":swiftshader_reactor_private_config" ] include_dirs = [ - "..", - "../Common", "../../third_party/LLVM/include/", ] } diff --git a/src/Reactor/CPUID.cpp b/src/Reactor/CPUID.cpp new file mode 100644 index 000000000..58ef00949 --- /dev/null +++ b/src/Reactor/CPUID.cpp @@ -0,0 +1,227 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "CPUID.hpp" + +#if defined(_WIN32) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include + #include + #include +#else + #include + #include + #include +#endif + +namespace rr +{ + bool CPUID::MMX = detectMMX(); + bool CPUID::CMOV = detectCMOV(); + bool CPUID::SSE = detectSSE(); + bool CPUID::SSE2 = detectSSE2(); + bool CPUID::SSE3 = detectSSE3(); + bool CPUID::SSSE3 = detectSSSE3(); + bool CPUID::SSE4_1 = detectSSE4_1(); + + bool CPUID::enableMMX = true; + bool CPUID::enableCMOV = true; + bool CPUID::enableSSE = true; + bool CPUID::enableSSE2 = true; + bool CPUID::enableSSE3 = true; + bool CPUID::enableSSSE3 = true; + bool CPUID::enableSSE4_1 = true; + + void CPUID::setEnableMMX(bool enable) + { + enableMMX = enable; + + if(!enableMMX) + { + enableSSE = false; + enableSSE2 = false; + enableSSE3 = false; + enableSSSE3 = false; + enableSSE4_1 = false; + } + } + + void CPUID::setEnableCMOV(bool enable) + { + enableCMOV = enable; + + if(!CMOV) + { + enableSSE = false; + enableSSE2 = false; + enableSSE3 = false; + enableSSSE3 = false; + enableSSE4_1 = false; + } + } + + void CPUID::setEnableSSE(bool enable) + { + enableSSE = enable; + + if(enableSSE) + { + enableMMX = true; + enableCMOV = true; + } + else + { + enableSSE2 = false; + enableSSE3 = false; + enableSSSE3 = false; + enableSSE4_1 = false; + } + } + + void CPUID::setEnableSSE2(bool enable) + { + enableSSE2 = enable; + + if(enableSSE2) + { + enableMMX = true; + enableCMOV = true; + enableSSE = true; + } + else + { + enableSSE3 = false; + enableSSSE3 = false; + enableSSE4_1 = false; + } + } + + void CPUID::setEnableSSE3(bool enable) + { + enableSSE3 = enable; + + if(enableSSE3) + { + enableMMX = true; + enableCMOV = true; + enableSSE = true; + enableSSE2 = true; + } + else + { + enableSSSE3 = false; + enableSSE4_1 = false; + } + } + + void CPUID::setEnableSSSE3(bool enable) + { + enableSSSE3 = enable; + + if(enableSSSE3) + { + enableMMX = true; + enableCMOV = true; + enableSSE = true; + enableSSE2 = true; + enableSSE3 = true; + } + else + { + enableSSE4_1 = false; + } + } + + void CPUID::setEnableSSE4_1(bool enable) + { + enableSSE4_1 = enable; + + if(enableSSE4_1) + { + enableMMX = true; + enableCMOV = true; + enableSSE = true; + enableSSE2 = true; + enableSSE3 = true; + enableSSSE3 = true; + } + } + + static void cpuid(int registers[4], int info) + { + #if defined(__i386__) || defined(__x86_64__) + #if defined(_WIN32) + __cpuid(registers, info); + #else + __asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info)); + #endif + #else + registers[0] = 0; + registers[1] = 0; + registers[2] = 0; + registers[3] = 0; + #endif + } + + bool CPUID::detectMMX() + { + int registers[4]; + cpuid(registers, 1); + return MMX = (registers[3] & 0x00800000) != 0; + } + + bool CPUID::detectCMOV() + { + int registers[4]; + cpuid(registers, 1); + return CMOV = (registers[3] & 0x00008000) != 0; + } + + bool CPUID::detectSSE() + { + int registers[4]; + cpuid(registers, 1); + return SSE = (registers[3] & 0x02000000) != 0; + } + + bool CPUID::detectSSE2() + { + int registers[4]; + cpuid(registers, 1); + return SSE2 = (registers[3] & 0x04000000) != 0; + } + + bool CPUID::detectSSE3() + { + int registers[4]; + cpuid(registers, 1); + return SSE3 = (registers[2] & 0x00000001) != 0; + } + + bool CPUID::detectSSSE3() + { + int registers[4]; + cpuid(registers, 1); + return SSSE3 = (registers[2] & 0x00000200) != 0; + } + + bool CPUID::detectSSE4_1() + { + int registers[4]; + cpuid(registers, 1); + return SSE4_1 = (registers[2] & 0x00080000) != 0; + } +} diff --git a/src/Reactor/CPUID.hpp b/src/Reactor/CPUID.hpp new file mode 100644 index 000000000..108d4a7ba --- /dev/null +++ b/src/Reactor/CPUID.hpp @@ -0,0 +1,118 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef rr_CPUID_hpp +#define rr_CPUID_hpp + +namespace rr +{ + #if !defined(__i386__) && defined(_M_IX86) + #define __i386__ 1 + #endif + + #if !defined(__x86_64__) && (defined(_M_AMD64) || defined (_M_X64)) + #define __x86_64__ 1 + #endif + + class CPUID + { + public: + static bool supportsMMX(); + static bool supportsCMOV(); + static bool supportsMMX2(); // MMX instructions added by SSE: pshufw, pmulhuw, pmovmskb, pavgw/b, pextrw, pinsrw, pmaxsw/ub, etc. + static bool supportsSSE(); + static bool supportsSSE2(); + static bool supportsSSE3(); + static bool supportsSSSE3(); + static bool supportsSSE4_1(); + + static void setEnableMMX(bool enable); + static void setEnableCMOV(bool enable); + static void setEnableSSE(bool enable); + static void setEnableSSE2(bool enable); + static void setEnableSSE3(bool enable); + static void setEnableSSSE3(bool enable); + static void setEnableSSE4_1(bool enable); + + private: + static bool MMX; + static bool CMOV; + static bool SSE; + static bool SSE2; + static bool SSE3; + static bool SSSE3; + static bool SSE4_1; + + static bool enableMMX; + static bool enableCMOV; + static bool enableSSE; + static bool enableSSE2; + static bool enableSSE3; + static bool enableSSSE3; + static bool enableSSE4_1; + + static bool detectMMX(); + static bool detectCMOV(); + static bool detectSSE(); + static bool detectSSE2(); + static bool detectSSE3(); + static bool detectSSSE3(); + static bool detectSSE4_1(); + }; +} + +namespace rr +{ + inline bool CPUID::supportsMMX() + { + return MMX && enableMMX; + } + + inline bool CPUID::supportsCMOV() + { + return CMOV && enableCMOV; + } + + inline bool CPUID::supportsMMX2() + { + return supportsSSE(); // Coincides with 64-bit integer vector instructions supported by SSE + } + + inline bool CPUID::supportsSSE() + { + return SSE && enableSSE; + } + + inline bool CPUID::supportsSSE2() + { + return SSE2 && enableSSE2; + } + + inline bool CPUID::supportsSSE3() + { + return SSE3 && enableSSE3; + } + + inline bool CPUID::supportsSSSE3() + { + return SSSE3 && enableSSSE3; + } + + inline bool CPUID::supportsSSE4_1() + { + return SSE4_1 && enableSSE4_1; + } +} + +#endif // rr_CPUID_hpp diff --git a/src/Reactor/Debug.cpp b/src/Reactor/Debug.cpp new file mode 100644 index 000000000..adfcabdc9 --- /dev/null +++ b/src/Reactor/Debug.cpp @@ -0,0 +1,39 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Debug.hpp" + +#include +#include + +namespace rr +{ +void trace(const char *format, ...) +{ + if(false) + { + FILE *file = fopen("debug.txt", "a"); + + if(file) + { + va_list vararg; + va_start(vararg, format); + vfprintf(file, format, vararg); + va_end(vararg); + + fclose(file); + } + } +} +} \ No newline at end of file diff --git a/src/Reactor/Debug.hpp b/src/Reactor/Debug.hpp new file mode 100644 index 000000000..720b38ac3 --- /dev/null +++ b/src/Reactor/Debug.hpp @@ -0,0 +1,52 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef Debug_hpp +#define Debug_hpp + +#ifdef __ANDROID__ +#include "DebugAndroid.hpp" +#else + +#include +#include + +#undef min +#undef max + +namespace rr +{ +void trace(const char *format, ...); + +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + #define TRACE(format, ...) trace("[0x%0.8X]%s(" format ")\n", this, __FUNCTION__, ##__VA_ARGS__) +#else + #define TRACE(...) ((void)0) +#endif + +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + #define UNIMPLEMENTED() {trace("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); ASSERT(false);} +#else + #define UNIMPLEMENTED() ((void)0) +#endif + +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + #define ASSERT(expression) {if(!(expression)) trace("\t! Assert failed in %s(%d): " #expression "\n", __FUNCTION__, __LINE__); assert(expression);} +#else + #define ASSERT assert +#endif +} + +#endif // __ANDROID__ +#endif // Debug_hpp diff --git a/src/Reactor/DebugAndroid.cpp b/src/Reactor/DebugAndroid.cpp new file mode 100644 index 000000000..c511fc379 --- /dev/null +++ b/src/Reactor/DebugAndroid.cpp @@ -0,0 +1,53 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "DebugAndroid.hpp" + +#include +#include +#include +#include + +void AndroidEnterDebugger() +{ + ALOGE(__FUNCTION__); +#ifndef NDEBUG + static volatile int * const makefault = nullptr; + char value[PROPERTY_VALUE_MAX]; + property_get("debug.db.uid", value, "-1"); + int debug_uid = atoi(value); + if((debug_uid >= 0) && (geteuid() < static_cast(debug_uid))) + { + ALOGE("Waiting for debugger: gdbserver :${PORT} --attach %u. Look for thread %u", getpid(), gettid()); + volatile int waiting = 1; + while (waiting) { + sleep(1); + } + } + else + { + ALOGE("No debugger"); + } +#endif +} + +void trace(const char *format, ...) +{ +#ifndef NDEBUG + va_list vararg; + va_start(vararg, format); + android_vprintLog(ANDROID_LOG_VERBOSE, NULL, LOG_TAG, format, vararg); + va_end(vararg); +#endif +} diff --git a/src/Reactor/DebugAndroid.hpp b/src/Reactor/DebugAndroid.hpp new file mode 100644 index 000000000..eced19453 --- /dev/null +++ b/src/Reactor/DebugAndroid.hpp @@ -0,0 +1,99 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef DebugAndroid_hpp +#define DebugAndroid_hpp + +#if ANDROID_PLATFORM_SDK_VERSION < 27 +#include +#elif ANDROID_PLATFORM_SDK_VERSION >= 27 +#include +#else +#error "ANDROID_PLATFORM_SDK_VERSION is not defined" +#endif + +#include + +// On Android Virtual Devices we heavily depend on logging, even in +// production builds. We do this because AVDs are components of larger +// systems, and may be configured in ways that are difficult to +// reproduce locally. For example some system run tests against +// third-party code that we cannot access. Aborting (cf. assert) on +// unimplemented functionality creates two problems. First, it produces +// a service failure where none is needed. Second, it puts the +// customer on the critical path for notifying us of a problem. +// The alternative, skipping unimplemented functionality silently, is +// arguably worse: neither the service provider nor the customer will +// learn that unimplemented functionality may have compromised the test +// results. +// Logging invocations of unimplemented functionality is useful to both +// service provider and the customer. The service provider can learn +// that the functionality is needed. The customer learns that the test +// results may be compromised. + +/** + * Enter the debugger with a memory fault iff debuggerd is set to capture this + * process. Otherwise return. + */ +void AndroidEnterDebugger(); + +#define ASSERT(E) do { \ + if (!(E)) { \ + ALOGE("badness: assertion_failed %s in %s at %s:%d", #E, \ + __FUNCTION__, __FILE__, __LINE__); \ + AndroidEnterDebugger(); \ + } \ + } while(0) + +#undef assert +#define assert(E) ASSERT(E) + +#define ERR(format, ...) \ + do { \ + ALOGE("badness: err %s %s:%d (" format ")", __FUNCTION__, __FILE__, \ + __LINE__, ##__VA_ARGS__); \ + AndroidEnterDebugger(); \ + } while(0) + +#define FIXME(format, ...) \ + do { \ + ALOGE("badness: fixme %s %s:%d (" format ")", __FUNCTION__, __FILE__, \ + __LINE__, ##__VA_ARGS__); \ + AndroidEnterDebugger(); \ + } while(0) + +// TODO: Handle __VA_ARGS__ (can be empty) +#define UNIMPLEMENTED(...) do { \ + ALOGE("badness: unimplemented: %s %s:%d", \ + __FUNCTION__, __FILE__, __LINE__); \ + AndroidEnterDebugger(); \ + } while(0) + +#define UNREACHABLE(value) do { \ + ALOGE("badness: unreachable case reached: %s %s:%d. %s: %d", \ + __FUNCTION__, __FILE__, __LINE__, #value, value); \ + AndroidEnterDebugger(); \ + } while(0) + +#ifndef NDEBUG + #define TRACE(format, ...) \ + ALOGV("%s %s:%d (" format ")", __FUNCTION__, __FILE__, \ + __LINE__, ##__VA_ARGS__) +#else + #define TRACE(...) ((void)0) +#endif + +void trace(const char *format, ...); + +#endif // DebugAndroid_hpp diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp index b702ec936..0f3b3dabf 100644 --- a/src/Reactor/LLVMReactor.cpp +++ b/src/Reactor/LLVMReactor.cpp @@ -14,6 +14,15 @@ #include "Reactor.hpp" +#include "x86.hpp" +#include "CPUID.hpp" +#include "Thread.hpp" +#include "Memory.hpp" +#include "MutexLock.hpp" + +#undef min +#undef max + #if SWIFTSHADER_LLVM_VERSION < 7 #include "llvm/Analysis/LoopPass.h" #include "llvm/Constants.h" @@ -69,12 +78,6 @@ #include #endif -#include "x86.hpp" -#include "Common/CPUID.hpp" -#include "Common/Thread.hpp" -#include "Common/Memory.hpp" -#include "Common/MutexLock.hpp" - #include #include @@ -120,7 +123,7 @@ namespace llvm::Module *module = nullptr; llvm::Function *function = nullptr; - sw::MutexLock codegenMutex; + rr::MutexLock codegenMutex; #if SWIFTSHADER_LLVM_VERSION >= 7 llvm::Value *lowerPAVG(llvm::Value *x, llvm::Value *y) @@ -443,8 +446,6 @@ namespace namespace rr { - using namespace sw; - #if SWIFTSHADER_LLVM_VERSION < 7 class LLVMReactorJIT { diff --git a/src/Reactor/LLVMRoutine.cpp b/src/Reactor/LLVMRoutine.cpp index 8dbfe079e..6b37fa6b7 100644 --- a/src/Reactor/LLVMRoutine.cpp +++ b/src/Reactor/LLVMRoutine.cpp @@ -14,16 +14,16 @@ #include "LLVMRoutine.hpp" -#include "Common/Memory.hpp" -#include "Common/Thread.hpp" -#include "Common/Types.hpp" +#include "Memory.hpp" +#include "Thread.hpp" +#include "Types.hpp" namespace rr { #if SWIFTSHADER_LLVM_VERSION < 7 LLVMRoutine::LLVMRoutine(int bufferSize) : bufferSize(bufferSize) { - void *memory = sw::allocateExecutable(bufferSize); + void *memory = allocateExecutable(bufferSize); buffer = memory; entry = memory; @@ -32,7 +32,7 @@ namespace rr LLVMRoutine::~LLVMRoutine() { - sw::deallocateExecutable(buffer, bufferSize); + deallocateExecutable(buffer, bufferSize); } const void *LLVMRoutine::getEntry() diff --git a/src/Reactor/LLVMRoutineManager.cpp b/src/Reactor/LLVMRoutineManager.cpp index 8af37f327..276bdd94e 100644 --- a/src/Reactor/LLVMRoutineManager.cpp +++ b/src/Reactor/LLVMRoutineManager.cpp @@ -18,9 +18,9 @@ #include "LLVMRoutine.hpp" #include "llvm/Function.h" -#include "Common/Memory.hpp" -#include "Common/Thread.hpp" -#include "Common/Debug.hpp" +#include "Memory.hpp" +#include "Thread.hpp" +#include "Debug.hpp" namespace rr { @@ -63,11 +63,11 @@ namespace rr } else // Estimate was too low { - sw::atomicIncrement(&averageInstructionSize); + atomicIncrement(&averageInstructionSize); } // Round up to the next page size - size_t pageSize = sw::memoryPageSize(); + size_t pageSize = memoryPageSize(); actualSize = (actualSize + pageSize - 1) & ~(pageSize - 1); delete routine; @@ -130,7 +130,7 @@ namespace rr void LLVMRoutineManager::setMemoryExecutable() { - sw::markExecutable(routine->buffer, routine->bufferSize); + markExecutable(routine->buffer, routine->bufferSize); } void LLVMRoutineManager::setPoisonMemory(bool poison) diff --git a/src/Reactor/Memory.cpp b/src/Reactor/Memory.cpp new file mode 100644 index 000000000..c7c3d6d5b --- /dev/null +++ b/src/Reactor/Memory.cpp @@ -0,0 +1,262 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Memory.hpp" + +#include "Types.hpp" +#include "Debug.hpp" + +#if defined(_WIN32) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include + #include +#else + #include + #include + #include + #include +#endif + +#include + +#undef allocate +#undef deallocate + +#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined (_M_X64)) && !defined(__x86__) +#define __x86__ +#endif + +namespace rr +{ +namespace +{ +struct Allocation +{ +// size_t bytes; + unsigned char *block; +}; + +void *allocateRaw(size_t bytes, size_t alignment) +{ + ASSERT((alignment & (alignment - 1)) == 0); // Power of 2 alignment. + + #if defined(LINUX_ENABLE_NAMED_MMAP) + void *allocation; + int result = posix_memalign(&allocation, alignment, bytes); + if(result != 0) + { + errno = result; + allocation = nullptr; + } + return allocation; + #else + unsigned char *block = new unsigned char[bytes + sizeof(Allocation) + alignment]; + unsigned char *aligned = nullptr; + + if(block) + { + aligned = (unsigned char*)((uintptr_t)(block + sizeof(Allocation) + alignment - 1) & -(intptr_t)alignment); + Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation)); + + // allocation->bytes = bytes; + allocation->block = block; + } + + return aligned; + #endif +} + +#if defined(LINUX_ENABLE_NAMED_MMAP) +// Create a file descriptor for anonymous memory with the given +// name. Returns -1 on failure. +// TODO: remove once libc wrapper exists. +int memfd_create(const char* name, unsigned int flags) +{ + #if __aarch64__ + #define __NR_memfd_create 279 + #elif __arm__ + #define __NR_memfd_create 279 + #elif __powerpc64__ + #define __NR_memfd_create 360 + #elif __i386__ + #define __NR_memfd_create 356 + #elif __x86_64__ + #define __NR_memfd_create 319 + #endif /* __NR_memfd_create__ */ + #ifdef __NR_memfd_create + // In the event of no system call this returns -1 with errno set + // as ENOSYS. + return syscall(__NR_memfd_create, name, flags); + #else + return -1; + #endif +} + +// Returns a file descriptor for use with an anonymous mmap, if +// memfd_create fails, -1 is returned. Note, the mappings should be +// MAP_PRIVATE so that underlying pages aren't shared. +int anonymousFd() +{ + static int fd = memfd_create("SwiftShader JIT", 0); + return fd; +} + +// Ensure there is enough space in the "anonymous" fd for length. +void ensureAnonFileSize(int anonFd, size_t length) +{ + static size_t fileSize = 0; + if(length > fileSize) + { + ftruncate(anonFd, length); + fileSize = length; + } +} +#endif // defined(LINUX_ENABLE_NAMED_MMAP) + +} // anonymous namespace + +size_t memoryPageSize() +{ + static int pageSize = 0; + + if(pageSize == 0) + { + #if defined(_WIN32) + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + pageSize = systemInfo.dwPageSize; + #else + pageSize = sysconf(_SC_PAGESIZE); + #endif + } + + return pageSize; +} + +void *allocate(size_t bytes, size_t alignment) +{ + void *memory = allocateRaw(bytes, alignment); + + if(memory) + { + memset(memory, 0, bytes); + } + + return memory; +} + +void deallocate(void *memory) +{ + #if defined(LINUX_ENABLE_NAMED_MMAP) + free(memory); + #else + if(memory) + { + unsigned char *aligned = (unsigned char*)memory; + Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation)); + + delete[] allocation->block; + } + #endif +} + +void *allocateExecutable(size_t bytes) +{ + size_t pageSize = memoryPageSize(); + size_t length = (bytes + pageSize - 1) & ~(pageSize - 1); + void *mapping; + + #if defined(LINUX_ENABLE_NAMED_MMAP) + // Try to name the memory region for the executable code, + // to aid profilers. + int anonFd = anonymousFd(); + if(anonFd == -1) + { + mapping = mmap(nullptr, length, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + else + { + ensureAnonFileSize(anonFd, length); + mapping = mmap(nullptr, length, PROT_READ | PROT_WRITE, + MAP_PRIVATE, anonFd, 0); + } + + if(mapping == MAP_FAILED) + { + mapping = nullptr; + } + #else + mapping = allocate(length, pageSize); + #endif + + return mapping; +} + +void markExecutable(void *memory, size_t bytes) +{ + #if defined(_WIN32) + unsigned long oldProtection; + VirtualProtect(memory, bytes, PAGE_EXECUTE_READ, &oldProtection); + #else + mprotect(memory, bytes, PROT_READ | PROT_EXEC); + #endif +} + +void deallocateExecutable(void *memory, size_t bytes) +{ + #if defined(_WIN32) + unsigned long oldProtection; + VirtualProtect(memory, bytes, PAGE_READWRITE, &oldProtection); + deallocate(memory); + #elif defined(LINUX_ENABLE_NAMED_MMAP) + size_t pageSize = memoryPageSize(); + size_t length = (bytes + pageSize - 1) & ~(pageSize - 1); + munmap(memory, length); + #else + mprotect(memory, bytes, PROT_READ | PROT_WRITE); + deallocate(memory); + #endif +} + +void clear(uint16_t *memory, uint16_t element, size_t count) +{ + #if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER) + __stosw(memory, element, count); + #elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER) + __asm__("rep stosw" : : "D"(memory), "a"(element), "c"(count)); + #else + for(size_t i = 0; i < count; i++) + { + memory[i] = element; + } + #endif +} + +void clear(uint32_t *memory, uint32_t element, size_t count) +{ + #if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER) + __stosd((unsigned long*)memory, element, count); + #elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER) + __asm__("rep stosl" : : "D"(memory), "a"(element), "c"(count)); + #else + for(size_t i = 0; i < count; i++) + { + memory[i] = element; + } + #endif +} +} diff --git a/src/Reactor/Memory.hpp b/src/Reactor/Memory.hpp new file mode 100644 index 000000000..3517f3c57 --- /dev/null +++ b/src/Reactor/Memory.hpp @@ -0,0 +1,36 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef rr_Memory_hpp +#define rr_Memory_hpp + +#include +#include + +namespace rr +{ +size_t memoryPageSize(); + +void *allocate(size_t bytes, size_t alignment = 16); +void deallocate(void *memory); + +void *allocateExecutable(size_t bytes); // Allocates memory that can be made executable using markExecutable() +void markExecutable(void *memory, size_t bytes); +void deallocateExecutable(void *memory, size_t bytes); + +void clear(uint16_t *memory, uint16_t element, size_t count); +void clear(uint32_t *memory, uint32_t element, size_t count); +} + +#endif // rr_Memory_hpp diff --git a/src/Reactor/MutexLock.hpp b/src/Reactor/MutexLock.hpp new file mode 100644 index 000000000..c2d00eb7b --- /dev/null +++ b/src/Reactor/MutexLock.hpp @@ -0,0 +1,177 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef rr_MutexLock_hpp +#define rr_MutexLock_hpp + +#include "Thread.hpp" + +#if defined(__linux__) +// Use a pthread mutex on Linux. Since many processes may use SwiftShader +// at the same time it's best to just have the scheduler overhead. +#include + +namespace rr +{ + class MutexLock + { + public: + MutexLock() + { + pthread_mutex_init(&mutex, NULL); + } + + ~MutexLock() + { + pthread_mutex_destroy(&mutex); + } + + bool attemptLock() + { + return pthread_mutex_trylock(&mutex) == 0; + } + + void lock() + { + pthread_mutex_lock(&mutex); + } + + void unlock() + { + pthread_mutex_unlock(&mutex); + } + + private: + pthread_mutex_t mutex; + }; +} + +#else // !__linux__ + +#include + +namespace rr +{ + class BackoffLock + { + public: + BackoffLock() + { + mutex = 0; + } + + bool attemptLock() + { + if(!isLocked()) + { + if(mutex.exchange(true) == false) + { + return true; + } + } + + return false; + } + + void lock() + { + int backoff = 1; + + while(!attemptLock()) + { + if(backoff <= 64) + { + for(int i = 0; i < backoff; i++) + { + nop(); + nop(); + nop(); + nop(); + nop(); + + nop(); + nop(); + nop(); + nop(); + nop(); + + nop(); + nop(); + nop(); + nop(); + nop(); + + nop(); + nop(); + nop(); + nop(); + nop(); + + nop(); + nop(); + nop(); + nop(); + nop(); + + nop(); + nop(); + nop(); + nop(); + nop(); + + nop(); + nop(); + nop(); + nop(); + nop(); + } + + backoff *= 2; + } + else + { + Thread::yield(); + + backoff = 1; + } + }; + } + + void unlock() + { + mutex.store(false, std::memory_order_release); + } + + bool isLocked() + { + return mutex.load(std::memory_order_acquire); + } + + private: + struct + { + // Ensure that the mutex variable is on its own 64-byte cache line to avoid false sharing + // Padding must be public to avoid compiler warnings + volatile int padding1[16]; + std::atomic mutex; + volatile int padding2[15]; + }; + }; + + using MutexLock = BackoffLock; +} + +#endif // !__linux__ + +#endif // rr_MutexLock_hpp diff --git a/src/Reactor/Reactor.vcxproj b/src/Reactor/Reactor.vcxproj index 788de64b9..dbf7b5fc5 100644 --- a/src/Reactor/Reactor.vcxproj +++ b/src/Reactor/Reactor.vcxproj @@ -277,17 +277,27 @@ + + + + + + + + + + diff --git a/src/Reactor/Reactor.vcxproj.filters b/src/Reactor/Reactor.vcxproj.filters index 2aebff538..34bb0f137 100644 --- a/src/Reactor/Reactor.vcxproj.filters +++ b/src/Reactor/Reactor.vcxproj.filters @@ -27,6 +27,18 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -47,5 +59,23 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/src/Reactor/Main.cpp b/src/Reactor/ReactorUnitTests.cpp similarity index 97% rename from src/Reactor/Main.cpp rename to src/Reactor/ReactorUnitTests.cpp index 2bc9f7e34..f6484f451 100644 --- a/src/Reactor/Main.cpp +++ b/src/Reactor/ReactorUnitTests.cpp @@ -33,7 +33,7 @@ int reference(int *p, int y) return sum; } -TEST(SubzeroReactorTest, Sample) +TEST(ReactorUnitTests, Sample) { Routine *routine = nullptr; @@ -73,7 +73,7 @@ TEST(SubzeroReactorTest, Sample) delete routine; } -TEST(SubzeroReactorTest, Uninitialized) +TEST(ReactorUnitTests, Uninitialized) { Routine *routine = nullptr; @@ -110,7 +110,7 @@ TEST(SubzeroReactorTest, Uninitialized) delete routine; } -TEST(SubzeroReactorTest, SubVectorLoadStore) +TEST(ReactorUnitTests, SubVectorLoadStore) { Routine *routine = nullptr; @@ -170,7 +170,7 @@ TEST(SubzeroReactorTest, SubVectorLoadStore) delete routine; } -TEST(SubzeroReactorTest, VectorConstant) +TEST(ReactorUnitTests, VectorConstant) { Routine *routine = nullptr; @@ -219,7 +219,7 @@ TEST(SubzeroReactorTest, VectorConstant) delete routine; } -TEST(SubzeroReactorTest, Concatenate) +TEST(ReactorUnitTests, Concatenate) { Routine *routine = nullptr; @@ -262,7 +262,7 @@ TEST(SubzeroReactorTest, Concatenate) delete routine; } -TEST(SubzeroReactorTest, Swizzle) +TEST(ReactorUnitTests, Swizzle) { Routine *routine = nullptr; @@ -389,7 +389,7 @@ TEST(SubzeroReactorTest, Swizzle) delete routine; } -TEST(SubzeroReactorTest, Branching) +TEST(ReactorUnitTests, Branching) { Routine *routine = nullptr; @@ -454,7 +454,7 @@ TEST(SubzeroReactorTest, Branching) delete routine; } -TEST(SubzeroReactorTest, MinMax) +TEST(ReactorUnitTests, MinMax) { Routine *routine = nullptr; @@ -545,7 +545,7 @@ TEST(SubzeroReactorTest, MinMax) delete routine; } -TEST(SubzeroReactorTest, NotNeg) +TEST(ReactorUnitTests, NotNeg) { Routine *routine = nullptr; @@ -630,7 +630,7 @@ TEST(SubzeroReactorTest, NotNeg) delete routine; } -TEST(SubzeroReactorTest, VectorCompare) +TEST(ReactorUnitTests, VectorCompare) { Routine *routine = nullptr; @@ -692,7 +692,7 @@ TEST(SubzeroReactorTest, VectorCompare) delete routine; } -TEST(SubzeroReactorTest, SaturatedAddAndSubtract) +TEST(ReactorUnitTests, SaturatedAddAndSubtract) { Routine *routine = nullptr; @@ -805,7 +805,7 @@ TEST(SubzeroReactorTest, SaturatedAddAndSubtract) delete routine; } -TEST(SubzeroReactorTest, Unpack) +TEST(ReactorUnitTests, Unpack) { Routine *routine = nullptr; @@ -852,7 +852,7 @@ TEST(SubzeroReactorTest, Unpack) delete routine; } -TEST(SubzeroReactorTest, Pack) +TEST(ReactorUnitTests, Pack) { Routine *routine = nullptr; @@ -914,7 +914,7 @@ TEST(SubzeroReactorTest, Pack) delete routine; } -TEST(SubzeroReactorTest, MulHigh) +TEST(ReactorUnitTests, MulHigh) { Routine *routine = nullptr; @@ -956,7 +956,7 @@ TEST(SubzeroReactorTest, MulHigh) delete routine; } -TEST(SubzeroReactorTest, MulAdd) +TEST(ReactorUnitTests, MulAdd) { Routine *routine = nullptr; diff --git a/src/Reactor/SubzeroTest.vcxproj b/src/Reactor/ReactorUnitTests.vcxproj similarity index 71% rename from src/Reactor/SubzeroTest.vcxproj rename to src/Reactor/ReactorUnitTests.vcxproj index 218073b04..0471ba622 100644 --- a/src/Reactor/SubzeroTest.vcxproj +++ b/src/Reactor/ReactorUnitTests.vcxproj @@ -21,7 +21,7 @@ {4EC107AB-89E8-4A0B-8366-B3E81085AE07} Win32Proj - SubzeroTest + ReactorUnitTests 10.0.16299.0 @@ -170,66 +170,13 @@ - - {0eb31aec-b020-46ab-ba05-730f6d01c29b} - false - true - false - - - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - + - - true - true - - - true - true - + + {0eb31aec-b020-46ab-ba05-730f6d01c29b} + diff --git a/src/Reactor/ReactorUnitTests.vcxproj.filters b/src/Reactor/ReactorUnitTests.vcxproj.filters new file mode 100644 index 000000000..721fc57cc --- /dev/null +++ b/src/Reactor/ReactorUnitTests.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/Reactor/Routine.cpp b/src/Reactor/Routine.cpp index 5899c5810..23cf92928 100644 --- a/src/Reactor/Routine.cpp +++ b/src/Reactor/Routine.cpp @@ -14,7 +14,7 @@ #include "Routine.hpp" -#include "Common/Thread.hpp" +#include "Thread.hpp" #include @@ -27,12 +27,12 @@ namespace rr void Routine::bind() { - sw::atomicIncrement(&bindCount); + atomicIncrement(&bindCount); } void Routine::unbind() { - long count = sw::atomicDecrement(&bindCount); + long count = atomicDecrement(&bindCount); if(count == 0) { diff --git a/src/Reactor/Subzero.vcxproj b/src/Reactor/Subzero.vcxproj index 7f7525e73..3aaf7b4c3 100644 --- a/src/Reactor/Subzero.vcxproj +++ b/src/Reactor/Subzero.vcxproj @@ -95,7 +95,7 @@ Disabled SZTARGET=X8632;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) %(AdditionalUsingDirectories) - $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\ + $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include MultiThreadedDebug src/IceTypes.h true @@ -114,7 +114,7 @@ Disabled SZTARGET=X8664;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) %(AdditionalUsingDirectories) - $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\ + $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include MultiThreadedDebug src/IceTypes.h true @@ -135,7 +135,7 @@ true SZTARGET=X8632;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) %(AdditionalUsingDirectories) - $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\ + $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include src/IceTypes.h MultiThreaded true @@ -158,7 +158,7 @@ true SZTARGET=X8664;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) %(AdditionalUsingDirectories) - $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\ + $(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include Size true true @@ -216,8 +216,9 @@ - - + + + @@ -279,6 +280,8 @@ + + @@ -296,6 +299,8 @@ {e3bbd7da-45c1-43ef-9c87-3f411031bde4} + false + false diff --git a/src/Reactor/Subzero.vcxproj.filters b/src/Reactor/Subzero.vcxproj.filters index 68cb2e833..42f0bdac2 100644 --- a/src/Reactor/Subzero.vcxproj.filters +++ b/src/Reactor/Subzero.vcxproj.filters @@ -120,10 +120,13 @@ Source Files - + Source Files - + + Source Files + + Source Files @@ -299,6 +302,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp index b92005cbd..a69103768 100644 --- a/src/Reactor/SubzeroReactor.cpp +++ b/src/Reactor/SubzeroReactor.cpp @@ -15,8 +15,7 @@ #include "Reactor.hpp" #include "Optimizer.hpp" - -#include "Common/Memory.hpp" +#include "Memory.hpp" #include "src/IceTypes.h" #include "src/IceCfg.h" @@ -49,7 +48,7 @@ #endif #endif -//#include +#include #include #include #include @@ -427,12 +426,12 @@ namespace rr T *allocate(size_type n) { - return (T*)sw::allocateExecutable(sizeof(T) * n); + return (T*)allocateExecutable(sizeof(T) * n); } void deallocate(T *p, size_type n) { - sw::deallocateExecutable(p, sizeof(T) * n); + deallocateExecutable(p, sizeof(T) * n); } }; diff --git a/src/Reactor/SubzeroTest.vcxproj.filters b/src/Reactor/SubzeroTest.vcxproj.filters deleted file mode 100644 index 4fc364349..000000000 --- a/src/Reactor/SubzeroTest.vcxproj.filters +++ /dev/null @@ -1,63 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/src/Reactor/Thread.cpp b/src/Reactor/Thread.cpp new file mode 100644 index 000000000..7a9b07da8 --- /dev/null +++ b/src/Reactor/Thread.cpp @@ -0,0 +1,91 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Thread.hpp" + +namespace rr +{ + Thread::Thread(void (*threadFunction)(void *parameters), void *parameters) + { + Event init; + Entry entry = {threadFunction, parameters, &init}; + + #if defined(_WIN32) + handle = CreateThread(NULL, 1024 * 1024, startFunction, &entry, 0, NULL); + #else + pthread_create(&handle, NULL, startFunction, &entry); + #endif + + init.wait(); + } + + Thread::~Thread() + { + join(); // Make threads exit before deleting them to not block here + } + + void Thread::join() + { + if(!hasJoined) + { + #if defined(_WIN32) + WaitForSingleObject(handle, INFINITE); + CloseHandle(handle); + #else + pthread_join(handle, NULL); + #endif + + hasJoined = true; + } + } + + #if defined(_WIN32) + unsigned long __stdcall Thread::startFunction(void *parameters) + { + Entry entry = *(Entry*)parameters; + entry.init->signal(); + entry.threadFunction(entry.threadParameters); + return 0; + } + #else + void *Thread::startFunction(void *parameters) + { + Entry entry = *(Entry*)parameters; + entry.init->signal(); + entry.threadFunction(entry.threadParameters); + return nullptr; + } + #endif + + Event::Event() + { + #if defined(_WIN32) + handle = CreateEvent(NULL, FALSE, FALSE, NULL); + #else + pthread_cond_init(&handle, NULL); + pthread_mutex_init(&mutex, NULL); + signaled = false; + #endif + } + + Event::~Event() + { + #if defined(_WIN32) + CloseHandle(handle); + #else + pthread_cond_destroy(&handle); + pthread_mutex_destroy(&mutex); + #endif + } +} diff --git a/src/Reactor/Thread.hpp b/src/Reactor/Thread.hpp new file mode 100644 index 000000000..7f8be136b --- /dev/null +++ b/src/Reactor/Thread.hpp @@ -0,0 +1,338 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef rr_Thread_hpp +#define rr_Thread_hpp + +#if defined(_WIN32) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include + #include +#else + #include + #include + #include + #define TLS_OUT_OF_INDEXES (pthread_key_t)(~0) +#endif + +#include + +#if defined(__clang__) +#if __has_include() // clang has an explicit check for the availability of atomic +#define USE_STD_ATOMIC 1 +#endif +// atomic is available in C++11 or newer, and in Visual Studio 2012 or newer +#elif (defined(_MSC_VER) && (_MSC_VER >= 1700)) || (__cplusplus >= 201103L) +#define USE_STD_ATOMIC 1 +#endif + +#if USE_STD_ATOMIC +#include +#endif + +namespace rr +{ + class Event; + + class Thread + { + public: + Thread(void (*threadFunction)(void *parameters), void *parameters); + + ~Thread(); + + void join(); + + static void yield(); + static void sleep(int milliseconds); + + #if defined(_WIN32) + typedef DWORD LocalStorageKey; + #else + typedef pthread_key_t LocalStorageKey; + #endif + + static LocalStorageKey allocateLocalStorageKey(void (*destructor)(void *storage) = free); + static void freeLocalStorageKey(LocalStorageKey key); + static void *allocateLocalStorage(LocalStorageKey key, size_t size); + static void *getLocalStorage(LocalStorageKey key); + static void freeLocalStorage(LocalStorageKey key); + + private: + struct Entry + { + void (*const threadFunction)(void *parameters); + void *threadParameters; + Event *init; + }; + + #if defined(_WIN32) + static unsigned long __stdcall startFunction(void *parameters); + HANDLE handle; + #else + static void *startFunction(void *parameters); + pthread_t handle; + #endif + + bool hasJoined = false; + }; + + class Event + { + friend class Thread; + + public: + Event(); + + ~Event(); + + void signal(); + void wait(); + + private: + #if defined(_WIN32) + HANDLE handle; + #else + pthread_cond_t handle; + pthread_mutex_t mutex; + volatile bool signaled; + #endif + }; + + #if PERF_PROFILE + int64_t atomicExchange(int64_t volatile *target, int64_t value); + #endif + + int atomicExchange(int volatile *target, int value); + int atomicIncrement(int volatile *value); + int atomicDecrement(int volatile *value); + int atomicAdd(int volatile *target, int value); + void nop(); +} + +namespace rr +{ + inline void Thread::yield() + { + #if defined(_WIN32) + Sleep(0); + #elif defined(__APPLE__) + pthread_yield_np(); + #else + sched_yield(); + #endif + } + + inline void Thread::sleep(int milliseconds) + { + #if defined(_WIN32) + Sleep(milliseconds); + #else + usleep(1000 * milliseconds); + #endif + } + + inline Thread::LocalStorageKey Thread::allocateLocalStorageKey(void (*destructor)(void *storage)) + { + #if defined(_WIN32) + return TlsAlloc(); + #else + LocalStorageKey key; + pthread_key_create(&key, destructor); + return key; + #endif + } + + inline void Thread::freeLocalStorageKey(LocalStorageKey key) + { + #if defined(_WIN32) + TlsFree(key); + #else + pthread_key_delete(key); // Using an invalid key is an error but not undefined behavior. + #endif + } + + inline void *Thread::allocateLocalStorage(LocalStorageKey key, size_t size) + { + if(key == TLS_OUT_OF_INDEXES) + { + return nullptr; + } + + freeLocalStorage(key); + + void *storage = malloc(size); + + #if defined(_WIN32) + TlsSetValue(key, storage); + #else + pthread_setspecific(key, storage); + #endif + + return storage; + } + + inline void *Thread::getLocalStorage(LocalStorageKey key) + { + #if defined(_WIN32) + return TlsGetValue(key); + #else + if(key == TLS_OUT_OF_INDEXES) // Avoid undefined behavior. + { + return nullptr; + } + + return pthread_getspecific(key); + #endif + } + + inline void Thread::freeLocalStorage(LocalStorageKey key) + { + free(getLocalStorage(key)); + + #if defined(_WIN32) + TlsSetValue(key, nullptr); + #else + pthread_setspecific(key, nullptr); + #endif + } + + inline void Event::signal() + { + #if defined(_WIN32) + SetEvent(handle); + #else + pthread_mutex_lock(&mutex); + signaled = true; + pthread_cond_signal(&handle); + pthread_mutex_unlock(&mutex); + #endif + } + + inline void Event::wait() + { + #if defined(_WIN32) + WaitForSingleObject(handle, INFINITE); + #else + pthread_mutex_lock(&mutex); + while(!signaled) pthread_cond_wait(&handle, &mutex); + signaled = false; + pthread_mutex_unlock(&mutex); + #endif + } + + #if PERF_PROFILE + inline int64_t atomicExchange(volatile int64_t *target, int64_t value) + { + #if defined(_WIN32) + return InterlockedExchange64(target, value); + #else + int ret; + __asm__ __volatile__("lock; xchg8 %0,(%1)" : "=r" (ret) :"r" (target), "0" (value) : "memory" ); + return ret; + #endif + } + #endif + + inline int atomicExchange(volatile int *target, int value) + { + #if defined(_WIN32) + return InterlockedExchange((volatile long*)target, (long)value); + #else + int ret; + __asm__ __volatile__("lock; xchgl %0,(%1)" : "=r" (ret) :"r" (target), "0" (value) : "memory" ); + return ret; + #endif + } + + inline int atomicIncrement(volatile int *value) + { + #if defined(_WIN32) + return InterlockedIncrement((volatile long*)value); + #else + return __sync_add_and_fetch(value, 1); + #endif + } + + inline int atomicDecrement(volatile int *value) + { + #if defined(_WIN32) + return InterlockedDecrement((volatile long*)value); + #else + return __sync_sub_and_fetch(value, 1); + #endif + } + + inline int atomicAdd(volatile int* target, int value) + { + #if defined(_WIN32) + return InterlockedExchangeAdd((volatile long*)target, value) + value; + #else + return __sync_add_and_fetch(target, value); + #endif + } + + inline void nop() + { + #if defined(_WIN32) + __nop(); + #else + __asm__ __volatile__ ("nop"); + #endif + } + + #if USE_STD_ATOMIC + class AtomicInt + { + public: + AtomicInt() : ai() {} + AtomicInt(int i) : ai(i) {} + + inline operator int() const { return ai.load(std::memory_order_acquire); } + inline void operator=(const AtomicInt& i) { ai.store(i.ai.load(std::memory_order_acquire), std::memory_order_release); } + inline void operator=(int i) { ai.store(i, std::memory_order_release); } + inline void operator--() { ai.fetch_sub(1, std::memory_order_acq_rel); } + inline void operator++() { ai.fetch_add(1, std::memory_order_acq_rel); } + inline int operator--(int) { return ai.fetch_sub(1, std::memory_order_acq_rel) - 1; } + inline int operator++(int) { return ai.fetch_add(1, std::memory_order_acq_rel) + 1; } + inline void operator-=(int i) { ai.fetch_sub(i, std::memory_order_acq_rel); } + inline void operator+=(int i) { ai.fetch_add(i, std::memory_order_acq_rel); } + private: + std::atomic ai; + }; + #else + class AtomicInt + { + public: + AtomicInt() {} + AtomicInt(int i) : vi(i) {} + + inline operator int() const { return vi; } // Note: this isn't a guaranteed atomic operation + inline void operator=(const AtomicInt& i) { atomicExchange(&vi, i.vi); } + inline void operator=(int i) { atomicExchange(&vi, i); } + inline void operator--() { atomicDecrement(&vi); } + inline void operator++() { atomicIncrement(&vi); } + inline int operator--(int) { return atomicDecrement(&vi); } + inline int operator++(int) { return atomicIncrement(&vi); } + inline void operator-=(int i) { atomicAdd(&vi, -i); } + inline void operator+=(int i) { atomicAdd(&vi, i); } + private: + volatile int vi; + }; + #endif +} + +#endif // rr_Thread_hpp diff --git a/src/Reactor/Types.hpp b/src/Reactor/Types.hpp new file mode 100644 index 000000000..428da5102 --- /dev/null +++ b/src/Reactor/Types.hpp @@ -0,0 +1,157 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef r3_Types_hpp +#define r3_Types_hpp + +#include +#include + +// GCC warns against bitfields not fitting the entire range of an enum with a fixed underlying type of unsigned int, which gets promoted to an error with -Werror and cannot be suppressed. +// However, GCC already defaults to using unsigned int as the underlying type of an unscoped enum without a fixed underlying type. So we can just omit it. +#if defined(__GNUC__) && !defined(__clang__) +namespace {enum E {}; static_assert(!std::numeric_limits::type>::is_signed, "expected unscoped enum whose underlying type is not fixed to be unsigned");} +#define ENUM_UNDERLYING_TYPE_UNSIGNED_INT +#else +#define ENUM_UNDERLYING_TYPE_UNSIGNED_INT : unsigned int +#endif + +#if defined(_MSC_VER) + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef signed __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + #define ALIGN(bytes, type) __declspec(align(bytes)) type +#else + #include + #define ALIGN(bytes, type) type __attribute__((aligned(bytes))) +#endif + +namespace rr +{ + typedef ALIGN(1, uint8_t) byte; + typedef ALIGN(2, uint16_t) word; + typedef ALIGN(4, uint32_t) dword; + typedef ALIGN(8, uint64_t) qword; + typedef ALIGN(16, uint64_t) qword2[2]; + typedef ALIGN(4, uint8_t) byte4[4]; + typedef ALIGN(8, uint8_t) byte8[8]; + typedef ALIGN(16, uint8_t) byte16[16]; + typedef ALIGN(8, uint16_t) word4[4]; + typedef ALIGN(8, uint32_t) dword2[2]; + typedef ALIGN(16, uint32_t) dword4[4]; + typedef ALIGN(16, uint64_t) xword[2]; + + typedef ALIGN(1, int8_t) sbyte; + typedef ALIGN(4, int8_t) sbyte4[4]; + typedef ALIGN(8, int8_t) sbyte8[8]; + typedef ALIGN(16, int8_t) sbyte16[16]; + typedef ALIGN(8, short) short4[4]; + typedef ALIGN(8, unsigned short) ushort4[4]; + typedef ALIGN(16, short) short8[8]; + typedef ALIGN(16, unsigned short) ushort8[8]; + typedef ALIGN(8, int) int2[2]; + typedef ALIGN(8, unsigned int) uint2[2]; + typedef ALIGN(16, unsigned int) uint4[4]; + + typedef ALIGN(8, float) float2[2]; + + ALIGN(16, struct int4 + { + int x; + int y; + int z; + int w; + + int &operator[](int i) + { + return (&x)[i]; + } + + const int &operator[](int i) const + { + return (&x)[i]; + } + + bool operator!=(const int4 &rhs) + { + return x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w; + } + + bool operator==(const int4 &rhs) + { + return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; + } + }); + + ALIGN(16, struct float4 + { + float x; + float y; + float z; + float w; + + float &operator[](int i) + { + return (&x)[i]; + } + + const float &operator[](int i) const + { + return (&x)[i]; + } + + bool operator!=(const float4 &rhs) + { + return x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w; + } + + bool operator==(const float4 &rhs) + { + return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; + } + }); + + inline float4 vector(float x, float y, float z, float w) + { + float4 v; + + v.x = x; + v.y = y; + v.z = z; + v.w = w; + + return v; + } + + inline float4 replicate(float f) + { + float4 v; + + v.x = f; + v.y = f; + v.z = f; + v.w = f; + + return v; + } + + #define OFFSET(s,m) (int)(size_t)&reinterpret_cast((((s*)0)->m)) +} + +#endif // r3_Types_hpp diff --git a/tests/unittests/unittests.vcxproj b/tests/unittests/GLESUnitTests.vcxproj similarity index 97% rename from tests/unittests/unittests.vcxproj rename to tests/unittests/GLESUnitTests.vcxproj index 424d30ad5..7769b9243 100644 --- a/tests/unittests/unittests.vcxproj +++ b/tests/unittests/GLESUnitTests.vcxproj @@ -21,7 +21,7 @@ {CF8EBC89-8762-49DC-9440-6C82B3499913} Win32Proj - unittests + GLESUnitTests 10.0.16299.0 diff --git a/tests/unittests/unittests.vcxproj.filters b/tests/unittests/GLESUnitTests.vcxproj.filters similarity index 100% rename from tests/unittests/unittests.vcxproj.filters rename to tests/unittests/GLESUnitTests.vcxproj.filters diff --git a/tests/unittests/unittests.vcxproj.user b/tests/unittests/GLESUnitTests.vcxproj.user similarity index 100% rename from tests/unittests/unittests.vcxproj.user rename to tests/unittests/GLESUnitTests.vcxproj.user