5e359ceaa2053ae306967621d7da321eb7c62987
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_printf.c
1 /**************************************************************************
2 *
3 * Copyright 2010 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <stdio.h>
29
30 #include "util/u_debug.h"
31 #include "util/u_memory.h"
32 #include "util/u_string.h"
33 #include "lp_bld_const.h"
34 #include "lp_bld_init.h"
35 #include "lp_bld_const.h"
36 #include "lp_bld_printf.h"
37
38
39 static int
40 lp_get_printf_arg_count(const char *fmt)
41 {
42 int count =0;
43 const char *p = fmt;
44 int c;
45
46 while ((c = *p++)) {
47 if (c != '%')
48 continue;
49 switch (*p) {
50 case '\0':
51 continue;
52 case '%':
53 p++;
54 continue;
55 case '.':
56 if (p[1] == '*' && p[2] == 's') {
57 count += 2;
58 p += 3;
59 continue;
60 }
61 /* fallthrough */
62 default:
63 count ++;
64 }
65 }
66 return count;
67 }
68
69 /**
70 * lp_build_printf.
71 *
72 * Build printf call in LLVM IR. The output goes to stdout.
73 * The additional variable arguments need to have type
74 * LLVMValueRef.
75 */
76 LLVMValueRef
77 lp_build_printf(struct gallivm_state *gallivm, const char *fmt, ...)
78 {
79 va_list arglist;
80 int i = 0;
81 int argcount = lp_get_printf_arg_count(fmt);
82 LLVMBuilderRef builder = gallivm->builder;
83 LLVMContextRef context = gallivm->context;
84 LLVMValueRef params[50];
85 LLVMValueRef fmtarg = lp_build_const_string(gallivm, fmt);
86 LLVMTypeRef printf_type;
87 LLVMValueRef func_printf;
88
89 assert(Elements(params) >= argcount + 1);
90
91 printf_type = LLVMFunctionType(LLVMIntTypeInContext(context, 32), NULL, 0, 1);
92
93 func_printf = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer)debug_printf));
94
95 func_printf = LLVMBuildBitCast(gallivm->builder, func_printf,
96 LLVMPointerType(printf_type, 0),
97 "debug_printf");
98
99 params[0] = fmtarg;
100
101 va_start(arglist, fmt);
102 for (i = 1; i <= argcount; i++) {
103 LLVMValueRef val = va_arg(arglist, LLVMValueRef);
104 LLVMTypeRef type = LLVMTypeOf(val);
105 /* printf wants doubles, so lets convert so that
106 * we can actually print them */
107 if (LLVMGetTypeKind(type) == LLVMFloatTypeKind)
108 val = LLVMBuildFPExt(builder, val, LLVMDoubleTypeInContext(context), "");
109 params[i] = val;
110 }
111 va_end(arglist);
112
113 return LLVMBuildCall(builder, func_printf, params, argcount + 1, "");
114 }
115
116
117
118 /**
119 * Print a float[4] vector.
120 */
121 LLVMValueRef
122 lp_build_print_vec4(struct gallivm_state *gallivm,
123 const char *msg, LLVMValueRef vec)
124 {
125 LLVMBuilderRef builder = gallivm->builder;
126 char format[1000];
127 LLVMValueRef x, y, z, w;
128
129 x = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 0), "");
130 y = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 1), "");
131 z = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 2), "");
132 w = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 3), "");
133
134 util_snprintf(format, sizeof(format), "%s %%f %%f %%f %%f\n", msg);
135 return lp_build_printf(gallivm, format, x, y, z, w);
136 }
137
138
139 /**
140 * Print a intt[4] vector.
141 */
142 LLVMValueRef
143 lp_build_print_ivec4(struct gallivm_state *gallivm,
144 const char *msg, LLVMValueRef vec)
145 {
146 LLVMBuilderRef builder = gallivm->builder;
147 char format[1000];
148 LLVMValueRef x, y, z, w;
149
150 x = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 0), "");
151 y = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 1), "");
152 z = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 2), "");
153 w = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 3), "");
154
155 util_snprintf(format, sizeof(format), "%s %%i %%i %%i %%i\n", msg);
156 return lp_build_printf(gallivm, format, x, y, z, w);
157 }
158
159
160 /**
161 * Print a uint8[16] vector.
162 */
163 LLVMValueRef
164 lp_build_print_uvec16(struct gallivm_state *gallivm,
165 const char *msg, LLVMValueRef vec)
166 {
167 LLVMBuilderRef builder = gallivm->builder;
168 char format[1000];
169 LLVMValueRef args[16];
170 int i;
171
172 for (i = 0; i < 16; ++i) {
173 args[i] = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, i), "");
174 }
175
176 util_snprintf(format, sizeof(format), "%s %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u\n", msg);
177
178 return lp_build_printf(
179 gallivm, format,
180 args[ 0], args[ 1], args[ 2], args[ 3],
181 args[ 4], args[ 5], args[ 6], args[ 7],
182 args[ 8], args[ 9], args[10], args[11],
183 args[12], args[13], args[14], args[15]);
184 }