#include "lp_bld_init.h"
#include "lp_bld_const.h"
#include "lp_bld_printf.h"
+#include "lp_bld_type.h"
+
+
+/**
+ * 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) == 8) {
+ type_fmt[2] = 'u';
+ } else {
+ type_fmt[2] = 'i';
+ }
+ } 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) {
+ util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1);
+ params[2] = value;
+ } else {
+ for (i = 0; i < length; ++i) {
+ util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1);
+ params[2 + i] = LLVMBuildExtractElement(builder, value, lp_build_const_int32(gallivm, i), "");
+ }
+ }
+
+ util_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 int
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,
- LLVMContextRef context,
- const char *str, int len)
-{
- LLVMValueRef string = LLVMAddGlobal(module, LLVMArrayType(LLVMInt8TypeInContext(context), len + 1), "");
- LLVMSetGlobalConstant(string, TRUE);
- LLVMSetLinkage(string, LLVMInternalLinkage);
- LLVMSetInitializer(string, LLVMConstStringInContext(context, 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(struct gallivm_state *gallivm, 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);
- LLVMBuilderRef builder = gallivm->builder;
- LLVMContextRef context = gallivm->context;
- LLVMModuleRef module = gallivm->module;
LLVMValueRef params[50];
- LLVMValueRef fmtarg = lp_build_const_string_variable(module, context,
- fmt, strlen(fmt) + 1);
- LLVMValueRef int0 = lp_build_const_int32(gallivm, 0);
- LLVMValueRef index[2];
- LLVMValueRef func_printf = LLVMGetNamedFunction(module, "printf");
+ va_list arglist;
+ int argcount;
+ int i;
+ argcount = lp_get_printf_arg_count(fmt);
assert(Elements(params) >= argcount + 1);
- index[0] = index[1] = int0;
-
- if (!func_printf) {
- LLVMTypeRef printf_type = LLVMFunctionType(LLVMIntTypeInContext(context, 32), NULL, 0, 1);
- func_printf = LLVMAddFunction(module, "printf", printf_type);
- }
-
- params[0] = LLVMBuildGEP(builder, fmtarg, index, 2, "");
-
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, LLVMDoubleTypeInContext(context), "");
- params[i] = val;
+ params[i] = va_arg(arglist, LLVMValueRef);
}
va_end(arglist);
- return LLVMBuildCall(builder, func_printf, params, argcount + 1, "");
-}
-
-
-
-/**
- * Print a float[4] vector.
- */
-LLVMValueRef
-lp_build_print_vec4(struct gallivm_state *gallivm,
- const char *msg, LLVMValueRef vec)
-{
- LLVMBuilderRef builder = gallivm->builder;
- char format[1000];
- LLVMValueRef x, y, z, w;
-
- x = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 0), "");
- y = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 1), "");
- z = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 2), "");
- w = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 3), "");
-
- util_snprintf(format, sizeof(format), "%s %%f %%f %%f %%f\n", msg);
- return lp_build_printf(gallivm, format, x, y, z, w);
-}
-
-
-/**
- * Print a intt[4] vector.
- */
-LLVMValueRef
-lp_build_print_ivec4(struct gallivm_state *gallivm,
- const char *msg, LLVMValueRef vec)
-{
- LLVMBuilderRef builder = gallivm->builder;
- char format[1000];
- LLVMValueRef x, y, z, w;
-
- x = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 0), "");
- y = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 1), "");
- z = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 2), "");
- w = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, 3), "");
-
- util_snprintf(format, sizeof(format), "%s %%i %%i %%i %%i\n", msg);
- return lp_build_printf(gallivm, format, x, y, z, w);
+ params[0] = lp_build_const_string(gallivm, fmt);
+ return lp_build_print_args(gallivm, argcount + 1, params);
}