From deaa55e7945bad9a0435ce67ad42f59187ee3595 Mon Sep 17 00:00:00 2001
From: Maria Kotsifakou <kotsifa2@illinois.edu>
Date: Wed, 5 Nov 2014 07:06:45 +0000
Subject: [PATCH] Adding OpenCL metadata. They are not entirely similar to
 those we have observed. They contain the same information, but in a different
 setting. We still need to see if the nvptx backend will accept this format.

---
 .../DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp         | 88 ++++++++++++++++++-
 1 file changed, 85 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp b/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp
index 1526989e82..0883500362 100644
--- a/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp
+++ b/llvm/lib/Transforms/DFG2LLVM_NVPTX/DFG2LLVM_NVPTX.cpp
@@ -9,10 +9,12 @@
 
 #define ENABLE_ASSERTS
 #define TARGET_PTX 32
+#define GENERIC_ADDRSPACE 0
 #define GLOBAL_ADDRSPACE 1
 
 #define DEBUG_TYPE "DFG2LLVM_NVPTX"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/InstIterator.h"
@@ -36,6 +38,7 @@ namespace {
 // Helper function declarations
   void changeDataLayout(Module &);
   void changeTargetTriple(Module &);
+  std::string printType(Type*);
   std::string convertInt(int);
   void findReturnInst(Function *, std::vector<ReturnInst *> &);
 
@@ -909,13 +912,84 @@ namespace {
     DEBUG(errs() << *F->getFunctionType() << "\n" <<*F << "\n");
   }
 
-  void CodeGenTraversal::addCLMetadata(Function* F) {
+  /* Add metadata to module KernelM, for OpenCL kernels */
+  void CodeGenTraversal::addCLMetadata(Function *F) {
+
+    IRBuilder<true> Builder(F->begin());
+
+    SmallVector<Value*,8> KernelMD;
+    KernelMD.push_back(F);
+
+    // MDNode for the kernel argument address space qualifiers.
+    SmallVector<llvm::Value*, 8> addressQuals;
+    addressQuals.push_back(MDString::get(KernelM.getContext(), "kernel_arg_addr_space"));
+
+    // We don't support images
+    // MDNode for the kernel argument access qualifiers (images only).
+//    SmallVector<llvm::Value*, 8> accessQuals;
+//    accessQuals.push_back(MDString::get(KernelM.getContext(), "kernel_arg_access_qual"));
+
+    // MDNode for the kernel argument type names.
+    SmallVector<llvm::Value*, 8> argTypeNames;
+    argTypeNames.push_back(MDString::get(KernelM.getContext(), "kernel_arg_type"));
+
+    //TODO: MDNode for the kernel argument type qualifiers.
+//    SmallVector<llvm::Value*, 8> argTypeQuals;
+//    argTypeQuals.push_back(MDString::get(KernelM.getContext(), "kernel_arg_type_qual"));
+
+    // MDNode for the kernel argument names.
+    SmallVector<llvm::Value*, 8> argNames;
+    argNames.push_back(MDString::get(KernelM.getContext(), "kernel_arg_name"));
+
+    for (Function::arg_iterator ai = F->arg_begin(),
+                                  ae = F->arg_end(); ai != ae; ++ai) {
+      Argument *arg = &*ai;
+      Type *argTy = arg->getType();
+
+      if (argTy->isPointerTy()) {
+        Type *pointeeTy = argTy->getPointerElementType();
+        std::string typeName = printType(pointeeTy) + "*";
+        // Get argument type name.
+        argTypeNames.push_back(MDString::get(KernelM.getContext(), typeName));
+
+        // Get address qualifier.
+        addressQuals.push_back(Builder.getInt32(argTy->getPointerAddressSpace()));
+      } else {
+        std::string typeName = printType(argTy);
+        // Get argument type name.
+        argTypeNames.push_back(MDString::get(KernelM.getContext(), typeName));
+
+        // Get address qualifier.
+        addressQuals.push_back(Builder.getInt32(GENERIC_ADDRSPACE));
+
+      }
+
+      // Get argument name.
+      argNames.push_back(MDString::get(KernelM.getContext(), arg->getName()));
+    }
+
+    KernelMD.push_back(MDNode::get(KernelM.getContext(), addressQuals));
+//    KernelMD.push_back(MDNode::get(KernelM.getContext(), accessQuals));
+    KernelMD.push_back(MDNode::get(KernelM.getContext(), argTypeNames));
+//    KernelMD.push_back(MDNode::get(KernelM.getContext(), argTypeQuals));
+    KernelMD.push_back(MDNode::get(KernelM.getContext(), argNames));
+
+    MDNode *MDKernelNode = MDNode::get(KernelM.getContext(), KernelMD);
+    NamedMDNode *MDN_kernels = KernelM.getOrInsertNamedMetadata("opencl.kernels");
+    MDN_kernels->addOperand(MDKernelNode);
+
+    KernelMD.push_back(MDNode::get(KernelM.getContext(),
+                       MDString::get(KernelM.getContext(), "kernel")));
+
+    MDNode *MDNvvmAnnotationsNode = MDNode::get(KernelM.getContext(), KernelMD);
+    NamedMDNode *MDN_annotations = KernelM.getOrInsertNamedMetadata("nvvm.annotations");
+    MDN_annotations->addOperand(MDNvvmAnnotationsNode);
+
+//!1 = metadata !{void (float addrspace(1)*, float addrspace(1)*, float addrspace(1)*, i32, i32)* @matrixMul, metadata !"kernel", i32 1}
   }
 
   void CodeGenTraversal::writeKernelsModule() {
 
-    //TODO: Add metadata
-
     char* ErrorMessage = NULL;
     LLVMModuleRef KernelMRef = wrap(&KernelM);
     errs() << "Writing to File --- ";
@@ -1046,6 +1120,14 @@ namespace {
     return;
   }
 
+// Helper function, generate a string representation of a type
+  std::string printType(Type* ty) {
+    std::string type_str;
+    raw_string_ostream rso(type_str);
+    ty->print(rso);
+    return rso.str();
+  }
+
 // Helper function, convert int to string
   std::string convertInt(int number) {
    std::stringstream ss;//create a stringstream
-- 
GitLab