clover: Factor kernel argument parsing into its own function v2

v2:
  - Code cleanups.

Reviewed-by: Francisco Jerez <currojerez@riseup.net>
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index 212b4e4..41f1d6a 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -293,6 +293,105 @@
       PM.run(*mod);
    }
 
+   compat::vector<module::argument>
+   get_kernel_args(const llvm::Module *mod, const std::string &kernel_name,
+                   const clang::LangAS::Map &address_spaces) {
+
+      compat::vector<module::argument> args;
+      llvm::Function *kernel_func = mod->getFunction(kernel_name);
+
+#if HAVE_LLVM < 0x0302
+         llvm::TargetData TD(kernel_func->getParent());
+#elif HAVE_LLVM < 0x0305
+         llvm::DataLayout TD(kernel_func->getParent()->getDataLayout());
+#else
+         llvm::DataLayout TD(mod);
+#endif
+
+      for (llvm::Function::const_arg_iterator I = kernel_func->arg_begin(),
+                                      E = kernel_func->arg_end(); I != E; ++I) {
+         const llvm::Argument &arg = *I;
+
+         llvm::Type *arg_type = arg.getType();
+         const unsigned arg_store_size = TD.getTypeStoreSize(arg_type);
+
+         // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data
+         // type that is not a power of two bytes in size must be
+         // aligned to the next larger power of two".  We need this
+         // alignment for three element vectors, which have
+         // non-power-of-2 store size.
+         const unsigned arg_api_size = util_next_power_of_two(arg_store_size);
+
+         llvm::Type *target_type = arg_type->isIntegerTy() ?
+               TD.getSmallestLegalIntType(mod->getContext(), arg_store_size * 8)
+               : arg_type;
+         unsigned target_size = TD.getTypeStoreSize(target_type);
+         unsigned target_align = TD.getABITypeAlignment(target_type);
+
+         if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) {
+            arg_type =
+                  llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType();
+         }
+
+         if (arg_type->isPointerTy()) {
+            unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace();
+            if (address_space == address_spaces[clang::LangAS::opencl_local
+                                                     - clang::LangAS::Offset]) {
+               args.push_back(module::argument(module::argument::local,
+                                               arg_api_size, target_size,
+                                               target_align,
+                                               module::argument::zero_ext));
+            } else {
+               // XXX: Correctly handle constant address space.  There is no
+               // way for r600g to pass a handle for constant buffers back
+               // to clover like it can for global buffers, so
+               // creating constant arguments will break r600g.  For now,
+               // continue treating constant buffers as global buffers
+               // until we can come up with a way to create handles for
+               // constant buffers.
+               args.push_back(module::argument(module::argument::global,
+                                               arg_api_size, target_size,
+                                               target_align,
+                                               module::argument::zero_ext));
+           }
+
+         } else {
+            llvm::AttributeSet attrs = kernel_func->getAttributes();
+            enum module::argument::ext_type ext_type =
+                  (attrs.hasAttribute(arg.getArgNo() + 1,
+                                     llvm::Attribute::SExt) ?
+                   module::argument::sign_ext :
+                   module::argument::zero_ext);
+
+            args.push_back(
+               module::argument(module::argument::scalar, arg_api_size,
+                                target_size, target_align, ext_type));
+         }
+      }
+
+      // Append implicit arguments.  XXX - The types, ordering and
+      // vector size of the implicit arguments should depend on the
+      // target according to the selected calling convention.
+      llvm::Type *size_type =
+         TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_uint) * 8);
+
+      args.push_back(
+         module::argument(module::argument::scalar, sizeof(cl_uint),
+                          TD.getTypeStoreSize(size_type),
+                          TD.getABITypeAlignment(size_type),
+                          module::argument::zero_ext,
+                          module::argument::grid_dimension));
+
+      args.push_back(
+         module::argument(module::argument::scalar, sizeof(cl_uint),
+                          TD.getTypeStoreSize(size_type),
+                          TD.getABITypeAlignment(size_type),
+                          module::argument::zero_ext,
+                          module::argument::grid_offset));
+
+      return args;
+   }
+
    module
    build_module_llvm(llvm::Module *mod,
                      const std::vector<llvm::Function *> &kernels,
@@ -308,97 +407,9 @@
       bitcode_ostream.flush();
 
       for (unsigned i = 0; i < kernels.size(); ++i) {
-         llvm::Function *kernel_func = kernels[i];
-         const std::string kernel_name = kernel_func->getName();
-#if HAVE_LLVM < 0x0302
-         llvm::TargetData TD(kernel_func->getParent());
-#elif HAVE_LLVM < 0x0305
-         llvm::DataLayout TD(kernel_func->getParent()->getDataLayout());
-#else
-         llvm::DataLayout TD(mod);
-#endif
-         compat::vector<module::argument> args;
-
-         for (llvm::Function::arg_iterator I = kernel_func->arg_begin(),
-                                      E = kernel_func->arg_end(); I != E; ++I) {
-            llvm::Argument &arg = *I;
-            llvm::Type *arg_type = arg.getType();
-            const unsigned arg_store_size = TD.getTypeStoreSize(arg_type);
-
-            // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data
-            // type that is not a power of two bytes in size must be
-            // aligned to the next larger power of two".  We need this
-            // alignment for three element vectors, which have
-            // non-power-of-2 store size.
-            const unsigned arg_api_size =
-               util_next_power_of_two(arg_store_size);
-
-            llvm::Type *target_type = arg_type->isIntegerTy() ?
-               TD.getSmallestLegalIntType(mod->getContext(), arg_store_size * 8)
-               : arg_type;
-            unsigned target_size = TD.getTypeStoreSize(target_type);
-            unsigned target_align = TD.getABITypeAlignment(target_type);
-
-            if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) {
-               arg_type =
-                  llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType();
-            }
-
-            if (arg_type->isPointerTy()) {
-               unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace();
-               if (address_space == address_spaces[clang::LangAS::opencl_local
-                                                     - clang::LangAS::Offset]) {
-                  args.push_back(module::argument(module::argument::local,
-                                                  arg_api_size, target_size,
-                                                  target_align,
-                                                  module::argument::zero_ext));
-               } else {
-                  // XXX: Correctly handle constant address space.  There is no
-                  // way for r600g to pass a handle for constant buffers back
-                  // to clover like it can for global buffers, so
-                  // creating constant arguments will break r600g.  For now,
-                  // continue treating constant buffers as global buffers
-                  // until we can come up with a way to create handles for
-                  // constant buffers.
-                  args.push_back(module::argument(module::argument::global,
-                                                  arg_api_size, target_size,
-                                                  target_align,
-                                                  module::argument::zero_ext));
-              }
-
-            } else {
-               llvm::AttributeSet attrs = kernel_func->getAttributes();
-               enum module::argument::ext_type ext_type =
-                  (attrs.hasAttribute(arg.getArgNo() + 1,
-                                     llvm::Attribute::SExt) ?
-                   module::argument::sign_ext :
-                   module::argument::zero_ext);
-
-               args.push_back(
-                  module::argument(module::argument::scalar, arg_api_size,
-                                   target_size, target_align, ext_type));
-            }
-         }
-
-         // Append implicit arguments.  XXX - The types, ordering and
-         // vector size of the implicit arguments should depend on the
-         // target according to the selected calling convention.
-         llvm::Type *size_type =
-            TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_uint) * 8);
-
-         args.push_back(
-            module::argument(module::argument::scalar, sizeof(cl_uint),
-                             TD.getTypeStoreSize(size_type),
-                             TD.getABITypeAlignment(size_type),
-                             module::argument::zero_ext,
-                             module::argument::grid_dimension));
-
-         args.push_back(
-            module::argument(module::argument::scalar, sizeof(cl_uint),
-                             TD.getTypeStoreSize(size_type),
-                             TD.getABITypeAlignment(size_type),
-                             module::argument::zero_ext,
-                             module::argument::grid_offset));
+         std::string kernel_name = kernels[i]->getName();
+         compat::vector<module::argument> args =
+               get_kernel_args(mod, kernel_name, address_spaces);
 
          m.syms.push_back(module::symbol(kernel_name, 0, i, args ));
       }