llvmpipe: Annotate functions with debug information

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28613>
This commit is contained in:
Konstantin Seurer 2024-04-06 10:22:25 +02:00 committed by Marge Bot
parent 95a68076a7
commit d6ca378f1b
12 changed files with 178 additions and 1 deletions

View file

@ -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;

View file

@ -47,13 +47,16 @@
#include "util/u_debug.h"
#include "lp_bld_debug.h"
#include "lp_bld_intr.h"
#ifdef __linux__
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include <llvm/BinaryFormat/Dwarf.h>
#include <filesystem>
/**
* 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;
}

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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, &params);
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++);