Skip to content

Commit cdd4adf

Browse files
committed
[FFI] Improve traceback setups
This PR improves traceback related setups
1 parent ffcd998 commit cdd4adf

File tree

17 files changed

+205
-141
lines changed

17 files changed

+205
-141
lines changed

ffi/CMakeLists.txt

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ if (MSVC)
126126
target_link_libraries(tvm_ffi_objs PRIVATE DbgHelp.lib)
127127
target_link_libraries(tvm_ffi_shared PRIVATE DbgHelp.lib)
128128
target_link_libraries(tvm_ffi_static PRIVATE DbgHelp.lib)
129+
# produce pdb file
130+
target_link_options(tvm_ffi_shared PRIVATE /DEBUG)
129131
endif ()
130132

131133
# expose the headers as public dependencies
@@ -141,24 +143,21 @@ if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
141143
return()
142144
endif()
143145

144-
option(TVM_FFI_USE_RELEASE_FLAGS "Set O3 with RelWithDebInfo, useful to get lineno" OFF)
146+
option(TVM_FFI_ATTACH_DEBUG_SYMBOLS "Attach debug symbols even in release mode" OFF)
145147
option(TVM_FFI_BUILD_TESTS "Adding test targets." OFF)
146148

147-
# related options
148-
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
149-
if (TVM_FFI_USE_RELEASE_FLAGS)
150-
message(STATUS "Targeting global CXX flags to -O3 for optimized build")
151-
target_compile_options(tvm_ffi_objs PRIVATE -O3 -g)
152-
target_compile_options(tvm_ffi_shared PRIVATE -O3)
153-
target_compile_options(tvm_ffi_static PRIVATE -O3)
149+
if (TVM_FFI_ATTACH_DEBUG_SYMBOLS)
150+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
151+
target_compile_options(tvm_ffi_objs PRIVATE -g1)
154152
endif()
155153
endif()
156154

157-
158155
include(cmake/Utils/CxxWarning.cmake)
159156
include(cmake/Utils/Sanitizer.cmake)
160157

161-
tvm_ffi_add_cxx_warning(tvm_ffi_objs)
158+
# remap the file name to the source directory so we can see the
159+
# exact file name in traceback relative to the project source root
160+
tvm_ffi_add_prefix_map(tvm_ffi_objs ${CMAKE_SOURCE_DIR})
162161

163162
########## Adding cpp tests ##########
164163

@@ -169,21 +168,7 @@ if (TVM_FFI_BUILD_TESTS)
169168
message(STATUS "Enable Testing")
170169
include(cmake/Utils/AddGoogleTest.cmake)
171170
add_subdirectory(tests/cpp/)
172-
endif()
173-
174-
########## Install the related for normal cmake library ##########
175-
176-
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/tvm/ffi/ DESTINATION include/tvm/ffi/)
177-
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/dlpack/include/ DESTINATION include/)
178-
179-
if (WIN32)
180-
# on windows, install by target is more robust as sometimes target may
181-
# append subfolders lib/Release in msbuild
182-
install(TARGETS tvm_ffi_shared tvm_ffi_static DESTINATION lib)
183-
else()
184-
# on mac and other platforms, install by dir helps to also copy
185-
# .dSYM over for debugging symbols
186-
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib/ DESTINATION lib)
171+
tvm_ffi_add_cxx_warning(tvm_ffi_objs)
187172
endif()
188173

189174
########## Adding python module ##########
@@ -208,9 +193,12 @@ if (TVM_FFI_BUILD_PYTHON_MODULE)
208193
${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/object.pxi
209194
${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/string.pxi
210195
)
196+
# set working directory to source so we can see the exact file name in traceback
197+
# relatived to the project source root
211198
add_custom_command(
212199
OUTPUT ${core_cpp}
213200
COMMAND ${Python_EXECUTABLE} -m cython --cplus ${core_pyx} -o ${core_cpp}
201+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
214202
COMMENT "Transpiling ${core_pyx} to ${core_cpp}"
215203
DEPENDS ${cython_sources}
216204
VERBATIM
@@ -247,3 +235,18 @@ if (TVM_FFI_BUILD_PYTHON_MODULE)
247235
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt DESTINATION .)
248236
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/tvm_ffi-config.cmake DESTINATION lib/cmake/tvm_ffi/)
249237
endif()
238+
239+
########## Install the related for normal cmake library ##########
240+
241+
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/tvm/ffi/ DESTINATION include/tvm/ffi/)
242+
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/dlpack/include/ DESTINATION include/)
243+
install(TARGETS tvm_ffi_shared DESTINATION lib)
244+
# ship additional dSYM files for debugging symbols on if available
245+
if (APPLE)
246+
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib/ DESTINATION lib FILES_MATCHING PATTERN "*.dSYM")
247+
endif()
248+
249+
if (NOT TVM_FFI_BUILD_PYTHON_MODULE)
250+
# when building wheel, we do not ship static as we already ships source and dll
251+
install(TARGETS tvm_ffi_static DESTINATION lib)
252+
endif()

ffi/cmake/Utils/Library.cmake

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17+
18+
function(tvm_ffi_add_prefix_map target_name prefix_path)
19+
# Add prefix map so the path displayed becomes relative to prefix_path
20+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
21+
target_compile_options(${target_name} PRIVATE "-ffile-prefix-map=${prefix_path}/=")
22+
endif()
23+
endfunction()
24+
1725
function(tvm_ffi_add_apple_dsymutil target_name)
1826
# running dsymutil on macos to generate debugging symbols for backtraces
1927
if(APPLE AND TVM_FFI_USE_LIBBACKTRACE)
@@ -36,7 +44,7 @@ function(tvm_ffi_add_msvc_flags target_name)
3644
target_compile_definitions(${target_name} PUBLIC -D_SCL_SECURE_NO_WARNINGS)
3745
target_compile_definitions(${target_name} PUBLIC -D_ENABLE_EXTENDED_ALIGNED_STORAGE)
3846
target_compile_definitions(${target_name} PUBLIC -DNOMINMAX)
39-
target_compile_options(${target_name} PRIVATE "/Z7")
47+
target_compile_options(${target_name} PRIVATE "/Zi")
4048
endif()
4149
endfunction()
4250

@@ -77,5 +85,4 @@ function(tvm_ffi_add_target_from_obj target_name obj_target_name)
7785
endforeach()
7886
endif()
7987
tvm_ffi_add_apple_dsymutil(${target_name}_shared)
80-
tvm_ffi_add_msvc_flags(${target_name}_shared)
8188
endfunction()

ffi/include/tvm/ffi/c_api.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -836,13 +836,15 @@ TVM_FFI_DLL const TVMFFITypeAttrColumn* TVMFFIGetTypeAttrColumn(const TVMFFIByte
836836
* \param filename The current file name.
837837
* \param lineno The current line number
838838
* \param func The current function
839+
* \param cross_ffi_boundary Whether the traceback is crossing the ffi boundary
840+
* or we should stop at the ffi boundary when detected
839841
* \return The traceback string
840842
*
841-
* \note filename func and lino are only used as a backup info, most cases they are not needed.
842-
* The return value is set to const char* to be more compatible across dll boundaries.
843+
* \note filename/func can be nullptr, then these info are skipped, they are useful
844+
* for cases when debug symbols is not available.
843845
*/
844846
TVM_FFI_DLL const TVMFFIByteArray* TVMFFITraceback(const char* filename, int lineno,
845-
const char* func);
847+
const char* func, int cross_ffi_boundary);
846848

847849
/*!
848850
* \brief Initialize the type info during runtime.

ffi/include/tvm/ffi/error.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,6 @@ class ErrorBuilder {
201201
bool log_before_throw_;
202202
};
203203

204-
// define traceback here as call into traceback function
205-
#define TVM_FFI_TRACEBACK_HERE TVMFFITraceback(__FILE__, __LINE__, TVM_FFI_FUNC_SIG)
206204
} // namespace details
207205

208206
/*!
@@ -216,9 +214,10 @@ class ErrorBuilder {
216214
*
217215
* \endcode
218216
*/
219-
#define TVM_FFI_THROW(ErrorKind) \
220-
::tvm::ffi::details::ErrorBuilder(#ErrorKind, TVM_FFI_TRACEBACK_HERE, \
221-
TVM_FFI_ALWAYS_LOG_BEFORE_THROW) \
217+
#define TVM_FFI_THROW(ErrorKind) \
218+
::tvm::ffi::details::ErrorBuilder(#ErrorKind, \
219+
TVMFFITraceback(__FILE__, __LINE__, TVM_FFI_FUNC_SIG, 0), \
220+
TVM_FFI_ALWAYS_LOG_BEFORE_THROW) \
222221
.stream()
223222

224223
/*!
@@ -228,8 +227,10 @@ class ErrorBuilder {
228227
* cannot be caught, and it is better to have a clear log message.
229228
* In most cases, we should use use TVM_FFI_THROW.
230229
*/
231-
#define TVM_FFI_LOG_AND_THROW(ErrorKind) \
232-
::tvm::ffi::details::ErrorBuilder(#ErrorKind, TVM_FFI_TRACEBACK_HERE, true).stream()
230+
#define TVM_FFI_LOG_AND_THROW(ErrorKind) \
231+
::tvm::ffi::details::ErrorBuilder( \
232+
#ErrorKind, TVMFFITraceback(__FILE__, __LINE__, TVM_FFI_FUNC_SIG, 0), true) \
233+
.stream()
233234

234235
// Glog style checks with TVM_FFI prefix
235236
// NOTE: we explicitly avoid glog style generic macros (LOG/CHECK) in tvm ffi

ffi/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ build.verbose = true
6262
cmake.version = "CMakeLists.txt"
6363
cmake.build-type = "Release"
6464
cmake.args = [
65-
"-DTVM_FFI_USE_RELEASE_FLAGS=ON",
65+
"-DTVM_FFI_ATTACH_DEBUG_SYMBOLS=ON",
6666
"-DTVM_FFI_BUILD_TESTS=OFF",
6767
"-DTVM_FFI_BUILD_PYTHON_MODULE=ON"
6868
]

ffi/python/tvm_ffi/cython/base.pxi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ cdef extern from "tvm/ffi/c_api.h":
187187
int TVMFFITypeKeyToIndex(TVMFFIByteArray* type_key, int32_t* out_tindex) nogil
188188
int TVMFFIDataTypeFromString(TVMFFIByteArray* str, DLDataType* out) nogil
189189
int TVMFFIDataTypeToString(const DLDataType* dtype, TVMFFIAny* out) nogil
190-
const TVMFFIByteArray* TVMFFITraceback(const char* filename, int lineno, const char* func) nogil;
190+
const TVMFFIByteArray* TVMFFITraceback(
191+
const char* filename, int lineno, const char* func, int cross_ffi_boundary) nogil;
191192
int TVMFFINDArrayFromDLPack(DLManagedTensor* src, int32_t require_alignment,
192193
int32_t require_contiguous, TVMFFIObjectHandle* out) nogil
193194
int TVMFFINDArrayFromDLPackVersioned(DLManagedTensorVersioned* src,

ffi/python/tvm_ffi/cython/error.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ cdef inline int set_last_ffi_error(error) except -1:
9898
kind = ERROR_TYPE_TO_NAME.get(type(error), "RuntimeError")
9999
message = error.__str__()
100100
py_traceback = _TRACEBACK_TO_STR(error.__traceback__)
101-
c_traceback = bytearray_to_str(TVMFFITraceback("<unknown>", 0, "<unknown>"))
101+
c_traceback = bytearray_to_str(TVMFFITraceback(NULL, 0, NULL, 0))
102102

103103
# error comes from an exception thrown from C++ side
104104
if hasattr(error, "__tvm_ffi_error__"):

ffi/scripts/run_tests.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
# under the License.
1818
set -euxo pipefail
1919

20-
BUILD_TYPE=RelWithDebugInfo
20+
BUILD_TYPE=Release
2121

2222
rm -rf build/CMakeFiles build/CMakeCache.txt
2323
cmake -G Ninja -S . -B build -DTVM_FFI_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
24-
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
24+
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS="-O3"
2525
cmake --build build --parallel 16 --clean-first --config ${BUILD_TYPE} --target tvm_ffi_tests
2626
GTEST_COLOR=1 ctest -V -C ${BUILD_TYPE} --test-dir build --output-on-failure

ffi/src/ffi/error.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class SafeCallContext {
5656

5757
void TVMFFIErrorSetRaisedFromCStr(const char* kind, const char* message) {
5858
// NOTE: run traceback here to simplify the depth of tracekback
59-
tvm::ffi::SafeCallContext::ThreadLocal()->SetRaisedByCstr(kind, message, TVM_FFI_TRACEBACK_HERE);
59+
tvm::ffi::SafeCallContext::ThreadLocal()->SetRaisedByCstr(
60+
kind, message, TVMFFITraceback(nullptr, 0, nullptr, 0));
6061
}
6162

6263
void TVMFFIErrorSetRaised(TVMFFIObjectHandle error) {

ffi/src/ffi/extra/testing.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,16 @@ class TestObjectDerived : public TestObjectBase {
5555
TVM_FFI_DECLARE_FINAL_OBJECT_INFO(TestObjectDerived, TestObjectBase);
5656
};
5757

58-
void TestRaiseError(String kind, String msg) {
59-
throw ffi::Error(kind, msg, TVM_FFI_TRACEBACK_HERE);
58+
TVM_FFI_NO_INLINE void TestRaiseError(String kind, String msg) {
59+
// keep name and no liner for testing traceback
60+
throw ffi::Error(kind, msg, TVMFFITraceback(__FILE__, __LINE__, TVM_FFI_FUNC_SIG, 0));
6061
}
6162

62-
void TestApply(Function f, PackedArgs args, Any* ret) { f.CallPacked(args, ret); }
63+
TVM_FFI_NO_INLINE void TestApply(PackedArgs args, Any* ret) {
64+
// keep name and no liner for testing traceback
65+
auto f = args[0].cast<Function>();
66+
f.CallPacked(args.Slice(1), ret);
67+
}
6368

6469
TVM_FFI_STATIC_INIT_BLOCK({
6570
namespace refl = tvm::ffi::reflection;
@@ -78,11 +83,7 @@ TVM_FFI_STATIC_INIT_BLOCK({
7883
.def("testing.test_raise_error", TestRaiseError)
7984
.def_packed("testing.nop", [](PackedArgs args, Any* ret) { *ret = args[0]; })
8085
.def_packed("testing.echo", [](PackedArgs args, Any* ret) { *ret = args[0]; })
81-
.def_packed("testing.apply",
82-
[](PackedArgs args, Any* ret) {
83-
auto f = args[0].cast<Function>();
84-
TestApply(f, args.Slice(1), ret);
85-
})
86+
.def_packed("testing.apply", TestApply)
8687
.def("testing.run_check_signal",
8788
[](int nsec) {
8889
for (int i = 0; i < nsec; ++i) {

0 commit comments

Comments
 (0)