Automate pod arg implementation decision (#575)

Contributes to #529

* Decision made on a per-kernel basis
* New pass assigns metadata to kernels
  * passes use that metadata through new utliities to get the right
  ArgKinds
  * currently only decides based on command line options (so NFC)
* Refactored layout validation into new files
* Refactored some global push constant methods
* new enum for how pod args are implemented
  * kGlobalPushConstant will be implemented in the future
* added new metadata to test that required it
* changed arg kind utility to take the arg instead of just the type
* Priorities per-kernel push constants then ubo then ssbo
  * checks for compatibility
* Added new variant of isValidExplicitLayout that checks the whole
struct
diff --git a/lib/ClusterPodKernelArgumentsPass.cpp b/lib/ClusterPodKernelArgumentsPass.cpp
index 04d24b4..3c272b9 100644
--- a/lib/ClusterPodKernelArgumentsPass.cpp
+++ b/lib/ClusterPodKernelArgumentsPass.cpp
@@ -43,6 +43,7 @@
 #include "clspv/Option.h"
 
 #include "ArgKind.h"
+#include "Constants.h"
 #include "Passes.h"
 
 using namespace llvm;
@@ -96,6 +97,8 @@
   for (Function *F : WorkList) {
     Changed = true;
 
+    auto pod_arg_impl = clspv::GetPodArgsImpl(*F);
+    auto pod_arg_kind = clspv::GetArgKindForPodArgs(*F);
     // An ArgMapping describes how a kernel argument is remapped.
     struct ArgMapping {
       std::string name;
@@ -131,7 +134,7 @@
       Type *ArgTy = Arg.getType();
       if (isa<PointerType>(ArgTy)) {
         PtrArgTys.push_back(ArgTy);
-        const auto kind = clspv::GetArgKindForType(ArgTy);
+        const auto kind = clspv::GetArgKind(Arg);
         int spec_id = -1;
         if (kind == clspv::ArgKind::Local) {
           spec_id = arg_spec_id_map[&Arg];
@@ -151,7 +154,7 @@
     auto PodArgsStructTy = StructType::get(Context, PodArgTys);
     SmallVector<Type *, 8> NewFuncParamTys(PtrArgTys);
 
-    if (clspv::Option::PodArgsInUniformBuffer() &&
+    if (pod_arg_impl == clspv::PodArgImpl::kUBO &&
         !clspv::Option::Std430UniformBufferLayout()) {
       SmallVector<Type *, 16> PaddedPodArgTys;
       const DataLayout DL(&M);
@@ -206,7 +209,7 @@
           RemapInfo.push_back(
               {std::string(Arg.getName()), arg_index, new_index,
                unsigned(StructLayout->getElementOffset(PodIndexMap[&Arg])),
-               arg_size, clspv::GetArgKindForType(ArgTy), -1});
+               arg_size, pod_arg_kind, -1});
         }
         arg_index++;
       }
@@ -261,10 +264,12 @@
     // Move OpenCL kernel named attributes.
     // TODO(dneto): Attributes starting with kernel_arg_* should be rewritten
     // to reflect change in the argument shape.
+    auto pod_md_name = clspv::PodArgsImplMetadataName();
     std::vector<const char *> Metadatas{
         "reqd_work_group_size",   "kernel_arg_addr_space",
         "kernel_arg_access_qual", "kernel_arg_type",
-        "kernel_arg_base_type",   "kernel_arg_type_qual"};
+        "kernel_arg_base_type",   "kernel_arg_type_qual",
+        pod_md_name.c_str()};
     for (auto name : Metadatas) {
       NewFunc->setMetadata(name, F->getMetadata(name));
       F->setMetadata(name, nullptr);