13b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li/************************************************************************** 23b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * 33b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * Copyright 2010 VMware, Inc. 43b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * All Rights Reserved. 53b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * 63b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * Permission is hereby granted, free of charge, to any person obtaining a 73b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * copy of this software and associated documentation files (the 83b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * "Software"), to deal in the Software without restriction, including 93b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * without limitation the rights to use, copy, modify, merge, publish, 103b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * distribute, sub license, and/or sell copies of the Software, and to 113b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * permit persons to whom the Software is furnished to do so, subject to 123b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * the following conditions: 133b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * 143b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * The above copyright notice and this permission notice (including the 153b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * next paragraph) shall be included in all copies or substantial portions 163b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * of the Software. 173b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * 183b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 193b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 203b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 213b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 223b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 233b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 243b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 253b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li * 263b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li **************************************************************************/ 273b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 283b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li#include <stdio.h> 29c01c6a95b41607dc58a343b2aa67bc3da673ca35Zack Rusin#include <inttypes.h> 303b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 318c6f71e01e40075156c8b83f2c5e15ab73e66036Brian Paul#include "util/u_debug.h" 328c6f71e01e40075156c8b83f2c5e15ab73e66036Brian Paul#include "util/u_memory.h" 3346c2ee4fad7d960fb0ff396caff4430df6a4611eBrian Paul#include "util/u_string.h" 34991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul#include "lp_bld_const.h" 35efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul#include "lp_bld_init.h" 36efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul#include "lp_bld_const.h" 373b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li#include "lp_bld_printf.h" 38789436f1e07a68b632937d9f2101efc5e68f7499James Benton#include "lp_bld_type.h" 393b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 403b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 413b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li/** 42789436f1e07a68b632937d9f2101efc5e68f7499James Benton * Generates LLVM IR to call debug_printf. 433b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li */ 44789436f1e07a68b632937d9f2101efc5e68f7499James Bentonstatic LLVMValueRef 45789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_build_print_args(struct gallivm_state* gallivm, 46789436f1e07a68b632937d9f2101efc5e68f7499James Benton int argcount, 47789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef* args) 483b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li{ 49efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul LLVMBuilderRef builder = gallivm->builder; 50efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul LLVMContextRef context = gallivm->context; 51494619ebacb632a879ebeecf0a1d732c10ddf25bJosé Fonseca LLVMValueRef func_printf; 52789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeRef printf_type; 53789436f1e07a68b632937d9f2101efc5e68f7499James Benton int i; 543b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 55789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(args); 56789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(argcount > 0); 57789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(LLVMTypeOf(args[0]) == LLVMPointerType(LLVMInt8TypeInContext(context), 0)); 583b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 59789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* Cast any float arguments to doubles as printf expects */ 60789436f1e07a68b632937d9f2101efc5e68f7499James Benton for (i = 1; i < argcount; i++) { 61789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeRef type = LLVMTypeOf(args[i]); 623b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 632fb655d1dbb3f8425aeff1597271262661ef206bZack Rusin if (LLVMGetTypeKind(type) == LLVMFloatTypeKind) 64789436f1e07a68b632937d9f2101efc5e68f7499James Benton args[i] = LLVMBuildFPExt(builder, args[i], LLVMDoubleTypeInContext(context), ""); 652fb655d1dbb3f8425aeff1597271262661ef206bZack Rusin } 663b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 67789436f1e07a68b632937d9f2101efc5e68f7499James Benton printf_type = LLVMFunctionType(LLVMInt32TypeInContext(context), NULL, 0, 1); 68789436f1e07a68b632937d9f2101efc5e68f7499James Benton func_printf = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer)debug_printf)); 69789436f1e07a68b632937d9f2101efc5e68f7499James Benton func_printf = LLVMBuildBitCast(builder, func_printf, LLVMPointerType(printf_type, 0), "debug_printf"); 703b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 71789436f1e07a68b632937d9f2101efc5e68f7499James Benton return LLVMBuildCall(builder, func_printf, args, argcount, ""); 72789436f1e07a68b632937d9f2101efc5e68f7499James Benton} 73991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 74991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 75991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul/** 76789436f1e07a68b632937d9f2101efc5e68f7499James Benton * Print a LLVM value of any type 77991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul */ 78991f0c27638c4bc03a0c609244bf755a0820d46fBrian PaulLLVMValueRef 79789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_build_print_value(struct gallivm_state *gallivm, 80789436f1e07a68b632937d9f2101efc5e68f7499James Benton const char *msg, 81789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef value) 82991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul{ 83efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul LLVMBuilderRef builder = gallivm->builder; 84789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeKind type_kind; 85789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeRef type_ref; 86789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef params[2 + LP_MAX_VECTOR_LENGTH]; 87978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca char type_fmt[6] = " %x"; 88978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca char format[2 + 5 * LP_MAX_VECTOR_LENGTH + 2] = "%s"; 89789436f1e07a68b632937d9f2101efc5e68f7499James Benton unsigned length; 90789436f1e07a68b632937d9f2101efc5e68f7499James Benton unsigned i; 91789436f1e07a68b632937d9f2101efc5e68f7499James Benton 92789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_ref = LLVMTypeOf(value); 93789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_kind = LLVMGetTypeKind(type_ref); 94789436f1e07a68b632937d9f2101efc5e68f7499James Benton 95789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (type_kind == LLVMVectorTypeKind) { 96789436f1e07a68b632937d9f2101efc5e68f7499James Benton length = LLVMGetVectorSize(type_ref); 97789436f1e07a68b632937d9f2101efc5e68f7499James Benton 98789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_ref = LLVMGetElementType(type_ref); 99789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_kind = LLVMGetTypeKind(type_ref); 100789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 101789436f1e07a68b632937d9f2101efc5e68f7499James Benton length = 1; 102789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 103991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 104789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (type_kind == LLVMFloatTypeKind || type_kind == LLVMDoubleTypeKind) { 105978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[2] = '.'; 106978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[3] = '9'; 107978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[4] = 'g'; 108978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[5] = '\0'; 109789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else if (type_kind == LLVMIntegerTypeKind) { 110c01c6a95b41607dc58a343b2aa67bc3da673ca35Zack Rusin if (LLVMGetIntTypeWidth(type_ref) == 64) { 111c01c6a95b41607dc58a343b2aa67bc3da673ca35Zack Rusin unsigned flen = strlen(PRId64); 112c01c6a95b41607dc58a343b2aa67bc3da673ca35Zack Rusin assert(flen <= 3); 113c01c6a95b41607dc58a343b2aa67bc3da673ca35Zack Rusin strncpy(type_fmt + 2, PRId64, flen); 114c01c6a95b41607dc58a343b2aa67bc3da673ca35Zack Rusin } else if (LLVMGetIntTypeWidth(type_ref) == 8) { 115789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_fmt[2] = 'u'; 116789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 117789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_fmt[2] = 'i'; 118789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 119cb9913cdab763ac21ea6659f93e9564db9df47e8José Fonseca } else if (type_kind == LLVMPointerTypeKind) { 120cb9913cdab763ac21ea6659f93e9564db9df47e8José Fonseca type_fmt[2] = 'p'; 121789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 122789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* Unsupported type */ 123789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(0); 124789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 125991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 126789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* Create format string and arguments */ 127789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(strlen(format) + strlen(type_fmt) * length + 2 <= sizeof format); 128789436f1e07a68b632937d9f2101efc5e68f7499James Benton 129789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[1] = lp_build_const_string(gallivm, msg); 130789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (length == 1) { 131bf679ce1dcc9cb90bb0092a550a03ad391f6ba72Johannes Obermayr util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); 132789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[2] = value; 133789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 134789436f1e07a68b632937d9f2101efc5e68f7499James Benton for (i = 0; i < length; ++i) { 13533ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca LLVMValueRef param; 136bf679ce1dcc9cb90bb0092a550a03ad391f6ba72Johannes Obermayr util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); 13733ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca param = LLVMBuildExtractElement(builder, value, lp_build_const_int32(gallivm, i), ""); 13833ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca if (type_kind == LLVMIntegerTypeKind && 13933ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca LLVMGetIntTypeWidth(type_ref) < sizeof(int) * 8) { 14033ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca LLVMTypeRef int_type = LLVMIntTypeInContext(gallivm->context, sizeof(int) * 8); 14133ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca if (LLVMGetIntTypeWidth(type_ref) == 8) { 14233ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca param = LLVMBuildZExt(builder, param, int_type, ""); 14333ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca } else { 14433ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca param = LLVMBuildSExt(builder, param, int_type, ""); 14533ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca } 14633ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca } 14733ffca713a5e593beda34d6bcbee8fb1af472cf7José Fonseca params[2 + i] = param; 148789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 149789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 150789436f1e07a68b632937d9f2101efc5e68f7499James Benton 151bf679ce1dcc9cb90bb0092a550a03ad391f6ba72Johannes Obermayr util_strncat(format, "\n", sizeof(format) - strlen(format) - 1); 152789436f1e07a68b632937d9f2101efc5e68f7499James Benton 153789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[0] = lp_build_const_string(gallivm, format); 154789436f1e07a68b632937d9f2101efc5e68f7499James Benton return lp_build_print_args(gallivm, 2 + length, params); 155991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul} 156903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul 157903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul 158ace70aedcf8b29380a17f68a994b18f60976bca6Jan Veselystatic unsigned 159789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_get_printf_arg_count(const char *fmt) 160903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul{ 161ace70aedcf8b29380a17f68a994b18f60976bca6Jan Vesely unsigned count = 0; 162789436f1e07a68b632937d9f2101efc5e68f7499James Benton const char *p = fmt; 163789436f1e07a68b632937d9f2101efc5e68f7499James Benton int c; 164903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul 165789436f1e07a68b632937d9f2101efc5e68f7499James Benton while ((c = *p++)) { 166789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (c != '%') 167789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 168789436f1e07a68b632937d9f2101efc5e68f7499James Benton switch (*p) { 169789436f1e07a68b632937d9f2101efc5e68f7499James Benton case '\0': 170789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 171789436f1e07a68b632937d9f2101efc5e68f7499James Benton case '%': 172789436f1e07a68b632937d9f2101efc5e68f7499James Benton p++; 173789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 174789436f1e07a68b632937d9f2101efc5e68f7499James Benton case '.': 175789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (p[1] == '*' && p[2] == 's') { 176789436f1e07a68b632937d9f2101efc5e68f7499James Benton count += 2; 177789436f1e07a68b632937d9f2101efc5e68f7499James Benton p += 3; 178789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 179789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 180789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* fallthrough */ 181789436f1e07a68b632937d9f2101efc5e68f7499James Benton default: 182789436f1e07a68b632937d9f2101efc5e68f7499James Benton count ++; 183789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 184789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 185789436f1e07a68b632937d9f2101efc5e68f7499James Benton return count; 186903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul} 187f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 188f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 189f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton/** 190789436f1e07a68b632937d9f2101efc5e68f7499James Benton * Generate LLVM IR for a c style printf 191f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton */ 192f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames BentonLLVMValueRef 193789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_build_printf(struct gallivm_state *gallivm, 194789436f1e07a68b632937d9f2101efc5e68f7499James Benton const char *fmt, ...) 195f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton{ 196789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef params[50]; 197789436f1e07a68b632937d9f2101efc5e68f7499James Benton va_list arglist; 198ace70aedcf8b29380a17f68a994b18f60976bca6Jan Vesely unsigned argcount, i; 199f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 200789436f1e07a68b632937d9f2101efc5e68f7499James Benton argcount = lp_get_printf_arg_count(fmt); 201e522a76226acfcf786457ce4472294d9e36adc94Brian Paul assert(ARRAY_SIZE(params) >= argcount + 1); 202f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 203789436f1e07a68b632937d9f2101efc5e68f7499James Benton va_start(arglist, fmt); 204789436f1e07a68b632937d9f2101efc5e68f7499James Benton for (i = 1; i <= argcount; i++) { 205789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[i] = va_arg(arglist, LLVMValueRef); 206789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 207789436f1e07a68b632937d9f2101efc5e68f7499James Benton va_end(arglist); 208f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 209789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[0] = lp_build_const_string(gallivm, fmt); 210789436f1e07a68b632937d9f2101efc5e68f7499James Benton return lp_build_print_args(gallivm, argcount + 1, params); 211f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton} 212