diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 81706d0dac2..b1357d30536 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -1633,6 +1633,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) lp_add_function_attr(variant_func, i + 1, LP_FUNC_ATTR_NOALIAS); + lp_function_add_debug_info(gallivm, variant_func, func_type); + if (gallivm->cache && gallivm->cache->data_size) { gallivm_stub_func(gallivm, variant_func); return; @@ -2365,6 +2367,8 @@ draw_gs_llvm_generate(struct draw_llvm *llvm, if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) lp_add_function_attr(variant_func, i + 1, LP_FUNC_ATTR_NOALIAS); + lp_function_add_debug_info(gallivm, variant_func, func_type); + if (gallivm->cache && gallivm->cache->data_size) { gallivm_stub_func(gallivm, variant_func); return; @@ -2958,6 +2962,9 @@ draw_tcs_llvm_generate(struct draw_llvm *llvm, } } + lp_function_add_debug_info(gallivm, variant_func, func_type); + lp_function_add_debug_info(gallivm, variant_coro, coro_func_type); + if (gallivm->cache && gallivm->cache->data_size) { gallivm_stub_func(gallivm, variant_func); gallivm_stub_func(gallivm, variant_coro); @@ -3521,6 +3528,8 @@ draw_tes_llvm_generate(struct draw_llvm *llvm, if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) lp_add_function_attr(variant_func, i + 1, LP_FUNC_ATTR_NOALIAS); + lp_function_add_debug_info(gallivm, variant_func, func_type); + if (gallivm->cache && gallivm->cache->data_size) { gallivm_stub_func(gallivm, variant_func); return; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp index 0fffb19e8ed..a0e61f65e13 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp +++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp @@ -47,13 +47,16 @@ #include "util/u_debug.h" #include "lp_bld_debug.h" +#include "lp_bld_intr.h" #ifdef __linux__ #include #include #endif +#include +#include /** * Check alignment. @@ -279,3 +282,121 @@ lp_profile(LLVMValueRef func, const void *code) (void)code; #endif } + + +LLVMMetadataRef +lp_bld_debug_info_type(gallivm_state *gallivm, LLVMTypeRef type) +{ + LLVMTypeKind kind = LLVMGetTypeKind(type); + + if (kind == LLVMHalfTypeKind) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "float16_t", strlen("float16_t"), 16, llvm::dwarf::DW_ATE_float, LLVMDIFlagZero); + if (kind == LLVMFloatTypeKind) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "float", strlen("float"), 32, llvm::dwarf::DW_ATE_float, LLVMDIFlagZero); + if (kind == LLVMDoubleTypeKind) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "double", strlen("double"), 64, llvm::dwarf::DW_ATE_float, LLVMDIFlagZero); + + if (kind == LLVMIntegerTypeKind) { + uint32_t bit_size = LLVMGetIntTypeWidth(type); + if (bit_size == 1) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "bool", strlen("bool"), 1, llvm::dwarf::DW_ATE_unsigned, LLVMDIFlagZero); + if (bit_size == 8) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "int8_t", strlen("int8_t"), 8, llvm::dwarf::DW_ATE_unsigned, LLVMDIFlagZero); + if (bit_size == 16) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "int16_t", strlen("int16_t"), 16, llvm::dwarf::DW_ATE_unsigned, LLVMDIFlagZero); + if (bit_size == 32) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "int32_t", strlen("int32_t"), 32, llvm::dwarf::DW_ATE_unsigned, LLVMDIFlagZero); + if (bit_size == 64) + return LLVMDIBuilderCreateBasicType( + gallivm->di_builder, "int64_t", strlen("int64_t"), 64, llvm::dwarf::DW_ATE_unsigned, LLVMDIFlagZero); + } + + if (kind == LLVMFunctionTypeKind) { + uint32_t num_params = LLVMCountParamTypes(type); + + LLVMTypeRef *param_types = (LLVMTypeRef *)calloc(num_params, sizeof(LLVMTypeRef)); + LLVMMetadataRef *di_param_types = (LLVMMetadataRef *)calloc(num_params + 1, sizeof(LLVMMetadataRef)); + + LLVMGetParamTypes(type, param_types); + + di_param_types[0] = lp_bld_debug_info_type(gallivm, LLVMGetReturnType(type)); + for (uint32_t i = 0; i < num_params; i++) + di_param_types[i + 1] = lp_bld_debug_info_type(gallivm, param_types[i]); + + LLVMMetadataRef function = LLVMDIBuilderCreateSubroutineType( + gallivm->di_builder, gallivm->file, di_param_types, num_params + 1, LLVMDIFlagZero); + + free(param_types); + free(di_param_types); + + return function; + } + + if (kind == LLVMArrayTypeKind) { + uint32_t count = LLVMGetArrayLength(type); + LLVMMetadataRef subrange = LLVMDIBuilderGetOrCreateSubrange(gallivm->di_builder, 0, count); + LLVMMetadataRef element_type = lp_bld_debug_info_type(gallivm, LLVMGetElementType(type)); + return LLVMDIBuilderCreateArrayType( + gallivm->di_builder, count, 0, element_type, &subrange, 1); + } + + if (kind == LLVMPointerTypeKind) { + return LLVMDIBuilderCreatePointerType( + gallivm->di_builder, NULL, sizeof(void *) * 8, 0, 0, "", 0); + } + + if (kind == LLVMVectorTypeKind) { + uint32_t count = LLVMGetVectorSize(type); + LLVMMetadataRef subrange = LLVMDIBuilderGetOrCreateSubrange(gallivm->di_builder, 0, count); + LLVMMetadataRef element_type = lp_bld_debug_info_type(gallivm, LLVMGetElementType(type)); + return LLVMDIBuilderCreateVectorType( + gallivm->di_builder, count, 0, element_type, &subrange, 1); + } + + return NULL; +} + + +static uint32_t global_shader_index = 0; + + +void +lp_function_add_debug_info(gallivm_state *gallivm, LLVMValueRef func, LLVMTypeRef func_type) +{ + if (!gallivm->di_builder) + return; + + if (!gallivm->file) { + uint32_t shader_index = p_atomic_add_return(&global_shader_index, 1); + + std::filesystem::create_directory(LP_NIR_SHADER_DUMP_DIR); + + asprintf(&gallivm->file_name, "%s/%u.nir", LP_NIR_SHADER_DUMP_DIR, shader_index); + + gallivm->file = LLVMDIBuilderCreateFile(gallivm->di_builder, gallivm->file_name, strlen(gallivm->file_name), ".", 1); + + LLVMDIBuilderCreateCompileUnit( + gallivm->di_builder, LLVMDWARFSourceLanguageC11, gallivm->file, gallivm->file_name, strlen(gallivm->file_name), + 0, NULL, 0, 0, NULL, 0, LLVMDWARFEmissionFull, 0, 0, 0, "/", 1, "", 0); + } + + LLVMMetadataRef di_function_type = lp_bld_debug_info_type(gallivm, func_type); + const char *func_name = LLVMGetValueName(func); + LLVMMetadataRef di_function = LLVMDIBuilderCreateFunction( + gallivm->di_builder, NULL, func_name, strlen(func_name), func_name, strlen(func_name), + gallivm->file, 1, di_function_type, true, true, 1, LLVMDIFlagZero, false); + + LLVMSetSubprogram(func, di_function); + + lp_add_function_attr(func, -1, LP_FUNC_ATTR_NOINLINE); + lp_add_function_attr(func, -1, LP_FUNC_ATTR_OPTNONE); + + gallivm->di_function = di_function; +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.h b/src/gallium/auxiliary/gallivm/lp_bld_debug.h index 13ca40de56c..ab1ea55b690 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_debug.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.h @@ -30,7 +30,7 @@ #define LP_BLD_DEBUG_H -#include "gallivm/lp_bld.h" +#include "gallivm/lp_bld_init.h" #include "util/compiler.h" #include "util/u_string.h" @@ -95,6 +95,17 @@ void lp_profile(LLVMValueRef func, const void *code); +LLVMMetadataRef +lp_bld_debug_info_type(struct gallivm_state *gallivm, LLVMTypeRef type); + + +void +lp_function_add_debug_info(struct gallivm_state *gallivm, LLVMValueRef func, LLVMTypeRef func_type); + + +#define LP_NIR_SHADER_DUMP_DIR "/tmp/nir_shaders" + + #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c index 4ce233c83e1..3aea51d141b 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c @@ -106,6 +106,7 @@ gallivm_free_ir(struct gallivm_state *gallivm) free(gallivm->cache->data); } FREE(gallivm->module_name); + FREE(gallivm->file_name); if (gallivm->target) { LLVMDisposeTargetData(gallivm->target); @@ -123,6 +124,7 @@ gallivm_free_ir(struct gallivm_state *gallivm) gallivm->target = NULL; gallivm->module = NULL; gallivm->module_name = NULL; + gallivm->file_name = NULL; gallivm->passmgr = NULL; gallivm->context = NULL; gallivm->builder = NULL; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.h b/src/gallium/auxiliary/gallivm/lp_bld_init.h index 15bcc6cefb0..bcc8e1095fd 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.h @@ -50,6 +50,7 @@ struct lp_cached_code; struct gallivm_state { char *module_name; + char *file_name; LLVMModuleRef module; LLVMTargetDataRef target; #if GALLIVM_USE_ORCJIT @@ -75,6 +76,9 @@ struct gallivm_state LLVMTypeRef coro_malloc_hook_type; LLVMTypeRef coro_free_hook_type; + LLVMMetadataRef di_function; + LLVMMetadataRef file; + LLVMValueRef get_time_hook; LLVMValueRef texture_descriptor; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.c b/src/gallium/auxiliary/gallivm/lp_bld_intr.c index 542a4ba0d20..284f83d7411 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.c @@ -140,6 +140,8 @@ static const char *attr_to_str(enum lp_func_attr attr) case LP_FUNC_ATTR_NOUNWIND: return "nounwind"; case LP_FUNC_ATTR_CONVERGENT: return "convergent"; case LP_FUNC_ATTR_PRESPLITCORO: return "presplitcoroutine"; + case LP_FUNC_ATTR_NOINLINE: return "noinline"; + case LP_FUNC_ATTR_OPTNONE: return "optnone"; default: _debug_printf("Unhandled function attribute: %x\n", attr); return 0; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.h b/src/gallium/auxiliary/gallivm/lp_bld_intr.h index 47a81cba20b..a9540292211 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.h @@ -41,6 +41,10 @@ #include "gallivm/lp_bld.h" #include "gallivm/lp_bld_init.h" +#ifdef __cplusplus +extern "C" { +#endif + struct lp_type; /** @@ -55,6 +59,8 @@ enum lp_func_attr { LP_FUNC_ATTR_NOUNWIND = (1 << 4), LP_FUNC_ATTR_CONVERGENT = (1 << 5), LP_FUNC_ATTR_PRESPLITCORO = (1 << 6), + LP_FUNC_ATTR_NOINLINE = (1 << 7), + LP_FUNC_ATTR_OPTNONE = (1 << 8), }; void @@ -135,4 +141,8 @@ lp_build_intrinsic_map_binary(struct gallivm_state *gallivm, LLVMValueRef b); +#ifdef __cplusplus +} +#endif + #endif /* !LP_BLD_INTR_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_state_cs.c b/src/gallium/drivers/llvmpipe/lp_state_cs.c index 6f1256d0b22..01bf9e626fe 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_cs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_cs.c @@ -573,6 +573,8 @@ generate_compute(struct llvmpipe_context *lp, LLVMValueRef vec_length = lp_build_const_int32(gallivm, cs_type.length); if (use_coro) { + lp_function_add_debug_info(gallivm, function, func_type); + block = LLVMAppendBasicBlockInContext(gallivm->context, function, "entry"); builder = gallivm->builder; assert(builder); @@ -704,6 +706,8 @@ generate_compute(struct llvmpipe_context *lp, output_array = LLVMGetParam(coro, CS_ARG_CORO_OUTPUTS); } + lp_function_add_debug_info(gallivm, coro, coro_func_type); + block = LLVMAppendBasicBlockInContext(gallivm->context, coro, "entry"); builder = gallivm->builder; LLVMPositionBuilderAtEnd(builder, block); diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 27cbac712ff..ee5ecefd8f5 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -3271,6 +3271,8 @@ generate_fragment(struct llvmpipe_context *lp, if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) lp_add_function_attr(function, i + 1, LP_FUNC_ATTR_NOALIAS); + lp_function_add_debug_info(gallivm, function, func_type); + if (variant->gallivm->cache->data_size) { gallivm_stub_func(gallivm, function); return; diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs_linear_llvm.c b/src/gallium/drivers/llvmpipe/lp_state_fs_linear_llvm.c index 1776fdb8bf3..85353de01ba 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs_linear_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs_linear_llvm.c @@ -288,6 +288,8 @@ llvmpipe_fs_variant_linear_llvm(struct llvmpipe_context *lp, LLVMAddFunction(gallivm->module, func_name, func_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); + lp_function_add_debug_info(gallivm, function, func_type); + variant->linear_function = function; variant->linear_function_name = MALLOC(strlen(func_name)+1); strcpy(variant->linear_function_name, func_name); diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c index 91e4d41c878..01c3fe2a017 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c @@ -695,6 +695,8 @@ generate_setup_variant(struct lp_setup_variant_key *key, LLVMSetFunctionCallConv(variant->function, LLVMCCallConv); + lp_function_add_debug_info(gallivm, variant->function, func_type); + struct lp_setup_args args; args.vec4f_type = vec4f_type; args.v0 = LLVMGetParam(variant->function, 0); diff --git a/src/gallium/drivers/llvmpipe/lp_texture_handle.c b/src/gallium/drivers/llvmpipe/lp_texture_handle.c index c6accb190b4..98636ba4743 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture_handle.c +++ b/src/gallium/drivers/llvmpipe/lp_texture_handle.c @@ -342,6 +342,8 @@ compile_image_function(struct llvmpipe_context *ctx, struct lp_static_texture_st LLVMValueRef function = LLVMAddFunction(gallivm->module, "image", function_type); + lp_function_add_debug_info(gallivm, function, function_type); + uint32_t arg_index = 0; gallivm->texture_descriptor = LLVMGetParam(function, arg_index++); @@ -487,6 +489,8 @@ compile_sample_function(struct llvmpipe_context *ctx, struct lp_static_texture_s LLVMTypeRef function_type = lp_build_sample_function_type(gallivm, sample_key); LLVMValueRef function = LLVMAddFunction(gallivm->module, "sample", function_type); + lp_function_add_debug_info(gallivm, function, function_type); + uint32_t arg_index = 0; gallivm->texture_descriptor = LLVMGetParam(function, arg_index++); @@ -629,6 +633,8 @@ compile_jit_sample_function(struct llvmpipe_context *ctx, uint32_t sample_key) LLVMTypeRef function_type = lp_build_sample_function_type(gallivm, sample_key); LLVMValueRef function = LLVMAddFunction(gallivm->module, "sample", function_type); + lp_function_add_debug_info(gallivm, function, function_type); + uint32_t arg_index = 0; LLVMValueRef texture_descriptor = LLVMGetParam(function, arg_index++); LLVMValueRef sampler_descriptor = LLVMGetParam(function, arg_index++); @@ -757,6 +763,8 @@ compile_size_function(struct llvmpipe_context *ctx, struct lp_static_texture_sta LLVMTypeRef function_type = lp_build_size_function_type(gallivm, ¶ms); LLVMValueRef function = LLVMAddFunction(gallivm->module, "size", function_type); + lp_function_add_debug_info(gallivm, function, function_type); + uint32_t arg_index = 0; gallivm->texture_descriptor = LLVMGetParam(function, arg_index++);