gallivm: Added a generic lp_build_print_value which prints a LLVMValueRef.
authorJames Benton <jbenton@vmware.com>
Tue, 26 Jun 2012 14:00:14 +0000 (15:00 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Wed, 27 Jun 2012 10:16:18 +0000 (11:16 +0100)
Updated lp_build_printf to share common code.
Removed specific lp_build_print_vecX.

Reviewed-by: José Fonseca <jfonseca@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/auxiliary/gallivm/lp_bld_printf.c
src/gallium/auxiliary/gallivm/lp_bld_printf.h

index 5e359ceaa2053ae306967621d7da321eb7c62987..16ef25a8a39c39217296337c319f80599f868307 100644 (file)
 #include "lp_bld_init.h"
 #include "lp_bld_const.h"
 #include "lp_bld_printf.h"
+#include "lp_bld_type.h"
 
 
-static int
-lp_get_printf_arg_count(const char *fmt)
-{
-   int count =0;
-   const char *p = fmt;
-   int c;
-
-   while ((c = *p++)) {
-      if (c != '%')
-         continue;
-      switch (*p) {
-         case '\0':
-           continue;
-         case '%':
-           p++;
-           continue;
-        case '.':
-           if (p[1] == '*' && p[2] == 's') {
-              count += 2;
-              p += 3;
-               continue;
-           }
-           /* fallthrough */
-        default:
-           count ++;
-      }
-   }
-   return count;
-}
-
 /**
- * lp_build_printf.
- *
- * Build printf call in LLVM IR. The output goes to stdout.
- * The additional variable arguments need to have type
- * LLVMValueRef.
+ * Generates LLVM IR to call debug_printf.
  */
-LLVMValueRef
-lp_build_printf(struct gallivm_state *gallivm, const char *fmt, ...)
+static LLVMValueRef
+lp_build_print_args(struct gallivm_state* gallivm,
+                    int argcount,
+                    LLVMValueRef* args)
 {
-   va_list arglist;
-   int i = 0;
-   int argcount = lp_get_printf_arg_count(fmt);
    LLVMBuilderRef builder = gallivm->builder;
    LLVMContextRef context = gallivm->context;
-   LLVMValueRef params[50];
-   LLVMValueRef fmtarg = lp_build_const_string(gallivm, fmt);
-   LLVMTypeRef printf_type;
    LLVMValueRef func_printf;
+   LLVMTypeRef printf_type;
+   int i;
 
-   assert(Elements(params) >= argcount + 1);
-
-   printf_type = LLVMFunctionType(LLVMIntTypeInContext(context, 32), NULL, 0, 1);
-
-   func_printf = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer)debug_printf));
-
-   func_printf = LLVMBuildBitCast(gallivm->builder, func_printf,
-                                  LLVMPointerType(printf_type, 0),
-                                  "debug_printf");
+   assert(args);
+   assert(argcount > 0);
+   assert(LLVMTypeOf(args[0]) == LLVMPointerType(LLVMInt8TypeInContext(context), 0));
 
-   params[0] = fmtarg;
+   /* Cast any float arguments to doubles as printf expects */
+   for (i = 1; i < argcount; i++) {
+      LLVMTypeRef type = LLVMTypeOf(args[i]);
 
-   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;
+         args[i] = LLVMBuildFPExt(builder, args[i], LLVMDoubleTypeInContext(context), "");
    }
-   va_end(arglist);
 
-   return LLVMBuildCall(builder, func_printf, params, argcount + 1, "");
-}
+   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 float[4] vector.
+ * Print a LLVM value of any type
  */
 LLVMValueRef
-lp_build_print_vec4(struct gallivm_state *gallivm,
-                    const char *msg, LLVMValueRef vec)
+lp_build_print_value(struct gallivm_state *gallivm,
+                     const char *msg,
+                     LLVMValueRef value)
 {
    LLVMBuilderRef builder = gallivm->builder;
-   char format[1000];
-   LLVMValueRef x, y, z, w;
+   LLVMTypeKind type_kind;
+   LLVMTypeRef type_ref;
+   LLVMValueRef params[2 + LP_MAX_VECTOR_LENGTH];
+   char type_fmt[4] = " %x";
+   char format[2 + 3 * 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;
+   }
 
-   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), "");
+   if (type_kind == LLVMFloatTypeKind || type_kind == LLVMDoubleTypeKind) {
+      type_fmt[2] = 'f';
+   } else if (type_kind == LLVMIntegerTypeKind) {
+      if (LLVMGetIntTypeWidth(type_ref) == 8) {
+         type_fmt[2] = 'u';
+      } else {
+         type_fmt[2] = 'i';
+      }
+   } else {
+      /* Unsupported type */
+      assert(0);
+   }
 
-   util_snprintf(format, sizeof(format), "%s %%f %%f %%f %%f\n", msg);
-   return lp_build_printf(gallivm, format, x, y, z, w);
+   /* 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);
+      params[2] = value;
+   } else {
+      for (i = 0; i < length; ++i) {
+         util_strncat(format, type_fmt, sizeof format);
+         params[2 + i] = LLVMBuildExtractElement(builder, value, lp_build_const_int32(gallivm, i), "");
+      }
+   }
+
+   util_strncat(format, "\n", sizeof format);
+
+   params[0] = lp_build_const_string(gallivm, format);
+   return lp_build_print_args(gallivm, 2 + length, params);
 }
 
 
-/**
- * Print a intt[4] vector.
- */
-LLVMValueRef
-lp_build_print_ivec4(struct gallivm_state *gallivm,
-                    const char *msg, LLVMValueRef vec)
+static int
+lp_get_printf_arg_count(const char *fmt)
 {
-   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), "");
+   int count =0;
+   const char *p = fmt;
+   int c;
 
-   util_snprintf(format, sizeof(format), "%s %%i %%i %%i %%i\n", msg);
-   return lp_build_printf(gallivm, format, x, y, z, w);
+   while ((c = *p++)) {
+      if (c != '%')
+         continue;
+      switch (*p) {
+         case '\0':
+       continue;
+         case '%':
+       p++;
+       continue;
+    case '.':
+       if (p[1] == '*' && p[2] == 's') {
+          count += 2;
+          p += 3;
+               continue;
+       }
+       /* fallthrough */
+    default:
+       count ++;
+      }
+   }
+   return count;
 }
 
 
 /**
- * Print a uint8[16] vector.
+ * Generate LLVM IR for a c style printf
  */
 LLVMValueRef
-lp_build_print_uvec16(struct gallivm_state *gallivm,
-                    const char *msg, LLVMValueRef vec)
+lp_build_printf(struct gallivm_state *gallivm,
+                const char *fmt, ...)
 {
-   LLVMBuilderRef builder = gallivm->builder;
-   char format[1000];
-   LLVMValueRef args[16];
+   LLVMValueRef params[50];
+   va_list arglist;
+   int argcount;
    int i;
 
-   for (i = 0; i < 16; ++i) {
-      args[i] = LLVMBuildExtractElement(builder, vec, lp_build_const_int32(gallivm, i), "");
-   }
+   argcount = lp_get_printf_arg_count(fmt);
+   assert(Elements(params) >= argcount + 1);
 
-   util_snprintf(format, sizeof(format), "%s %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u %%u\n", msg);
+   va_start(arglist, fmt);
+   for (i = 1; i <= argcount; i++) {
+      params[i] = va_arg(arglist, LLVMValueRef);
+   }
+   va_end(arglist);
 
-   return lp_build_printf(
-            gallivm, format,
-            args[ 0], args[ 1], args[ 2], args[ 3],
-            args[ 4], args[ 5], args[ 6], args[ 7],
-            args[ 8], args[ 9], args[10], args[11],
-            args[12], args[13], args[14], args[15]);
+   params[0] = lp_build_const_string(gallivm, fmt);
+   return lp_build_print_args(gallivm, argcount + 1, params);
 }
index 7a2b26d41f42132db40c9cf1c6f9ac6afabfe3e3..ede93cc834e51a0b97ee539a0d577ede12fcff7d 100644 (file)
@@ -39,16 +39,9 @@ lp_build_printf(struct gallivm_state *gallivm,
                 const char *fmt, ...);
 
 LLVMValueRef
-lp_build_print_vec4(struct gallivm_state *gallivm,
-                    const char *msg, LLVMValueRef vec);
-
-LLVMValueRef
-lp_build_print_ivec4(struct gallivm_state *gallivm,
-                     const char *msg, LLVMValueRef vec);
-
-LLVMValueRef
-lp_build_print_uvec16(struct gallivm_state *gallivm,
-                     const char *msg, LLVMValueRef vec);
+lp_build_print_value(struct gallivm_state *gallivm,
+                     const char *msg,
+                     LLVMValueRef value);
 
 #endif