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> 293b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 308c6f71e01e40075156c8b83f2c5e15ab73e66036Brian Paul#include "util/u_debug.h" 318c6f71e01e40075156c8b83f2c5e15ab73e66036Brian Paul#include "util/u_memory.h" 3246c2ee4fad7d960fb0ff396caff4430df6a4611eBrian Paul#include "util/u_string.h" 33991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul#include "lp_bld_const.h" 34efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul#include "lp_bld_init.h" 35efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul#include "lp_bld_const.h" 363b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li#include "lp_bld_printf.h" 37789436f1e07a68b632937d9f2101efc5e68f7499James Benton#include "lp_bld_type.h" 383b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 393b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 403b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li/** 41789436f1e07a68b632937d9f2101efc5e68f7499James Benton * Generates LLVM IR to call debug_printf. 423b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li */ 43789436f1e07a68b632937d9f2101efc5e68f7499James Bentonstatic LLVMValueRef 44789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_build_print_args(struct gallivm_state* gallivm, 45789436f1e07a68b632937d9f2101efc5e68f7499James Benton int argcount, 46789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef* args) 473b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li{ 48efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul LLVMBuilderRef builder = gallivm->builder; 49efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul LLVMContextRef context = gallivm->context; 50494619ebacb632a879ebeecf0a1d732c10ddf25bJosé Fonseca LLVMValueRef func_printf; 51789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeRef printf_type; 52789436f1e07a68b632937d9f2101efc5e68f7499James Benton int i; 533b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 54789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(args); 55789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(argcount > 0); 56789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(LLVMTypeOf(args[0]) == LLVMPointerType(LLVMInt8TypeInContext(context), 0)); 573b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 58789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* Cast any float arguments to doubles as printf expects */ 59789436f1e07a68b632937d9f2101efc5e68f7499James Benton for (i = 1; i < argcount; i++) { 60789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeRef type = LLVMTypeOf(args[i]); 613b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 622fb655d1dbb3f8425aeff1597271262661ef206bZack Rusin if (LLVMGetTypeKind(type) == LLVMFloatTypeKind) 63789436f1e07a68b632937d9f2101efc5e68f7499James Benton args[i] = LLVMBuildFPExt(builder, args[i], LLVMDoubleTypeInContext(context), ""); 642fb655d1dbb3f8425aeff1597271262661ef206bZack Rusin } 653b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 66789436f1e07a68b632937d9f2101efc5e68f7499James Benton printf_type = LLVMFunctionType(LLVMInt32TypeInContext(context), NULL, 0, 1); 67789436f1e07a68b632937d9f2101efc5e68f7499James Benton func_printf = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer)debug_printf)); 68789436f1e07a68b632937d9f2101efc5e68f7499James Benton func_printf = LLVMBuildBitCast(builder, func_printf, LLVMPointerType(printf_type, 0), "debug_printf"); 693b1a8d9d5ba286da568b4176ed533a7dde60ad18Chris Li 70789436f1e07a68b632937d9f2101efc5e68f7499James Benton return LLVMBuildCall(builder, func_printf, args, argcount, ""); 71789436f1e07a68b632937d9f2101efc5e68f7499James Benton} 72991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 73991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 74991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul/** 75789436f1e07a68b632937d9f2101efc5e68f7499James Benton * Print a LLVM value of any type 76991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul */ 77991f0c27638c4bc03a0c609244bf755a0820d46fBrian PaulLLVMValueRef 78789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_build_print_value(struct gallivm_state *gallivm, 79789436f1e07a68b632937d9f2101efc5e68f7499James Benton const char *msg, 80789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef value) 81991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul{ 82efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul LLVMBuilderRef builder = gallivm->builder; 83789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeKind type_kind; 84789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMTypeRef type_ref; 85789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef params[2 + LP_MAX_VECTOR_LENGTH]; 86978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca char type_fmt[6] = " %x"; 87978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca char format[2 + 5 * LP_MAX_VECTOR_LENGTH + 2] = "%s"; 88789436f1e07a68b632937d9f2101efc5e68f7499James Benton unsigned length; 89789436f1e07a68b632937d9f2101efc5e68f7499James Benton unsigned i; 90789436f1e07a68b632937d9f2101efc5e68f7499James Benton 91789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_ref = LLVMTypeOf(value); 92789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_kind = LLVMGetTypeKind(type_ref); 93789436f1e07a68b632937d9f2101efc5e68f7499James Benton 94789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (type_kind == LLVMVectorTypeKind) { 95789436f1e07a68b632937d9f2101efc5e68f7499James Benton length = LLVMGetVectorSize(type_ref); 96789436f1e07a68b632937d9f2101efc5e68f7499James Benton 97789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_ref = LLVMGetElementType(type_ref); 98789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_kind = LLVMGetTypeKind(type_ref); 99789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 100789436f1e07a68b632937d9f2101efc5e68f7499James Benton length = 1; 101789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 102991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 103789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (type_kind == LLVMFloatTypeKind || type_kind == LLVMDoubleTypeKind) { 104978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[2] = '.'; 105978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[3] = '9'; 106978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[4] = 'g'; 107978807ef0153be27e4df19691e3d5f7d7a2a472bJosé Fonseca type_fmt[5] = '\0'; 108789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else if (type_kind == LLVMIntegerTypeKind) { 109789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (LLVMGetIntTypeWidth(type_ref) == 8) { 110789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_fmt[2] = 'u'; 111789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 112789436f1e07a68b632937d9f2101efc5e68f7499James Benton type_fmt[2] = 'i'; 113789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 114789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 115789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* Unsupported type */ 116789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(0); 117789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 118991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul 119789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* Create format string and arguments */ 120789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(strlen(format) + strlen(type_fmt) * length + 2 <= sizeof format); 121789436f1e07a68b632937d9f2101efc5e68f7499James Benton 122789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[1] = lp_build_const_string(gallivm, msg); 123789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (length == 1) { 124bf679ce1dcc9cb90bb0092a550a03ad391f6ba72Johannes Obermayr util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); 125789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[2] = value; 126789436f1e07a68b632937d9f2101efc5e68f7499James Benton } else { 127789436f1e07a68b632937d9f2101efc5e68f7499James Benton for (i = 0; i < length; ++i) { 128bf679ce1dcc9cb90bb0092a550a03ad391f6ba72Johannes Obermayr util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); 129789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[2 + i] = LLVMBuildExtractElement(builder, value, lp_build_const_int32(gallivm, i), ""); 130789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 131789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 132789436f1e07a68b632937d9f2101efc5e68f7499James Benton 133bf679ce1dcc9cb90bb0092a550a03ad391f6ba72Johannes Obermayr util_strncat(format, "\n", sizeof(format) - strlen(format) - 1); 134789436f1e07a68b632937d9f2101efc5e68f7499James Benton 135789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[0] = lp_build_const_string(gallivm, format); 136789436f1e07a68b632937d9f2101efc5e68f7499James Benton return lp_build_print_args(gallivm, 2 + length, params); 137991f0c27638c4bc03a0c609244bf755a0820d46fBrian Paul} 138903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul 139903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul 140789436f1e07a68b632937d9f2101efc5e68f7499James Bentonstatic int 141789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_get_printf_arg_count(const char *fmt) 142903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul{ 143789436f1e07a68b632937d9f2101efc5e68f7499James Benton int count =0; 144789436f1e07a68b632937d9f2101efc5e68f7499James Benton const char *p = fmt; 145789436f1e07a68b632937d9f2101efc5e68f7499James Benton int c; 146903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul 147789436f1e07a68b632937d9f2101efc5e68f7499James Benton while ((c = *p++)) { 148789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (c != '%') 149789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 150789436f1e07a68b632937d9f2101efc5e68f7499James Benton switch (*p) { 151789436f1e07a68b632937d9f2101efc5e68f7499James Benton case '\0': 152789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 153789436f1e07a68b632937d9f2101efc5e68f7499James Benton case '%': 154789436f1e07a68b632937d9f2101efc5e68f7499James Benton p++; 155789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 156789436f1e07a68b632937d9f2101efc5e68f7499James Benton case '.': 157789436f1e07a68b632937d9f2101efc5e68f7499James Benton if (p[1] == '*' && p[2] == 's') { 158789436f1e07a68b632937d9f2101efc5e68f7499James Benton count += 2; 159789436f1e07a68b632937d9f2101efc5e68f7499James Benton p += 3; 160789436f1e07a68b632937d9f2101efc5e68f7499James Benton continue; 161789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 162789436f1e07a68b632937d9f2101efc5e68f7499James Benton /* fallthrough */ 163789436f1e07a68b632937d9f2101efc5e68f7499James Benton default: 164789436f1e07a68b632937d9f2101efc5e68f7499James Benton count ++; 165789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 166789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 167789436f1e07a68b632937d9f2101efc5e68f7499James Benton return count; 168903a14ed9146f3a38895ca7e39f69f2ad77bf5dfBrian Paul} 169f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 170f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 171f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton/** 172789436f1e07a68b632937d9f2101efc5e68f7499James Benton * Generate LLVM IR for a c style printf 173f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton */ 174f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames BentonLLVMValueRef 175789436f1e07a68b632937d9f2101efc5e68f7499James Bentonlp_build_printf(struct gallivm_state *gallivm, 176789436f1e07a68b632937d9f2101efc5e68f7499James Benton const char *fmt, ...) 177f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton{ 178789436f1e07a68b632937d9f2101efc5e68f7499James Benton LLVMValueRef params[50]; 179789436f1e07a68b632937d9f2101efc5e68f7499James Benton va_list arglist; 180789436f1e07a68b632937d9f2101efc5e68f7499James Benton int argcount; 1817d1f414103bb294d30cac8fecddff0b2ab694810José Fonseca int i; 182f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 183789436f1e07a68b632937d9f2101efc5e68f7499James Benton argcount = lp_get_printf_arg_count(fmt); 184789436f1e07a68b632937d9f2101efc5e68f7499James Benton assert(Elements(params) >= argcount + 1); 185f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 186789436f1e07a68b632937d9f2101efc5e68f7499James Benton va_start(arglist, fmt); 187789436f1e07a68b632937d9f2101efc5e68f7499James Benton for (i = 1; i <= argcount; i++) { 188789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[i] = va_arg(arglist, LLVMValueRef); 189789436f1e07a68b632937d9f2101efc5e68f7499James Benton } 190789436f1e07a68b632937d9f2101efc5e68f7499James Benton va_end(arglist); 191f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton 192789436f1e07a68b632937d9f2101efc5e68f7499James Benton params[0] = lp_build_const_string(gallivm, fmt); 193789436f1e07a68b632937d9f2101efc5e68f7499James Benton return lp_build_print_args(gallivm, argcount + 1, params); 194f64fe7d333ef5f00f1d13d19c9b986abe21a524cJames Benton} 195