Make REACTOR_EMIT_DEBUG_INFO work on Windows and add "print on emit" support
- Use boost::stacktrace instead of libbacktrace so that we get can get
callstacks on Windows as well. Note that on non-Windows, we tell
boost::stacktrace to use libbacktrace.
- REACTOR_EMIT_DEBUG_INFO can now be enabled on all platforms
- Fix RR_LOG not building on MSVC by using __FUNCSIG__ instead of
__PRETTY_FUNCTION__.
- Enable CMake option REACTOR_EMIT_PRINT_LOCATION so that EmitLocation
in LLVMReactorDebugInfo.cpp injects printfs with func/file/line.
Sample output:
rr> sw::Blitter::generate [c:\src\swiftshader\src\renderer\blitter.cpp:1303]
rr> sw::Blitter::generate [c:\src\swiftshader\src\renderer\blitter.cpp:1304]
rr> sw::Blitter::ComputeOffset [c:\src\swiftshader\src\renderer\blitter.cpp:1148]
rr> sw::Blitter::generate [c:\src\swiftshader\src\renderer\blitter.cpp:1312]
rr> sw::Blitter::generate [c:\src\swiftshader\src\renderer\blitter.cpp:1314]
rr> sw::SetupRoutine::edge [c:\src\swiftshader\src\shader\setuproutine.cpp:566]
Bug: b/131425026
Change-Id: Ia3b78652f4a76dcd6597ce2df61a236c4a90acc2
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30030
Tested-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b4c0a1..b270abe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -75,13 +75,14 @@
option(BUILD_SAMPLES "Build sample programs" 1)
option(BUILD_TESTS "Build test programs" 1)
-option (MSAN "Build with memory sanitizer" 0)
-option (ASAN "Build with address sanitizer" 0)
-option (TSAN "Build with thread sanitizer" 0)
-option (UBSAN "Build with undefined behavior sanitizer" 0)
-option (WARNINGS_AS_ERRORS "Treat all warnings as errors" 1)
-option (DCHECK_ALWAYS_ON "Check validation macros even in release builds" 0)
-option (REACTOR_EMIT_DEBUG_INFO "Emit debug info for JIT functions" 0)
+option(MSAN "Build with memory sanitizer" 0)
+option(ASAN "Build with address sanitizer" 0)
+option(TSAN "Build with thread sanitizer" 0)
+option(UBSAN "Build with undefined behavior sanitizer" 0)
+option(WARNINGS_AS_ERRORS "Treat all warnings as errors" 1)
+option(DCHECK_ALWAYS_ON "Check validation macros even in release builds" 0)
+option(REACTOR_EMIT_DEBUG_INFO "Emit debug info for JIT functions" 0)
+option(REACTOR_EMIT_PRINT_LOCATION "Emit printing of location info for JIT functions" 0)
if(ARCH STREQUAL "arm")
set(DEFAULT_REACTOR_BACKEND "Subzero")
@@ -336,10 +337,6 @@
list(APPEND SWIFTSHADER_COMPILE_OPTIONS "-DDCHECK_ALWAYS_ON")
endif()
- if(REACTOR_EMIT_DEBUG_INFO)
- list(APPEND SWIFTSHADER_COMPILE_OPTIONS "-DENABLE_RR_DEBUG_INFO")
- endif()
-
# Disable pedanitc warnings
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
list(APPEND SWIFTSHADER_COMPILE_OPTIONS
@@ -383,6 +380,17 @@
endif()
endif()
+if(REACTOR_EMIT_PRINT_LOCATION)
+ # This feature depends on REACTOR_EMIT_DEBUG_INFO, so enable it
+ set(REACTOR_EMIT_DEBUG_INFO "On")
+ list(APPEND SWIFTSHADER_COMPILE_OPTIONS "-DENABLE_RR_EMIT_PRINT_LOCATION")
+endif()
+
+if(REACTOR_EMIT_DEBUG_INFO)
+ message(WARNING "REACTOR_EMIT_DEBUG_INFO is enabled. This will likely affect performance.")
+ list(APPEND SWIFTSHADER_COMPILE_OPTIONS "-DENABLE_RR_DEBUG_INFO")
+endif()
+
if(WIN32)
add_definitions(-DWINVER=0x501 -DNOMINMAX -DSTRICT)
set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "" "lib")
@@ -1232,7 +1240,6 @@
if(WIN32)
list(APPEND LLVM_INCLUDE_DIR ${LLVM_CONFIG_DIR}/windows/include)
- list(APPEND LIBBACKTRACE_INCLUDE_DIR ${LIBBACKTRACE_CONFIG_DIR}/windows/include)
elseif(LINUX)
list(APPEND LLVM_INCLUDE_DIR ${LLVM_CONFIG_DIR}/linux/include)
list(APPEND LIBBACKTRACE_INCLUDE_DIR ${LIBBACKTRACE_CONFIG_DIR}/linux/include)
@@ -1375,6 +1382,7 @@
set(SUBZERO_REACTOR_LIST
${SOURCE_DIR}/Reactor/Reactor.cpp
+ ${SOURCE_DIR}/Reactor/Reactor.hpp
${SOURCE_DIR}/Reactor/SubzeroReactor.cpp
${SOURCE_DIR}/Reactor/Routine.cpp
${SOURCE_DIR}/Reactor/Optimizer.cpp
@@ -1505,6 +1513,7 @@
set(REACTOR_LLVM_LIST
${SOURCE_DIR}/Reactor/Reactor.cpp
+ ${SOURCE_DIR}/Reactor/Reactor.hpp
${SOURCE_DIR}/Reactor/LLVMReactor.cpp
${SOURCE_DIR}/Reactor/LLVMReactor.hpp
${SOURCE_DIR}/Reactor/LLVMReactorDebugInfo.cpp
@@ -1708,14 +1717,31 @@
target_link_libraries(ReactorLLVM llvm ${OS_LIBS})
if(REACTOR_EMIT_DEBUG_INFO)
- add_library(Libbacktrace STATIC ${LIBBACKTRACE_LIST})
- set_target_properties(Libbacktrace PROPERTIES
- INCLUDE_DIRECTORIES "${LIBBACKTRACE_INCLUDE_DIR}"
- POSITION_INDEPENDENT_CODE 1
- FOLDER "Core"
+ add_library(Boost INTERFACE)
+ target_include_directories(Boost INTERFACE
+ "${CMAKE_CURRENT_SOURCE_DIR}/third_party/boost"
)
- target_link_libraries(Libbacktrace ${OS_LIBS})
- target_link_libraries(ReactorLLVM Libbacktrace)
+ if(WIN32)
+ # Boost stacktrace uses COM on Windows.
+ # On Windows, cache COM instances in TLS for performance.
+ target_compile_definitions(Boost INTERFACE BOOST_STACKTRACE_USE_WINDBG_CACHED)
+ else()
+ # Boost stacktrace uses libbacktrace
+ target_compile_definitions(Boost INTERFACE BOOST_STACKTRACE_USE_BACKTRACE)
+
+ # Boost stacktrace uses exceptions, so force enable it
+ set_cpp_flag("-fexceptions")
+
+ add_library(Libbacktrace STATIC ${LIBBACKTRACE_LIST})
+ set_target_properties(Libbacktrace PROPERTIES
+ INCLUDE_DIRECTORIES "${LIBBACKTRACE_INCLUDE_DIR}"
+ POSITION_INDEPENDENT_CODE 1
+ FOLDER "Core"
+ )
+ target_link_libraries(Libbacktrace ${OS_LIBS})
+ target_link_libraries(ReactorLLVM Libbacktrace)
+ endif()
+ target_link_libraries(ReactorLLVM Boost)
endif(REACTOR_EMIT_DEBUG_INFO)
set(Reactor ReactorLLVM)
diff --git a/src/Reactor/LLVMReactorDebugInfo.cpp b/src/Reactor/LLVMReactorDebugInfo.cpp
index 5b00585..d021a5f 100644
--- a/src/Reactor/LLVMReactorDebugInfo.cpp
+++ b/src/Reactor/LLVMReactorDebugInfo.cpp
@@ -19,7 +19,7 @@
#include "Reactor.hpp"
#include "LLVMReactor.hpp"
-#include "backtrace.h"
+#include "boost/stacktrace.hpp"
#include "llvm/Demangle/Demangle.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
@@ -109,6 +109,20 @@
auto const& backtrace = getCallerBacktrace();
syncScope(backtrace);
builder->SetCurrentDebugLocation(getLocation(backtrace, backtrace.size() - 1));
+
+#ifdef ENABLE_RR_EMIT_PRINT_LOCATION
+ static Location lastLocation;
+ if (backtrace.size() == 0)
+ {
+ return;
+ }
+ Location currLocation = backtrace[backtrace.size() - 1];
+ if (currLocation != lastLocation)
+ {
+ rr::Print("rr> {0} [{1}:{2}]\n", currLocation.function.name.c_str(), currLocation.function.file.c_str(), currLocation.line);
+ lastLocation = std::move(currLocation);
+ }
+#endif // ENABLE_RR_EMIT_PRINT_LOCATION
}
void DebugInfo::Flush()
@@ -178,7 +192,7 @@
size_t size = sizeof(buf);
int status = 0;
llvm::itaniumDemangle(location.function.name.c_str(), buf, &size, &status);
- auto name = status == 0 ? buf : location.function.name.c_str();
+ auto name = "jit!" + (status == 0 ? std::string(buf) : location.function.name);
auto func = diBuilder->createFunction(
file, // scope
@@ -414,48 +428,41 @@
DebugInfo::Backtrace DebugInfo::getCallerBacktrace(size_t limit /* = 0 */) const
{
- struct callbacks
- {
- static void onError(void *data, const char *msg, int errnum)
- {
- fprintf(stderr, "BACKTRACE ERROR %d: %s\n", errnum, msg);
- }
-
- static int onPCInfo(void *data, uintptr_t pc, const char *file, int line, const char *function)
- {
- if (file == nullptr) { return 0; }
-
- auto const &fileSR = llvm::StringRef(file);
- if (fileSR.endswith("ReactorDebugInfo.cpp") ||
- fileSR.endswith("Reactor.cpp") ||
- fileSR.endswith("Reactor.hpp"))
- {
- return 0;
- }
-
- auto cb = reinterpret_cast<callbacks*>(data);
-
- Location location;
- location.function.file = file;
- location.function.name = function;
- location.line = line;
-
- cb->locations.push_back(location);
- return (cb->limit == 0 || sizeof(cb->locations) < cb->limit) ? 0 : 1;
- }
-
- size_t limit;
- std::vector<DebugInfo::Location> locations;
+ auto shouldSkipFile = [](llvm::StringRef fileSR) {
+ return fileSR.empty() ||
+ fileSR.endswith_lower("ReactorDebugInfo.cpp") ||
+ fileSR.endswith_lower("Reactor.cpp") ||
+ fileSR.endswith_lower("Reactor.hpp") ||
+ fileSR.endswith_lower("stacktrace.hpp");
};
- callbacks callbacks;
- callbacks.limit = limit;
- static auto state = backtrace_create_state(nullptr, 0, &callbacks::onError, nullptr);
- backtrace_full(state, 1, &callbacks::onPCInfo, &callbacks::onError, &callbacks);
+ std::vector<DebugInfo::Location> locations;
- std::reverse(callbacks.locations.begin(), callbacks.locations.end());
+ // Note that bs::stacktrace() effectively returns a vector of addresses; bs::frame construction is where
+ // the heavy lifting is done: resolving the function name, file and line number.
+ namespace bs = boost::stacktrace;
+ for (bs::frame frame : bs::stacktrace())
+ {
+ if (shouldSkipFile(frame.source_file()))
+ {
+ continue;
+ }
- return callbacks.locations;
+ DebugInfo::Location location;
+ location.function.file = frame.source_file();
+ location.function.name = frame.name();
+ location.line = frame.source_line();
+ locations.push_back(location);
+
+ if (limit > 0 && locations.size() >= limit)
+ {
+ break;
+ }
+ }
+
+ std::reverse(locations.begin(), locations.end());
+
+ return locations;
}
llvm::DIType *DebugInfo::getOrCreateType(llvm::Type* type)
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index 5cf1be0..8ac97d5 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -3420,7 +3420,11 @@
//
// RR_LOG() is intended to be used for debugging JIT compiled code, and is
// not intended for production use.
- #define RR_LOG(msg, ...) Print(__PRETTY_FUNCTION__, __FILE__, __LINE__, msg "\n", ##__VA_ARGS__)
+ #if defined(_WIN32)
+ #define RR_LOG(msg, ...) Print(__FUNCSIG__, __FILE__, __LINE__, msg "\n", ##__VA_ARGS__)
+ #else
+ #define RR_LOG(msg, ...) Print(__PRETTY_FUNCTION__, __FILE__, __LINE__, msg "\n", ##__VA_ARGS__)
+ #endif
// Macro magic to perform variadic dispatch.
// See: https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/__VA_ARGS__/count-arguments