Commit aae33735 by Antonio Maiorano

Subzero: add REACTOR_EMIT_PRINT_LOCATION support

Adds support for emitting print locations when using the Subzero backend. Very useful for debugging. Bug: b/149572931 Change-Id: I32fc14486cd7a021f424fb926dc776072374b931 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/41288Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com>
parent d42d2fd9
...@@ -543,12 +543,6 @@ else() ...@@ -543,12 +543,6 @@ else()
endif() endif()
endif() endif()
if((${REACTOR_BACKEND} STREQUAL "Subzero") AND (REACTOR_EMIT_PRINT_LOCATION OR REACTOR_EMIT_DEBUG_INFO))
message(WARNING "REACTOR_ENABLE_PRINT, REACTOR_EMIT_PRINT_LOCATION, and REACTOR_EMIT_DEBUG_INFO are not supported by Subzero, disabling.")
set(REACTOR_EMIT_PRINT_LOCATION "Off")
set(REACTOR_EMIT_DEBUG_INFO "Off")
endif()
if(REACTOR_EMIT_PRINT_LOCATION) if(REACTOR_EMIT_PRINT_LOCATION)
# This feature depends on REACTOR_EMIT_DEBUG_INFO and REACTOR_ENABLE_PRINT # This feature depends on REACTOR_EMIT_DEBUG_INFO and REACTOR_ENABLE_PRINT
set(REACTOR_EMIT_DEBUG_INFO "On") set(REACTOR_EMIT_DEBUG_INFO "On")
...@@ -1640,6 +1634,8 @@ if(${REACTOR_BACKEND} STREQUAL "Subzero") ...@@ -1640,6 +1634,8 @@ if(${REACTOR_BACKEND} STREQUAL "Subzero")
${SOURCE_DIR}/Reactor/Print.hpp ${SOURCE_DIR}/Reactor/Print.hpp
${SOURCE_DIR}/Reactor/Reactor.cpp ${SOURCE_DIR}/Reactor/Reactor.cpp
${SOURCE_DIR}/Reactor/Reactor.hpp ${SOURCE_DIR}/Reactor/Reactor.hpp
${SOURCE_DIR}/Reactor/ReactorDebugInfo.cpp
${SOURCE_DIR}/Reactor/ReactorDebugInfo.hpp
${SOURCE_DIR}/Reactor/Routine.hpp ${SOURCE_DIR}/Reactor/Routine.hpp
${SOURCE_DIR}/Reactor/SubzeroReactor.cpp ${SOURCE_DIR}/Reactor/SubzeroReactor.cpp
) )
...@@ -1780,6 +1776,8 @@ set(REACTOR_LLVM_LIST ...@@ -1780,6 +1776,8 @@ set(REACTOR_LLVM_LIST
${SOURCE_DIR}/Reactor/Print.hpp ${SOURCE_DIR}/Reactor/Print.hpp
${SOURCE_DIR}/Reactor/Reactor.cpp ${SOURCE_DIR}/Reactor/Reactor.cpp
${SOURCE_DIR}/Reactor/Reactor.hpp ${SOURCE_DIR}/Reactor/Reactor.hpp
${SOURCE_DIR}/Reactor/ReactorDebugInfo.cpp
${SOURCE_DIR}/Reactor/ReactorDebugInfo.hpp
${SOURCE_DIR}/Reactor/Routine.hpp ${SOURCE_DIR}/Reactor/Routine.hpp
) )
...@@ -2002,37 +2000,6 @@ if(${REACTOR_BACKEND} STREQUAL "LLVM") ...@@ -2002,37 +2000,6 @@ if(${REACTOR_BACKEND} STREQUAL "LLVM")
COMPILE_OPTIONS "${SWIFTSHADER_COMPILE_OPTIONS}" COMPILE_OPTIONS "${SWIFTSHADER_COMPILE_OPTIONS}"
) )
target_link_libraries(ReactorLLVM llvm ${OS_LIBS}) target_link_libraries(ReactorLLVM llvm ${OS_LIBS})
if(REACTOR_EMIT_DEBUG_INFO)
if(WIN32)
# Boost stacktrace uses COM on Windows.
# On Windows, cache COM instances in TLS for performance.
target_compile_definitions(ReactorLLVM PRIVATE BOOST_STACKTRACE_USE_WINDBG_CACHED)
else()
# Boost stacktrace uses libbacktrace
target_compile_definitions(ReactorLLVM PRIVATE 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()
# Download boost and use it
DownloadBoost()
set(BOOST_INCLUDEDIR ${BOOST_THIRD_PARTY_DIR})
find_package(Boost REQUIRED)
target_link_libraries(ReactorLLVM Boost::boost)
endif(REACTOR_EMIT_DEBUG_INFO)
set(Reactor ReactorLLVM) set(Reactor ReactorLLVM)
elseif(${REACTOR_BACKEND} STREQUAL "Subzero") elseif(${REACTOR_BACKEND} STREQUAL "Subzero")
set(Reactor ReactorSubzero) set(Reactor ReactorSubzero)
...@@ -2040,6 +2007,36 @@ else() ...@@ -2040,6 +2007,36 @@ else()
message(FATAL_ERROR "REACTOR_BACKEND must be 'LLVM' or 'Subzero'") message(FATAL_ERROR "REACTOR_BACKEND must be 'LLVM' or 'Subzero'")
endif() endif()
if(REACTOR_EMIT_DEBUG_INFO)
if(WIN32)
# Boost stacktrace uses COM on Windows.
# On Windows, cache COM instances in TLS for performance.
target_compile_definitions(${Reactor} PRIVATE BOOST_STACKTRACE_USE_WINDBG_CACHED)
else()
# Boost stacktrace uses libbacktrace
target_compile_definitions(${Reactor} PRIVATE 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(${Reactor} Libbacktrace)
endif()
# Download boost and use it
DownloadBoost()
set(BOOST_INCLUDEDIR ${BOOST_THIRD_PARTY_DIR})
find_package(Boost REQUIRED)
target_link_libraries(${Reactor} Boost::boost)
endif(REACTOR_EMIT_DEBUG_INFO)
add_library(GLCompiler STATIC ${OPENGL_COMPILER_LIST}) add_library(GLCompiler STATIC ${OPENGL_COMPILER_LIST})
set_target_properties(GLCompiler PROPERTIES set_target_properties(GLCompiler PROPERTIES
INCLUDE_DIRECTORIES "${OPENGL_INCLUDE_DIR}" INCLUDE_DIRECTORIES "${OPENGL_INCLUDE_DIR}"
......
...@@ -1109,6 +1109,8 @@ Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatil ...@@ -1109,6 +1109,8 @@ Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatil
Value *Nucleus::createMaskedLoad(Value *ptr, Type *elTy, Value *mask, unsigned int alignment, bool zeroMaskedLanes) Value *Nucleus::createMaskedLoad(Value *ptr, Type *elTy, Value *mask, unsigned int alignment, bool zeroMaskedLanes)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
ASSERT(V(ptr)->getType()->isPointerTy()); ASSERT(V(ptr)->getType()->isPointerTy());
ASSERT(V(mask)->getType()->isVectorTy()); ASSERT(V(mask)->getType()->isVectorTy());
...@@ -1126,6 +1128,8 @@ Value *Nucleus::createMaskedLoad(Value *ptr, Type *elTy, Value *mask, unsigned i ...@@ -1126,6 +1128,8 @@ Value *Nucleus::createMaskedLoad(Value *ptr, Type *elTy, Value *mask, unsigned i
void Nucleus::createMaskedStore(Value *ptr, Value *val, Value *mask, unsigned int alignment) void Nucleus::createMaskedStore(Value *ptr, Value *val, Value *mask, unsigned int alignment)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
ASSERT(V(ptr)->getType()->isPointerTy()); ASSERT(V(ptr)->getType()->isPointerTy());
ASSERT(V(val)->getType()->isVectorTy()); ASSERT(V(val)->getType()->isVectorTy());
ASSERT(V(mask)->getType()->isVectorTy()); ASSERT(V(mask)->getType()->isVectorTy());
...@@ -1163,6 +1167,7 @@ void Scatter(RValue<Pointer<Int>> base, RValue<Int4> val, RValue<Int4> offsets, ...@@ -1163,6 +1167,7 @@ void Scatter(RValue<Pointer<Int>> base, RValue<Int4> val, RValue<Int4> offsets,
void Nucleus::createFence(std::memory_order memoryOrder) void Nucleus::createFence(std::memory_order memoryOrder)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
jit->builder->CreateFence(atomicOrdering(true, memoryOrder)); jit->builder->CreateFence(atomicOrdering(true, memoryOrder));
} }
...@@ -1658,6 +1663,7 @@ Value *Nucleus::createNullPointer(Type *Ty) ...@@ -1658,6 +1663,7 @@ Value *Nucleus::createNullPointer(Type *Ty)
Value *Nucleus::createConstantVector(const int64_t *constants, Type *type) Value *Nucleus::createConstantVector(const int64_t *constants, Type *type)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
ASSERT(llvm::isa<llvm::VectorType>(T(type))); ASSERT(llvm::isa<llvm::VectorType>(T(type)));
const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type. const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type.
const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); // Number of elements of the underlying vector type. const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); // Number of elements of the underlying vector type.
...@@ -1674,6 +1680,7 @@ Value *Nucleus::createConstantVector(const int64_t *constants, Type *type) ...@@ -1674,6 +1680,7 @@ Value *Nucleus::createConstantVector(const int64_t *constants, Type *type)
Value *Nucleus::createConstantVector(const double *constants, Type *type) Value *Nucleus::createConstantVector(const double *constants, Type *type)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
ASSERT(llvm::isa<llvm::VectorType>(T(type))); ASSERT(llvm::isa<llvm::VectorType>(T(type)));
const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type. const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type.
const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); // Number of elements of the underlying vector type. const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); // Number of elements of the underlying vector type.
...@@ -1690,6 +1697,7 @@ Value *Nucleus::createConstantVector(const double *constants, Type *type) ...@@ -1690,6 +1697,7 @@ Value *Nucleus::createConstantVector(const double *constants, Type *type)
Value *Nucleus::createConstantString(const char *v) Value *Nucleus::createConstantString(const char *v)
{ {
// NOTE: Do not call RR_DEBUG_INFO_UPDATE_LOC() here to avoid recursion when called from rr::Printv
auto ptr = jit->builder->CreateGlobalStringPtr(v); auto ptr = jit->builder->CreateGlobalStringPtr(v);
return V(ptr); return V(ptr);
} }
...@@ -3152,18 +3160,21 @@ RValue<Float4> Ceil(RValue<Float4> x) ...@@ -3152,18 +3160,21 @@ RValue<Float4> Ceil(RValue<Float4> x)
RValue<Float4> Sin(RValue<Float4> v) RValue<Float4> Sin(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::sin, { V(v.value)->getType() }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::sin, { V(v.value)->getType() });
return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value)))); return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value))));
} }
RValue<Float4> Cos(RValue<Float4> v) RValue<Float4> Cos(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cos, { V(v.value)->getType() }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cos, { V(v.value)->getType() });
return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value)))); return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value))));
} }
RValue<Float4> Tan(RValue<Float4> v) RValue<Float4> Tan(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return Sin(v) / Cos(v); return Sin(v) / Cos(v);
} }
...@@ -3182,51 +3193,61 @@ static RValue<Float4> TransformFloat4PerElement(RValue<Float4> v, const char *na ...@@ -3182,51 +3193,61 @@ static RValue<Float4> TransformFloat4PerElement(RValue<Float4> v, const char *na
RValue<Float4> Asin(RValue<Float4> v) RValue<Float4> Asin(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return TransformFloat4PerElement(v, "asinf"); return TransformFloat4PerElement(v, "asinf");
} }
RValue<Float4> Acos(RValue<Float4> v) RValue<Float4> Acos(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return TransformFloat4PerElement(v, "acosf"); return TransformFloat4PerElement(v, "acosf");
} }
RValue<Float4> Atan(RValue<Float4> v) RValue<Float4> Atan(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return TransformFloat4PerElement(v, "atanf"); return TransformFloat4PerElement(v, "atanf");
} }
RValue<Float4> Sinh(RValue<Float4> v) RValue<Float4> Sinh(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return emulated::Sinh(v); return emulated::Sinh(v);
} }
RValue<Float4> Cosh(RValue<Float4> v) RValue<Float4> Cosh(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return emulated::Cosh(v); return emulated::Cosh(v);
} }
RValue<Float4> Tanh(RValue<Float4> v) RValue<Float4> Tanh(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return TransformFloat4PerElement(v, "tanhf"); return TransformFloat4PerElement(v, "tanhf");
} }
RValue<Float4> Asinh(RValue<Float4> v) RValue<Float4> Asinh(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return TransformFloat4PerElement(v, "asinhf"); return TransformFloat4PerElement(v, "asinhf");
} }
RValue<Float4> Acosh(RValue<Float4> v) RValue<Float4> Acosh(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return TransformFloat4PerElement(v, "acoshf"); return TransformFloat4PerElement(v, "acoshf");
} }
RValue<Float4> Atanh(RValue<Float4> v) RValue<Float4> Atanh(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
return TransformFloat4PerElement(v, "atanhf"); return TransformFloat4PerElement(v, "atanhf");
} }
RValue<Float4> Atan2(RValue<Float4> x, RValue<Float4> y) RValue<Float4> Atan2(RValue<Float4> x, RValue<Float4> y)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
::llvm::SmallVector<::llvm::Type *, 2> paramTys; ::llvm::SmallVector<::llvm::Type *, 2> paramTys;
paramTys.push_back(T(Float::getType())); paramTys.push_back(T(Float::getType()));
paramTys.push_back(T(Float::getType())); paramTys.push_back(T(Float::getType()));
...@@ -3245,36 +3266,42 @@ RValue<Float4> Atan2(RValue<Float4> x, RValue<Float4> y) ...@@ -3245,36 +3266,42 @@ RValue<Float4> Atan2(RValue<Float4> x, RValue<Float4> y)
RValue<Float4> Pow(RValue<Float4> x, RValue<Float4> y) RValue<Float4> Pow(RValue<Float4> x, RValue<Float4> y)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::pow, { T(Float4::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::pow, { T(Float4::getType()) });
return RValue<Float4>(V(jit->builder->CreateCall2(func, ARGS(V(x.value), V(y.value))))); return RValue<Float4>(V(jit->builder->CreateCall2(func, ARGS(V(x.value), V(y.value)))));
} }
RValue<Float4> Exp(RValue<Float4> v) RValue<Float4> Exp(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::exp, { T(Float4::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::exp, { T(Float4::getType()) });
return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value)))); return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value))));
} }
RValue<Float4> Log(RValue<Float4> v) RValue<Float4> Log(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::log, { T(Float4::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::log, { T(Float4::getType()) });
return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value)))); return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value))));
} }
RValue<Float4> Exp2(RValue<Float4> v) RValue<Float4> Exp2(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::exp2, { T(Float4::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::exp2, { T(Float4::getType()) });
return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value)))); return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value))));
} }
RValue<Float4> Log2(RValue<Float4> v) RValue<Float4> Log2(RValue<Float4> v)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::log2, { T(Float4::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::log2, { T(Float4::getType()) });
return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value)))); return RValue<Float4>(V(jit->builder->CreateCall(func, V(v.value))));
} }
RValue<UInt> Ctlz(RValue<UInt> v, bool isZeroUndef) RValue<UInt> Ctlz(RValue<UInt> v, bool isZeroUndef)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::ctlz, { T(UInt::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::ctlz, { T(UInt::getType()) });
return RValue<UInt>(V(jit->builder->CreateCall2(func, ARGS( return RValue<UInt>(V(jit->builder->CreateCall2(func, ARGS(
V(v.value), V(v.value),
...@@ -3283,6 +3310,7 @@ RValue<UInt> Ctlz(RValue<UInt> v, bool isZeroUndef) ...@@ -3283,6 +3310,7 @@ RValue<UInt> Ctlz(RValue<UInt> v, bool isZeroUndef)
RValue<UInt4> Ctlz(RValue<UInt4> v, bool isZeroUndef) RValue<UInt4> Ctlz(RValue<UInt4> v, bool isZeroUndef)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::ctlz, { T(UInt4::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::ctlz, { T(UInt4::getType()) });
return RValue<UInt4>(V(jit->builder->CreateCall2(func, ARGS( return RValue<UInt4>(V(jit->builder->CreateCall2(func, ARGS(
V(v.value), V(v.value),
...@@ -3291,6 +3319,7 @@ RValue<UInt4> Ctlz(RValue<UInt4> v, bool isZeroUndef) ...@@ -3291,6 +3319,7 @@ RValue<UInt4> Ctlz(RValue<UInt4> v, bool isZeroUndef)
RValue<UInt> Cttz(RValue<UInt> v, bool isZeroUndef) RValue<UInt> Cttz(RValue<UInt> v, bool isZeroUndef)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cttz, { T(UInt::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cttz, { T(UInt::getType()) });
return RValue<UInt>(V(jit->builder->CreateCall2(func, ARGS( return RValue<UInt>(V(jit->builder->CreateCall2(func, ARGS(
V(v.value), V(v.value),
...@@ -3299,6 +3328,7 @@ RValue<UInt> Cttz(RValue<UInt> v, bool isZeroUndef) ...@@ -3299,6 +3328,7 @@ RValue<UInt> Cttz(RValue<UInt> v, bool isZeroUndef)
RValue<UInt4> Cttz(RValue<UInt4> v, bool isZeroUndef) RValue<UInt4> Cttz(RValue<UInt4> v, bool isZeroUndef)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cttz, { T(UInt4::getType()) }); auto func = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::cttz, { T(UInt4::getType()) });
return RValue<UInt4>(V(jit->builder->CreateCall2(func, ARGS( return RValue<UInt4>(V(jit->builder->CreateCall2(func, ARGS(
V(v.value), V(v.value),
...@@ -3340,6 +3370,7 @@ RValue<Long> Ticks() ...@@ -3340,6 +3370,7 @@ RValue<Long> Ticks()
RValue<Pointer<Byte>> ConstantPointer(void const *ptr) RValue<Pointer<Byte>> ConstantPointer(void const *ptr)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
// Note: this should work for 32-bit pointers as well because 'inttoptr' // Note: this should work for 32-bit pointers as well because 'inttoptr'
// is defined to truncate (and zero extend) if necessary. // is defined to truncate (and zero extend) if necessary.
auto ptrAsInt = ::llvm::ConstantInt::get(::llvm::Type::getInt64Ty(jit->context), reinterpret_cast<uintptr_t>(ptr)); auto ptrAsInt = ::llvm::ConstantInt::get(::llvm::Type::getInt64Ty(jit->context), reinterpret_cast<uintptr_t>(ptr));
...@@ -3348,6 +3379,7 @@ RValue<Pointer<Byte>> ConstantPointer(void const *ptr) ...@@ -3348,6 +3379,7 @@ RValue<Pointer<Byte>> ConstantPointer(void const *ptr)
RValue<Pointer<Byte>> ConstantData(void const *data, size_t size) RValue<Pointer<Byte>> ConstantData(void const *data, size_t size)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
auto str = ::std::string(reinterpret_cast<const char *>(data), size); auto str = ::std::string(reinterpret_cast<const char *>(data), size);
auto ptr = jit->builder->CreateGlobalStringPtr(str); auto ptr = jit->builder->CreateGlobalStringPtr(str);
return RValue<Pointer<Byte>>(V(ptr)); return RValue<Pointer<Byte>>(V(ptr));
...@@ -3355,6 +3387,7 @@ RValue<Pointer<Byte>> ConstantData(void const *data, size_t size) ...@@ -3355,6 +3387,7 @@ RValue<Pointer<Byte>> ConstantData(void const *data, size_t size)
Value *Call(RValue<Pointer<Byte>> fptr, Type *retTy, std::initializer_list<Value *> args, std::initializer_list<Type *> argTys) Value *Call(RValue<Pointer<Byte>> fptr, Type *retTy, std::initializer_list<Value *> args, std::initializer_list<Type *> argTys)
{ {
RR_DEBUG_INFO_UPDATE_LOC();
::llvm::SmallVector<::llvm::Type *, 8> paramTys; ::llvm::SmallVector<::llvm::Type *, 8> paramTys;
for(auto ty : argTys) { paramTys.push_back(T(ty)); } for(auto ty : argTys) { paramTys.push_back(T(ty)); }
auto funcTy = ::llvm::FunctionType::get(T(retTy), paramTys, false); auto funcTy = ::llvm::FunctionType::get(T(retTy), paramTys, false);
...@@ -3369,6 +3402,7 @@ Value *Call(RValue<Pointer<Byte>> fptr, Type *retTy, std::initializer_list<Value ...@@ -3369,6 +3402,7 @@ Value *Call(RValue<Pointer<Byte>> fptr, Type *retTy, std::initializer_list<Value
void Breakpoint() void Breakpoint()
{ {
RR_DEBUG_INFO_UPDATE_LOC();
llvm::Function *debugtrap = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::debugtrap); llvm::Function *debugtrap = llvm::Intrinsic::getDeclaration(jit->module.get(), llvm::Intrinsic::debugtrap);
jit->builder->CreateCall(debugtrap); jit->builder->CreateCall(debugtrap);
......
...@@ -134,17 +134,7 @@ void DebugInfo::EmitLocation() ...@@ -134,17 +134,7 @@ void DebugInfo::EmitLocation()
builder->SetCurrentDebugLocation(getLocation(backtrace, backtrace.size() - 1)); builder->SetCurrentDebugLocation(getLocation(backtrace, backtrace.size() - 1));
# ifdef ENABLE_RR_EMIT_PRINT_LOCATION # ifdef ENABLE_RR_EMIT_PRINT_LOCATION
static Location lastLocation; emitPrintLocation(backtrace);
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 # endif // ENABLE_RR_EMIT_PRINT_LOCATION
} }
...@@ -443,48 +433,14 @@ void DebugInfo::registerBasicTypes() ...@@ -443,48 +433,14 @@ void DebugInfo::registerBasicTypes()
diTypes.emplace(T(Float4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Float::getType())], { vec4 })); diTypes.emplace(T(Float4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Float::getType())], { vec4 }));
} }
DebugInfo::Location DebugInfo::getCallerLocation() const Location DebugInfo::getCallerLocation() const
{ {
return getCallerBacktrace(1)[0]; return getCallerBacktrace(1)[0];
} }
DebugInfo::Backtrace DebugInfo::getCallerBacktrace(size_t limit /* = 0 */) const Backtrace DebugInfo::getCallerBacktrace(size_t limit /* = 0 */) const
{ {
auto shouldSkipFile = [](llvm::StringRef fileSR) { return rr::getCallerBacktrace(limit);
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())
{
if(shouldSkipFile(frame.source_file()))
{
continue;
}
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) llvm::DIType *DebugInfo::getOrCreateType(llvm::Type *type)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define rr_LLVMReactorDebugInfo_hpp #define rr_LLVMReactorDebugInfo_hpp
#include "Reactor.hpp" #include "Reactor.hpp"
#include "ReactorDebugInfo.hpp"
#ifdef ENABLE_RR_DEBUG_INFO #ifdef ENABLE_RR_DEBUG_INFO
...@@ -111,44 +112,6 @@ private: ...@@ -111,44 +112,6 @@ private:
using LineTokens = std::unordered_map<unsigned int, Token>; using LineTokens = std::unordered_map<unsigned int, Token>;
struct FunctionLocation
{
std::string name;
std::string file;
bool operator==(const FunctionLocation &rhs) const { return name == rhs.name && file == rhs.file; }
bool operator!=(const FunctionLocation &rhs) const { return !(*this == rhs); }
struct Hash
{
std::size_t operator()(const FunctionLocation &l) const noexcept
{
return std::hash<std::string>()(l.file) * 31 +
std::hash<std::string>()(l.name);
}
};
};
struct Location
{
FunctionLocation function;
unsigned int line = 0;
bool operator==(const Location &rhs) const { return function == rhs.function && line == rhs.line; }
bool operator!=(const Location &rhs) const { return !(*this == rhs); }
struct Hash
{
std::size_t operator()(const Location &l) const noexcept
{
return FunctionLocation::Hash()(l.function) * 31 +
std::hash<unsigned int>()(l.line);
}
};
};
using Backtrace = std::vector<Location>;
struct Pending struct Pending
{ {
std::string name; std::string name;
......
// Copyright 2020 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 "ReactorDebugInfo.hpp"
#include "Print.hpp"
#ifdef ENABLE_RR_DEBUG_INFO
# include "boost/stacktrace.hpp"
# include <algorithm>
namespace rr {
namespace {
std::string to_lower(std::string str)
{
std::transform(str.begin(), str.end(), str.begin(),
[](unsigned char c) { return std::tolower(c); });
return str;
}
bool endswith_lower(const std::string &str, const std::string &suffix)
{
size_t strLen = str.size();
size_t suffixLen = suffix.size();
if(strLen < suffixLen)
{
return false;
}
return to_lower(str).substr(strLen - suffixLen) == to_lower(suffix);
}
} // namespace
Backtrace getCallerBacktrace(size_t limit /* = 0 */)
{
auto shouldSkipFile = [](const std::string &fileSR) {
return fileSR.empty() ||
endswith_lower(fileSR, "ReactorDebugInfo.cpp") ||
endswith_lower(fileSR, "Reactor.cpp") ||
endswith_lower(fileSR, "Reactor.hpp") ||
endswith_lower(fileSR, "Traits.hpp") ||
endswith_lower(fileSR, "stacktrace.hpp");
};
std::vector<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())
{
if(shouldSkipFile(frame.source_file()))
{
continue;
}
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;
}
void emitPrintLocation(const Backtrace &backtrace)
{
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);
}
}
} // namespace rr
#endif // ENABLE_RR_DEBUG_INFO
// Copyright 2020 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_ReactorDebugInfo_hpp
#define rr_ReactorDebugInfo_hpp
#ifdef ENABLE_RR_DEBUG_INFO
# include <vector>
# include <string>
namespace rr {
struct FunctionLocation
{
std::string name;
std::string file;
bool operator==(const FunctionLocation &rhs) const { return name == rhs.name && file == rhs.file; }
bool operator!=(const FunctionLocation &rhs) const { return !(*this == rhs); }
struct Hash
{
std::size_t operator()(const FunctionLocation &l) const noexcept
{
return std::hash<std::string>()(l.file) * 31 +
std::hash<std::string>()(l.name);
}
};
};
struct Location
{
FunctionLocation function;
unsigned int line = 0;
bool operator==(const Location &rhs) const { return function == rhs.function && line == rhs.line; }
bool operator!=(const Location &rhs) const { return !(*this == rhs); }
struct Hash
{
std::size_t operator()(const Location &l) const noexcept
{
return FunctionLocation::Hash()(l.function) * 31 +
std::hash<unsigned int>()(l.line);
}
};
};
using Backtrace = std::vector<Location>;
// Returns the backtrace for the callstack, starting at the first
// non-Reactor file. If limit is non-zero, then a maximum of limit
// frames will be returned.
Backtrace getCallerBacktrace(size_t limit = 0);
// Emits a print location for the top of the input backtrace.
void emitPrintLocation(const Backtrace &backtrace);
} // namespace rr
#endif // ENABLE_RR_DEBUG_INFO
#endif // rr_ReactorDebugInfo_hpp
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