Commit f448d8e1 by Antonio Maiorano

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/+/30030Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 829ad4c5
......@@ -75,13 +75,14 @@ option(USE_GROUP_SOURCES "Group the source files in a folder tree for Visual Stu
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 @@ else()
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 @@ else()
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 @@ set(LLVM_INCLUDE_DIR "")
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 @@ if(${REACTOR_BACKEND} STREQUAL "Subzero")
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 @@ endif(REACTOR_EMIT_DEBUG_INFO)
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 @@ if(${REACTOR_BACKEND} STREQUAL "LLVM")
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)
......
......@@ -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 @@ namespace rr
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 @@ namespace rr
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 @@ namespace rr
DebugInfo::Backtrace DebugInfo::getCallerBacktrace(size_t limit /* = 0 */) const
{
struct callbacks
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");
};
std::vector<DebugInfo::Location> locations;
// 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())
{
static void onError(void *data, const char *msg, int errnum)
if (shouldSkipFile(frame.source_file()))
{
fprintf(stderr, "BACKTRACE ERROR %d: %s\n", errnum, msg);
continue;
}
static int onPCInfo(void *data, uintptr_t pc, const char *file, int line, const char *function)
{
if (file == nullptr) { return 0; }
DebugInfo::Location location;
location.function.file = frame.source_file();
location.function.name = frame.name();
location.line = frame.source_line();
locations.push_back(location);
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;
if (limit > 0 && locations.size() >= limit)
{
break;
}
}
size_t limit;
std::vector<DebugInfo::Location> locations;
};
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::reverse(callbacks.locations.begin(), callbacks.locations.end());
std::reverse(locations.begin(), locations.end());
return callbacks.locations;
return locations;
}
llvm::DIType *DebugInfo::getOrCreateType(llvm::Type* type)
......
......@@ -3420,7 +3420,11 @@ namespace rr
//
// 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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment