X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fgallivm%2Flp_bld_printf.c;h=a4233a24e3317cc98f0c1cb3afe60cdc73258826;hb=dffeaa55dd1155d7a1e8feb5ecfc54fff688fcd8;hp=153ba5b15b17656b3b3be65ce43c2b73f4cf38a6;hpb=c7f5c9a3dc6350252e73b541bb85ab3ed9e64a9c;p=mesa.git diff --git a/src/gallium/auxiliary/gallivm/lp_bld_printf.c b/src/gallium/auxiliary/gallivm/lp_bld_printf.c index 153ba5b15b1..a4233a24e33 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_printf.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_printf.c @@ -26,16 +26,137 @@ **************************************************************************/ #include +#include #include "util/u_debug.h" #include "util/u_memory.h" +#include "util/u_string.h" +#include "lp_bld_const.h" +#include "lp_bld_init.h" +#include "lp_bld_const.h" #include "lp_bld_printf.h" +#include "lp_bld_type.h" -static int +/** + * Generates LLVM IR to call debug_printf. + */ +static LLVMValueRef +lp_build_print_args(struct gallivm_state* gallivm, + int argcount, + LLVMValueRef* args) +{ + LLVMBuilderRef builder = gallivm->builder; + LLVMContextRef context = gallivm->context; + LLVMValueRef func_printf; + LLVMTypeRef printf_type; + int i; + + assert(args); + assert(argcount > 0); + assert(LLVMTypeOf(args[0]) == LLVMPointerType(LLVMInt8TypeInContext(context), 0)); + + /* Cast any float arguments to doubles as printf expects */ + for (i = 1; i < argcount; i++) { + LLVMTypeRef type = LLVMTypeOf(args[i]); + + if (LLVMGetTypeKind(type) == LLVMFloatTypeKind) + args[i] = LLVMBuildFPExt(builder, args[i], LLVMDoubleTypeInContext(context), ""); + } + + printf_type = LLVMFunctionType(LLVMInt32TypeInContext(context), NULL, 0, 1); + func_printf = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer)debug_printf)); + func_printf = LLVMBuildBitCast(builder, func_printf, LLVMPointerType(printf_type, 0), "debug_printf"); + + return LLVMBuildCall(builder, func_printf, args, argcount, ""); +} + + +/** + * Print a LLVM value of any type + */ +LLVMValueRef +lp_build_print_value(struct gallivm_state *gallivm, + const char *msg, + LLVMValueRef value) +{ + LLVMBuilderRef builder = gallivm->builder; + LLVMTypeKind type_kind; + LLVMTypeRef type_ref; + LLVMValueRef params[2 + LP_MAX_VECTOR_LENGTH]; + char type_fmt[6] = " %x"; + char format[2 + 5 * LP_MAX_VECTOR_LENGTH + 2] = "%s"; + unsigned length; + unsigned i; + + type_ref = LLVMTypeOf(value); + type_kind = LLVMGetTypeKind(type_ref); + + if (type_kind == LLVMVectorTypeKind) { + length = LLVMGetVectorSize(type_ref); + + type_ref = LLVMGetElementType(type_ref); + type_kind = LLVMGetTypeKind(type_ref); + } else { + length = 1; + } + + if (type_kind == LLVMFloatTypeKind || type_kind == LLVMDoubleTypeKind) { + type_fmt[2] = '.'; + type_fmt[3] = '9'; + type_fmt[4] = 'g'; + type_fmt[5] = '\0'; + } else if (type_kind == LLVMIntegerTypeKind) { + if (LLVMGetIntTypeWidth(type_ref) == 64) { + snprintf(type_fmt + 2, 3, "%s", PRId64); + } else if (LLVMGetIntTypeWidth(type_ref) == 8) { + type_fmt[2] = 'u'; + } else { + type_fmt[2] = 'i'; + } + } else if (type_kind == LLVMPointerTypeKind) { + type_fmt[2] = 'p'; + } else { + /* Unsupported type */ + assert(0); + } + + /* Create format string and arguments */ + assert(strlen(format) + strlen(type_fmt) * length + 2 <= sizeof format); + + params[1] = lp_build_const_string(gallivm, msg); + if (length == 1) { + strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); + params[2] = value; + } else { + for (i = 0; i < length; ++i) { + LLVMValueRef param; + strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); + param = LLVMBuildExtractElement(builder, value, lp_build_const_int32(gallivm, i), ""); + if (type_kind == LLVMIntegerTypeKind && + LLVMGetIntTypeWidth(type_ref) < sizeof(int) * 8) { + LLVMTypeRef int_type = LLVMIntTypeInContext(gallivm->context, sizeof(int) * 8); + if (LLVMGetIntTypeWidth(type_ref) == 8) { + param = LLVMBuildZExt(builder, param, int_type, ""); + } else { + param = LLVMBuildSExt(builder, param, int_type, ""); + } + } + params[2 + i] = param; + } + } + + strncat(format, "\n", sizeof(format) - strlen(format) - 1); + + params[0] = lp_build_const_string(gallivm, format); + return lp_build_print_args(gallivm, 2 + length, params); +} + + +static unsigned lp_get_printf_arg_count(const char *fmt) { - int count =0; + unsigned count = 0; const char *p = fmt; int c; @@ -44,78 +165,45 @@ lp_get_printf_arg_count(const char *fmt) continue; switch (*p) { case '\0': - continue; + continue; case '%': - p++; - continue; - case '.': - if (p[1] == '*' && p[2] == 's') { - count += 2; - p += 3; + p++; + continue; + case '.': + if (p[1] == '*' && p[2] == 's') { + count += 2; + p += 3; continue; - } - /* fallthrough */ - default: - count ++; + } + /* fallthrough */ + default: + count ++; } } return count; } -LLVMValueRef -lp_build_const_string_variable(LLVMModuleRef module, const char *str, int len) -{ - LLVMValueRef string = LLVMAddGlobal(module, LLVMArrayType(LLVMInt8Type(), len + 1), ""); - LLVMSetGlobalConstant(string, TRUE); - LLVMSetLinkage(string, LLVMInternalLinkage); - LLVMSetInitializer(string, LLVMConstString(str, len + 1, TRUE)); - return string; -} - /** - * lp_build_printf. - * - * Build printf call in LLVM IR. The output goes to stdout. - * The additional variable arguments need to have type - * LLVMValueRef. + * Generate LLVM IR for a c style printf */ LLVMValueRef -lp_build_printf(LLVMBuilderRef builder, const char *fmt, ...) +lp_build_printf(struct gallivm_state *gallivm, + const char *fmt, ...) { - va_list arglist; - int i = 0; - int argcount = lp_get_printf_arg_count(fmt); - LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder))); LLVMValueRef params[50]; - LLVMValueRef fmtarg = lp_build_const_string_variable(module, fmt, strlen(fmt) + 1); - LLVMValueRef int0 = LLVMConstInt(LLVMInt32Type(), 0, 0); - LLVMValueRef index[2]; - LLVMValueRef func_printf = LLVMGetNamedFunction(module, "printf"); - - assert(Elements(params) >= argcount + 1); - - index[0] = index[1] = int0; - - if (!func_printf) { - LLVMTypeRef printf_type = LLVMFunctionType(LLVMIntType(32), NULL, 0, 1); - func_printf = LLVMAddFunction(module, "printf", printf_type); - } + va_list arglist; + unsigned argcount, i; - params[0] = LLVMBuildGEP(builder, fmtarg, index, 2, ""); + argcount = lp_get_printf_arg_count(fmt); + assert(ARRAY_SIZE(params) >= argcount + 1); va_start(arglist, fmt); for (i = 1; i <= argcount; i++) { - LLVMValueRef val = va_arg(arglist, LLVMValueRef); - LLVMTypeRef type = LLVMTypeOf(val); - /* printf wants doubles, so lets convert so that - * we can actually print them */ - if (LLVMGetTypeKind(type) == LLVMFloatTypeKind) - val = LLVMBuildFPExt(builder, val, LLVMDoubleType(), ""); - params[i] = val; + params[i] = va_arg(arglist, LLVMValueRef); } va_end(arglist); - return LLVMBuildCall(builder, func_printf, params, argcount + 1, ""); + params[0] = lp_build_const_string(gallivm, fmt); + return lp_build_print_args(gallivm, argcount + 1, params); } -