diff --git a/.github/workflows/sycl_post_commit.yml b/.github/workflows/sycl_post_commit.yml index 02b27d2d89420..3e0a5bb49b1fe 100644 --- a/.github/workflows/sycl_post_commit.yml +++ b/.github/workflows/sycl_post_commit.yml @@ -36,6 +36,7 @@ jobs: lts_matrix: ${{ needs.test_matrix.outputs.lts_matrix }} cts_matrix: ${{ needs.test_matrix.outputs.cts_matrix }} lts_aws_matrix: ${{ needs.test_matrix.outputs.lts_aws_matrix }} + build_configure_extra_args: --cmake-opt="-DSYCL_ENABLE_STACK_PRINTING=ON" --cmake-opt="-DSYCL_LIB_WITH_DEBUG_SYMBOL=ON" linux_no_assert: name: Linux (no assert) if: github.repository == 'intel/llvm' diff --git a/sycl/CMakeLists.txt b/sycl/CMakeLists.txt index 389342f8f71fb..8d7ca1a3af17f 100644 --- a/sycl/CMakeLists.txt +++ b/sycl/CMakeLists.txt @@ -9,6 +9,8 @@ option(SYCL_ENABLE_WERROR "Treat all warnings as errors in SYCL project" OFF) option(SYCL_DISABLE_STL_ASSERTIONS "Disable assertions in STL containers" ON) option(SYCL_ADD_DEV_VERSION_POSTFIX "Adds -V postfix to version string" ON) option(SYCL_ENABLE_COVERAGE "Enables code coverage for runtime and unit tests" OFF) +option(SYCL_ENABLE_STACK_PRINTING "Enables stack printing on crashes of SYCL applications" OFF) +option(SYCL_LIB_WITH_DEBUG_SYMBOLS "Builds SYCL runtime libraries with debug symbols" OFF) if (NOT SYCL_COVERAGE_PATH) set(SYCL_COVERAGE_PATH "${CMAKE_CURRENT_BINARY_DIR}/profiles") @@ -327,6 +329,10 @@ if (SYCL_ENABLE_XPTI_TRACING) endif() endif() +if (SYCL_ENABLE_STACK_PRINTING) + add_dependencies(sycl-toolchain llvm-symbolizer) +endif() + option(SYCL_INCLUDE_TESTS "Generate build targets for the SYCL unit tests." ${LLVM_INCLUDE_TESTS}) diff --git a/sycl/cmake/modules/AddSYCL.cmake b/sycl/cmake/modules/AddSYCL.cmake index d4e4f385629f1..9956037568edf 100644 --- a/sycl/cmake/modules/AddSYCL.cmake +++ b/sycl/cmake/modules/AddSYCL.cmake @@ -24,6 +24,12 @@ function(add_sycl_library LIB_NAME TYPE) add_stripped_pdb(${LIB_NAME}) endif() + # TODO: Enabled for MSVC + if (NOT MSVC AND SYCL_LIB_WITH_DEBUG_SYMBOLS) + separate_arguments(CMAKE_CXX_FLAGS_DEBUG_SEPARATED UNIX_COMMAND "${CMAKE_CXX_FLAGS_DEBUG}") + target_compile_options(${LIB_NAME} PRIVATE ${CMAKE_CXX_FLAGS_DEBUG_SEPARATED}) + endif() + # TODO remove add_common_options add_common_options(${LIB_NAME}) endfunction() diff --git a/sycl/source/CMakeLists.txt b/sycl/source/CMakeLists.txt index c9a1ba4101296..778599f5f5f44 100644 --- a/sycl/source/CMakeLists.txt +++ b/sycl/source/CMakeLists.txt @@ -26,6 +26,23 @@ function(add_sycl_rt_library LIB_NAME LIB_OBJ_NAME) $ ${CMAKE_CURRENT_BINARY_DIR}/version.rc) + # Unlike for sycl library, for LLVMSupport we have only one version for a given build, + # so, we link LLVMSupport lib to matching sycl version only. + if (SYCL_ENABLE_STACK_PRINTING) + if(NOT MSVC OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ARG_COMPILE_OPTIONS MATCHES ".*MDd.*") OR + (NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT ARG_COMPILE_OPTIONS MATCHES ".*MDd.*")) + add_dependencies(${LIB_NAME} LLVMSupport) + target_compile_definitions(${LIB_OBJ_NAME} PUBLIC ENABLE_STACK_TRACE) + target_link_libraries(${LIB_NAME} PRIVATE LLVMSupport) + endif() + endif() + + # TODO: Enabled for MSVC + if (NOT MSVC AND SYCL_LIB_WITH_DEBUG_SYMBOLS) + separate_arguments(CMAKE_CXX_FLAGS_DEBUG_SEPARATED UNIX_COMMAND "${CMAKE_CXX_FLAGS_DEBUG}") + target_compile_options(${LIB_NAME} PRIVATE ${CMAKE_CXX_FLAGS_DEBUG_SEPARATED}) + endif() + if (SYCL_ENABLE_COVERAGE) target_compile_options(${LIB_OBJ_NAME} PUBLIC -fprofile-instr-generate -fcoverage-mapping diff --git a/sycl/source/detail/global_handler.cpp b/sycl/source/detail/global_handler.cpp index 91aac69cd30aa..aeb1b99cb5703 100644 --- a/sycl/source/detail/global_handler.cpp +++ b/sycl/source/detail/global_handler.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +#ifdef ENABLE_STACK_TRACE +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Signals.h" +#endif + #include #include #include @@ -95,9 +100,25 @@ void GlobalHandler::attachScheduler(Scheduler *Scheduler) { MScheduler.Inst.reset(Scheduler); } +static void enableOnCrashStackPrinting() { +#ifdef ENABLE_STACK_TRACE + static std::once_flag PrintStackFlag; + std::call_once(PrintStackFlag, []() { + llvm::sys::PrintStackTraceOnErrorSignal(llvm::StringRef()); + }); +#endif +} + Scheduler &GlobalHandler::getScheduler() { getOrCreate(MScheduler); registerSchedulerUsage(); + // On Windows the registration of the signal handler before main function + // (e.g. from DLLMain or from constructors of program scope objects) doesn't + // work. So, registering signal handler here because: + // 1) getScheduler is likely to be called for any non-trivial application; + // 2) first call to getScheduler is likely to be done after main starts. + // The same is done in getPlugins. + enableOnCrashStackPrinting(); return *MScheduler.Inst; } @@ -132,6 +153,7 @@ std::mutex &GlobalHandler::getFilterMutex() { return getOrCreate(MFilterMutex); } std::vector &GlobalHandler::getPlugins() { + enableOnCrashStackPrinting(); return getOrCreate(MPlugins); } device_filter_list & diff --git a/sycl/test/Unit/lit.cfg.py b/sycl/test/Unit/lit.cfg.py index 9ad08d5cde55c..162ff0ebbee3b 100644 --- a/sycl/test/Unit/lit.cfg.py +++ b/sycl/test/Unit/lit.cfg.py @@ -50,6 +50,9 @@ if symbolizer in os.environ: config.environment[symbolizer] = os.environ[symbolizer] +llvm_symbolizer = os.path.join(config.llvm_tools_dir, 'llvm-symbolizer') +config.environment['LLVM_SYMBOLIZER_PATH'] = llvm_symbolizer + def find_shlibpath_var(): if platform.system() in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']: yield 'LD_LIBRARY_PATH' diff --git a/sycl/test/lit.cfg.py b/sycl/test/lit.cfg.py index eb7be1feb334d..d0b10d1298b36 100644 --- a/sycl/test/lit.cfg.py +++ b/sycl/test/lit.cfg.py @@ -93,6 +93,9 @@ config.substitutions.append( ('%llvm_build_lib_dir', config.llvm_build_lib_dir ) ) config.substitutions.append( ('%llvm_build_bin_dir', config.llvm_build_bin_dir ) ) +llvm_symbolizer = os.path.join(config.llvm_build_bin_dir, 'llvm-symbolizer') +llvm_config.with_environment('LLVM_SYMBOLIZER_PATH', llvm_symbolizer) + config.substitutions.append( ('%fsycl-host-only', '-std=c++17 -Xclang -fsycl-is-host -isystem %s -isystem %s -isystem %s -isystem %s' % (config.sycl_include, config.level_zero_include_dir, config.opencl_include_dir, config.sycl_include + '/sycl/') ) ) config.substitutions.append( ('%sycl_lib', ' -lsycl6' if platform.system() == "Windows" else '-lsycl') )