[pkg-d-commits] [ldc] 34/74: [dcompute] targets & ABIs (#2125)

Matthias Klumpp mak at moszumanska.debian.org
Thu Jul 13 20:54:16 UTC 2017


This is an automated email from the git hooks/post-receive script.

mak pushed a commit to annotated tag v1.3.0-beta2
in repository ldc.

commit efb9c3cef03b2a86ecf61ee9f0ef66322ecfdad1
Author: Nicholas Wilson <thewilsonator at users.noreply.github.com>
Date:   Sun May 21 19:43:55 2017 +0800

    [dcompute] targets & ABIs (#2125)
---
 gen/abi-nvptx.cpp           |  56 ++++++++++++
 gen/abi-nvptx.h             |  21 +++++
 gen/abi-spirv.cpp           |  56 ++++++++++++
 gen/abi-spirv.h             |  22 +++++
 gen/dcompute/abi-rewrites.h |  40 +++++++++
 gen/dcompute/druntime.h     |  13 ++-
 gen/dcompute/target.cpp     |  58 +++++++++++++
 gen/dcompute/target.h       |  58 +++++++++++++
 gen/dcompute/targetCUDA.cpp |  79 +++++++++++++++++
 gen/dcompute/targetOCL.cpp  | 207 ++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 606 insertions(+), 4 deletions(-)

diff --git a/gen/abi-nvptx.cpp b/gen/abi-nvptx.cpp
new file mode 100644
index 0000000..8cb4a3f
--- /dev/null
+++ b/gen/abi-nvptx.cpp
@@ -0,0 +1,56 @@
+//===-- gen/abi-nvptx.cpp ---------------------------------------*- C++ -*-===//
+//
+//                         LDC – the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gen/abi.h"
+#include "gen/dcompute/druntime.h"
+#include "gen/uda.h"
+#include "ddmd/declaration.h"
+#include "gen/tollvm.h"
+#include "gen/dcompute/abi-rewrites.h"
+
+struct NVPTXTargetABI : TargetABI {
+  DComputePointerRewrite pointerRewite;
+  llvm::CallingConv::ID callingConv(llvm::FunctionType *ft, LINK l,
+                                  FuncDeclaration *fdecl = nullptr) override {
+    assert(fdecl);
+    if (hasKernelAttr(fdecl))
+        return llvm::CallingConv::PTX_Kernel;
+    else
+        return llvm::CallingConv::PTX_Device;
+  }
+  bool passByVal(Type *t) override {
+    t = t->toBasetype();
+    return ((t->ty == Tsarray || t->ty == Tstruct) && t->size() > 64);
+  }
+  void rewriteFunctionType(TypeFunction *t, IrFuncTy &fty) override {
+    for (auto arg : fty.args) {
+      if (!arg->byref)
+        rewriteArgument(fty, *arg);
+    }
+  }
+  bool returnInArg(TypeFunction *tf) override {
+    return !tf->isref && DtoIsInMemoryOnly(tf->next);
+  }
+  void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
+    Type *ty = arg.type->toBasetype();
+    llvm::Optional<DcomputePointer> ptr;
+    if (ty->ty == Tstruct &&
+        (ptr = toDcomputePointer(static_cast<TypeStruct*>(ty)->sym)))
+    {
+        arg.rewrite = &pointerRewite;
+        arg.ltype = pointerRewite.type(arg.type);
+    }
+  }
+  // There are no exceptions at all, so no need for unwind tables.
+  bool needsUnwindTables() override {
+    return false;
+  }
+};
+
+TargetABI *createNVPTXABI() { return new NVPTXTargetABI(); }
diff --git a/gen/abi-nvptx.h b/gen/abi-nvptx.h
new file mode 100644
index 0000000..4cb76cd
--- /dev/null
+++ b/gen/abi-nvptx.h
@@ -0,0 +1,21 @@
+//===-- gen/abi-nvptx.h - NVPTX ABI description ----------------*- C++ -*-===//
+//
+//                         LDC - the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The ABI implementation used by dcompute for targetting NVPTX for cuda
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LDC_GEN_ABI_NVPTX_H
+#define LDC_GEN_ABI_NVPTX_H
+
+struct TargetABI;
+
+TargetABI *createNVPTXABI();
+
+#endif
diff --git a/gen/abi-spirv.cpp b/gen/abi-spirv.cpp
new file mode 100644
index 0000000..1e4568e
--- /dev/null
+++ b/gen/abi-spirv.cpp
@@ -0,0 +1,56 @@
+//===-- gen/abi-spirv.cpp ---------------------------------------*- C++ -*-===//
+//
+//                         LDC – the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gen/abi.h"
+#include "gen/dcompute/druntime.h"
+#include "gen/uda.h"
+#include "ddmd/declaration.h"
+#include "gen/tollvm.h"
+#include "gen/dcompute/abi-rewrites.h"
+
+struct SPIRVTargetABI : TargetABI {
+  DComputePointerRewrite pointerRewite;
+  llvm::CallingConv::ID callingConv(llvm::FunctionType *ft, LINK l,
+                                    FuncDeclaration *fdecl = nullptr) override {
+    assert(fdecl);
+    if (hasKernelAttr(fdecl))
+      return llvm::CallingConv::SPIR_KERNEL;
+    else
+      return llvm::CallingConv::SPIR_FUNC;
+  }
+  bool passByVal(Type *t) override {
+    t = t->toBasetype();
+    return ((t->ty == Tsarray || t->ty == Tstruct) && t->size() > 64);
+  }
+  void rewriteFunctionType(TypeFunction *t, IrFuncTy &fty) override {
+    for (auto arg : fty.args) {
+      if (!arg->byref)
+        rewriteArgument(fty, *arg);
+    }
+  }
+  bool returnInArg(TypeFunction *tf) override {
+    return !tf->isref && DtoIsInMemoryOnly(tf->next);
+  }
+  void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
+    Type *ty = arg.type->toBasetype();
+    llvm::Optional<DcomputePointer> ptr;
+    if (ty->ty == Tstruct &&
+        (ptr = toDcomputePointer(static_cast<TypeStruct*>(ty)->sym)))
+    {
+      arg.rewrite = &pointerRewite;
+      arg.ltype = pointerRewite.type(arg.type);
+    }
+  }
+  // There are no exceptions at all, so no need for unwind tables.
+  bool needsUnwindTables() override {
+    return false;
+  }
+};
+
+TargetABI *createSPIRVABI() { return new SPIRVTargetABI(); }
diff --git a/gen/abi-spirv.h b/gen/abi-spirv.h
new file mode 100644
index 0000000..7ee1742
--- /dev/null
+++ b/gen/abi-spirv.h
@@ -0,0 +1,22 @@
+//===-- gen/abi-spirv.h - SPIRV ABI description ----------------*- C++ -*-===//
+//
+//                         LDC - the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The ABI implementation used by dcompute for the SPIR-V targets, only OpenCL
+// at the moment.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LDC_GEN_ABI_SPIRV_H
+#define LDC_GEN_ABI_SPIRV_H
+
+struct TargetABI;
+
+TargetABI *createSPIRVABI();
+
+#endif
diff --git a/gen/dcompute/abi-rewrites.h b/gen/dcompute/abi-rewrites.h
new file mode 100644
index 0000000..ce63db5
--- /dev/null
+++ b/gen/dcompute/abi-rewrites.h
@@ -0,0 +1,40 @@
+//===-- gen/dcompute/abi-rewrites.h - dcompute ABI rewrites -----*- C++ -*-===//
+//
+//                         LDC – the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains ABI rewrites for the dcompute targets SPIR-V and NVPTX
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LDC_GEN_DCOMPUTE_ABI_REWRITES_H
+#define LDC_GEN_DCOMPUTE_ABI_REWRITES_H
+
+#include "gen/abi.h"
+#include "gen/irstate.h"
+#include "gen/llvmhelpers.h"
+#include "gen/logger.h"
+#include "gen/structs.h"
+#include "gen/tollvm.h"
+#include "gen/dcompute/druntime.h"
+
+struct DComputePointerRewrite : ABIRewrite {
+  LLType* type(Type* t) override {
+    auto ptr = toDcomputePointer(static_cast<TypeStruct*>(t)->sym);
+    return ptr->toLLVMType();
+  }
+  LLValue *getLVal(Type *dty, LLValue *v) override {
+    // TODO: Is this correct?
+    return DtoBitCast(v,this->type(dty));
+  }
+  LLValue *put(DValue *dv) override {
+    LLValue *address = getAddressOf(dv);
+    LLType *t = this->type(dv->type);
+    return loadFromMemory(address, t);
+  }
+};
+#endif
diff --git a/gen/dcompute/druntime.h b/gen/dcompute/druntime.h
index c05f2c6..d75aebd 100644
--- a/gen/dcompute/druntime.h
+++ b/gen/dcompute/druntime.h
@@ -14,8 +14,9 @@
 
 #include "ddmd/aggregate.h"
 #include "ddmd/mtype.h"
-
 #include "llvm/ADT/Optional.h"
+#include "gen/llvm.h"
+#include "gen/tollvm.h"
 
 class Dsymbol;
 class Type;
@@ -24,9 +25,13 @@ class Type;
 bool isFromLDC_DCompute(Dsymbol *sym);
 
 struct DcomputePointer {
-    int addrspace;
-    Type* type;
-    DcomputePointer(int as,Type* ty) : addrspace(as),type(ty) {}
+  int addrspace;
+  Type* type;
+  DcomputePointer(int as,Type* ty) : addrspace(as),type(ty) {}
+  LLType *toLLVMType() {
+    auto llType = DtoMemType(type);
+    return llType->getPointerElementType()->getPointerTo(addrspace);
+  }
 };
 llvm::Optional<DcomputePointer> toDcomputePointer(StructDeclaration *sd);
 #endif
diff --git a/gen/dcompute/target.cpp b/gen/dcompute/target.cpp
new file mode 100644
index 0000000..235f5be
--- /dev/null
+++ b/gen/dcompute/target.cpp
@@ -0,0 +1,58 @@
+//===-- gen/dcompute/target.cpp -------------------------------------------===//
+//
+//                         LDC – the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ddmd/dsymbol.h"
+#include "ddmd/module.h"
+#include "ddmd/mars.h"
+#include "ddmd/module.h"
+#include "ddmd/scope.h"
+#include "driver/linker.h"
+#include "driver/toobj.h"
+#include "gen/dcompute/target.h"
+#include "gen/llvmhelpers.h"
+#include "gen/runtime.h"
+#include <string>
+
+void DComputeTarget::doCodeGen(Module *m) {
+
+  // process module members
+  for (unsigned k = 0; k < m->members->dim; k++) {
+    Dsymbol *dsym = (*m->members)[k];
+    assert(dsym);
+    Declaration_codegen(dsym, _ir);
+  }
+
+  if (global.errors)
+    fatal();
+
+}
+
+void DComputeTarget::emit(Module *m) {
+  // Reset the global ABI to the target's ABI. Necessary because we have
+  // multiple ABI we are trying to target. Also reset gIR. These are both
+  // reused. Somewhat of a HACK.
+  gABI = abi;
+  gIR = _ir;
+  doCodeGen(m);
+}
+
+void DComputeTarget::writeModule() {
+  addMetadata();
+
+  char tmp[32];
+  const char *fmt = "kernels_%s%d_%d.%s";
+  int len = sprintf(tmp, fmt, short_name, tversion,
+                    global.params.is64bit ? 64 : 32, binSuffix);
+  tmp[len] = '\0';
+  setGTargetMachine();
+  ::writeModule(&_ir->module, tmp);
+
+  delete _ir;
+  _ir = nullptr;
+}
diff --git a/gen/dcompute/target.h b/gen/dcompute/target.h
new file mode 100644
index 0000000..cc3a197
--- /dev/null
+++ b/gen/dcompute/target.h
@@ -0,0 +1,58 @@
+//===-- gen/dcompute/target.h ------------------------------------*- C++-*-===//
+//
+//                         LDC – the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LDC_GEN_DCOMPUTE_TARGET_H
+#define LDC_GEN_DCOMPUTE_TARGET_H
+#include "gen/irstate.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Function.h"
+#include <array>
+namespace llvm {
+class Module;
+class Function;
+}
+
+class Module;
+class FuncDeclaration;
+
+class DComputeTarget {
+public:
+  enum ID { Host = 0, OpenCL = 1, CUDA = 2 };
+  ID target;    // ID for codegen time conditional compilation.
+  int tversion; // OpenCL or CUDA CC version:major*100 + minor*10
+
+  // The nominal address spaces in DCompute are Private = 0, Global = 1,
+  // Shared = 2, Constant = 3, Generic = 4
+  std::array<int, 5> mapping;
+
+  IRState *_ir;
+  llvm::LLVMContext &ctx;
+  TargetABI *abi;
+  const char *binSuffix;
+  const char *short_name;
+
+  DComputeTarget(llvm::LLVMContext &c, int v, ID id, const char *_short_name,
+                 const char *suffix, TargetABI *a, std::array<int, 5> map)
+    : ctx(c), tversion(v), target(id), short_name(_short_name),
+      binSuffix(suffix), abi(a), mapping(map) { }
+
+  void emit(Module *m);
+  void doCodeGen(Module *m);
+  void writeModule();
+
+  // HACK: Resets the gTargetMachine to one appropriate for this dcompute target
+  virtual void setGTargetMachine() = 0;
+  virtual void addMetadata() = 0;
+  virtual void addKernelMetadata(FuncDeclaration *df, llvm::Function *llf) = 0;
+};
+
+DComputeTarget *createCUDATarget(llvm::LLVMContext &c, int sm);
+DComputeTarget *createOCLTarget(llvm::LLVMContext &c, int oclver);
+
+#endif
diff --git a/gen/dcompute/targetCUDA.cpp b/gen/dcompute/targetCUDA.cpp
new file mode 100644
index 0000000..a1a7794
--- /dev/null
+++ b/gen/dcompute/targetCUDA.cpp
@@ -0,0 +1,79 @@
+//===-- gen/dcompute/targetCUDA.cpp ---------------------------------------===//
+//
+//                         LDC – the LLVM D compiler
+//
+// This file is distributed under the BSD-style LDC license. See the LICENSE
+// file for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gen/dcompute/target.h"
+#include "gen/dcompute/druntime.h"
+#include "gen/metadata.h"
+#include "gen/abi-nvptx.h"
+#include "gen/logger.h"
+#include "gen/optimizer.h"
+#include "llvm/Transforms/Scalar.h"
+#include "driver/targetmachine.h"
+#include <cstring>
+
+namespace {
+class TargetCUDA : public DComputeTarget {
+public:
+  TargetCUDA(llvm::LLVMContext &c, int sm)
+     : DComputeTarget(
+            c, sm, CUDA, "cuda", "ptx", createNVPTXABI(),
+
+            // Map from nominal DCompute address space to NVPTX address space.
+            // see $LLVM_ROOT/docs/docs/NVPTXUsage.rst section Address Spaces
+            {{5, 1, 3, 4, 0}}) {
+    std::string dl = global.params.is64bit ?
+        "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-"
+        "f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" :
+        "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-"
+        "f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64";
+
+    _ir = new IRState("dcomputeTargetCUDA", ctx);
+    _ir->module.setTargetTriple(global.params.is64bit ? "nvptx64-nvidia-cuda"
+                                                      : "nvptx-nvidia-cuda");
+    _ir->module.setDataLayout(dl);
+    _ir->dcomputetarget = this;
+  }
+
+ void addMetadata() override {
+    // sm version?
+  }
+ void setGTargetMachine() override {
+   char buf[8];
+   bool is64 = global.params.is64bit;
+   snprintf(buf, sizeof(buf), "sm_%d", tversion / 10);
+   gTargetMachine = createTargetMachine(
+        is64 ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda",
+        is64 ? "nvptx64" : "nvptx", buf, {},
+        is64 ? ExplicitBitness::M64 : ExplicitBitness::M32, ::FloatABI::Hard,
+        llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(), false,
+        false);
+ }
+
+  void addKernelMetadata(FuncDeclaration *df, llvm::Function *llf) override {
+// Fix 3.5.2 build failures. Remove when dropping 3.5 support.
+#if LDC_LLVM_VER >= 306
+    // TODO: Handle Function attibutes
+    llvm::NamedMDNode *na =
+        _ir->module.getOrInsertNamedMetadata("nvvm.annotations");
+    llvm::Metadata *fn = llvm::ConstantAsMetadata::get(llf);
+    llvm::Metadata *kstr = llvm::MDString::get(ctx, "kernel");
+    llvm::Metadata *one = llvm::ConstantAsMetadata::get(
+        llvm::ConstantInt::get(llvm::IntegerType::get(ctx, 32), 1));
+
+    llvm::Metadata *arr[] = {fn, kstr, one};
+    llvm::MDNode *tup = llvm::MDTuple::get(ctx, arr);
+    na->addOperand(tup);
+#endif
+  }
+};
+} // anonymous namespace.
+
+DComputeTarget *createCUDATarget(llvm::LLVMContext &c, int sm) {
+  return new TargetCUDA(c, sm);
+};
diff --git a/gen/dcompute/targetOCL.cpp b/gen/dcompute/targetOCL.cpp
new file mode 100644
index 0000000..3b65934
--- /dev/null
+++ b/gen/dcompute/targetOCL.cpp
@@ -0,0 +1,207 @@
+//===-- gen/dcomputetargetOCL.cpp -----------------------------------------===//
+//
+//                         LDC – the LLVM D compiler
+//
+// Parts of this file are adapted from CodeGenFunction.cpp (Clang, LLVM).
+// Therefore, this file is distributed under the LLVM license.
+// See the LICENSE file for details.
+//===----------------------------------------------------------------------===//
+
+#include "gen/dcompute/target.h"
+#include "gen/dcompute/druntime.h"
+#include "ddmd/template.h"
+#include "gen/abi-spirv.h"
+#include "gen/logger.h"
+#include "llvm/Transforms/Scalar.h"
+#include "id.h"
+#include <cstring>
+#include <string>
+
+// from SPIRVInternal.h
+#define SPIR_TARGETTRIPLE32 "spir-unknown-unknown"
+#define SPIR_TARGETTRIPLE64 "spir64-unknown-unknown"
+#define SPIR_DATALAYOUT32                                                      \
+  "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32"                             \
+  "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32"                         \
+  "-v32:32:32-v48:64:64-v64:64:64-v96:128:128"                                 \
+  "-v128:128:128-v192:256:256-v256:256:256"                                    \
+  "-v512:512:512-v1024:1024:1024"
+#define SPIR_DATALAYOUT64                                                      \
+  "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32"                             \
+  "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32"                         \
+  "-v32:32:32-v48:64:64-v64:64:64-v96:128:128"                                 \
+  "-v128:128:128-v192:256:256-v256:256:256"                                    \
+  "-v512:512:512-v1024:1024:1024"
+
+namespace {
+class TargetOCL : public DComputeTarget {
+public:
+  TargetOCL(llvm::LLVMContext &c, int oclversion)
+      : DComputeTarget(c, oclversion, OpenCL, "ocl", "spv", createSPIRVABI(),
+                       // Map from nomimal DCompute address space to OpenCL
+                       // address. For OpenCL this is a no-op.
+                       {{0, 1, 2, 3, 4}}) {
+
+    _ir = new IRState("dcomputeTargetOCL", ctx);
+    _ir->module.setTargetTriple(global.params.is64bit ? SPIR_TARGETTRIPLE64
+                                                      : SPIR_TARGETTRIPLE32);
+
+    _ir->module.setDataLayout(global.params.is64bit ? SPIR_DATALAYOUT64
+                                                    : SPIR_DATALAYOUT32);
+    _ir->dcomputetarget = this;
+  }
+  void setGTargetMachine() override { gTargetMachine = nullptr; }
+
+    // Adapted from clang
+  void addMetadata() override {
+    // Fix 3.5.2 build failures. Remove when dropping 3.5 support.
+    // OCL is only supported for 3.6.1 and 3.8 anyway.
+#if LDC_LLVM_VER >= 306
+    // opencl.ident?
+    // spirv.Source // debug only
+    // stuff from clang's CGSPIRMetadataAdder.cpp
+    // opencl.used.extensions
+    // opencl.used.optional.core.features
+    // opencl.compiler.options
+    // opencl.enable.FP_CONTRACT (-ffast-math)
+    llvm::Metadata *SPIRVerElts[] = {
+        llvm::ConstantAsMetadata::get(
+            llvm::ConstantInt::get(llvm::Type::getInt32Ty(ctx), 1)),
+        llvm::ConstantAsMetadata::get(
+            llvm::ConstantInt::get(llvm::Type::getInt32Ty(ctx), 2))};
+    llvm::NamedMDNode *SPIRVerMD =
+      _ir->module.getOrInsertNamedMetadata("opencl.spir.version");
+    SPIRVerMD->addOperand(llvm::MDNode::get(ctx, SPIRVerElts));
+
+    // Add OpenCL version
+    llvm::Metadata *OCLVerElts[] = {
+        llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+            llvm::Type::getInt32Ty(ctx), tversion / 100)),
+        llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+            llvm::Type::getInt32Ty(ctx), (tversion % 100) / 10))};
+    llvm::NamedMDNode *OCLVerMD =
+        _ir->module.getOrInsertNamedMetadata("opencl.ocl.version");
+      
+    OCLVerMD->addOperand(llvm::MDNode::get(ctx, OCLVerElts));
+#endif
+  }
+  enum KernArgMD {
+      KernArgMD_addr_space,
+      KernArgMD_access_qual,
+      KernArgMD_type,
+      KernArgMD_base_type,
+      KernArgMD_type_qual,
+      KernArgMD_name
+  };
+  void addKernelMetadata(FuncDeclaration *fd, llvm::Function *llf) override {
+    // By the time we get here the ABI should have rewritten the function
+    // type so that the magic types in ldc.dcompute are transformed into
+    // what the LLVM backend expects.
+
+    // Fix 3.5.2 build failures. Remove when dropping 3.5 support.
+#if LDC_LLVM_VER >= 306
+
+    // TODO: Handle Function attibutes
+    llvm::SmallVector<llvm::Metadata *, 8> kernelMDArgs;
+    kernelMDArgs.push_back(llvm::ConstantAsMetadata::get(llf));
+    // MDNode for the kernel argument address space qualifiers.
+    llvm::SmallVector<llvm::SmallVector<llvm::Metadata *, 8>,6> paramArgs;
+    llvm::SmallVector<const char*,6> args = {
+      "kernel_arg_addr_space",
+      "kernel_arg_access_qual",
+      "kernel_arg_type",
+      "kernel_arg_type_qual",
+      "kernel_arg_base_type",
+      "kernel_arg_name"
+    };
+      
+    for (auto &str : args) {
+      llvm::SmallVector<llvm::Metadata *, 8> tmp;
+      tmp.push_back(llvm::MDString::get(ctx, str));
+      paramArgs.push_back(tmp);
+    }
+
+    VarDeclarations *vs = fd->parameters;
+    for (unsigned i = 0; i < vs->dim; i++) {
+      VarDeclaration *v = (*vs)[i];
+      decodeTypes(paramArgs,v);
+    }
+  
+    for(auto& md : paramArgs)
+      kernelMDArgs.push_back(llvm::MDNode::get(ctx, md));
+    ///-------------------------------
+    /// TODO: Handle Function attibutes
+    ///-------------------------------
+    llvm::MDNode *kernelMDNode = llvm::MDNode::get(ctx, kernelMDArgs);
+    llvm::NamedMDNode *OpenCLKernelMetadata =
+      _ir->module.getOrInsertNamedMetadata("opencl.kernels");
+    OpenCLKernelMetadata->addOperand(kernelMDNode);
+#endif
+  }
+
+  std::string mod2str(MOD mod) {
+    return mod & (MODconst | MODimmutable) ? "const" : "";
+  }
+
+  std::string basicTypeToString(Type *t) {
+    std::stringstream ss;
+    auto ty = t->ty;
+    if      (ty == Tint8)  ss << "char";
+    else if (ty == Tuns8) ss << "uchar";
+    else if (ty == Tvector) {
+      TypeVector* vec = static_cast<TypeVector*>(t);
+      auto size = vec->size(Loc());
+      auto basety = vec->basetype->ty;
+      if      (basety == Tint8)  ss << "char";
+      else if (basety == Tuns8) ss << "uchar";
+      else ss << vec->basetype->toChars();
+      ss << (int)size;
+    }
+    else
+        ss << t->toChars();
+    return ss.str();
+  }
+
+  void decodeTypes(llvm::SmallVector<
+                        llvm::SmallVector<llvm::Metadata *, 8>,
+                    6>& attrs,
+                   VarDeclaration *v)
+  {
+    llvm::Optional<DcomputePointer> ptr;
+    std::string typeQuals;
+    std::string baseTyName;
+    std::string tyName;
+    std::string accessQual = "none";
+    int addrspace = 0;
+    if (v->type->ty == Tstruct && (ptr = toDcomputePointer(static_cast<TypeStruct*>(v->type)->sym)))
+    {
+      addrspace = ptr->addrspace;
+      tyName = basicTypeToString(ptr->type) + "*";
+      baseTyName = tyName;
+      // there is no volatile or restrict (yet) in D
+      typeQuals = mod2str(ptr->type->mod);
+      // TODO: Images and Pipes They are global pointers to opaques
+    }
+    else
+    {
+      tyName = basicTypeToString(v->type);
+      baseTyName = tyName;
+      typeQuals = mod2str(v->type->mod);
+    }
+#if LDC_LLVM_VER >= 306
+    attrs[KernArgMD_addr_space].push_back( // i32 addrspace
+        llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+            llvm::IntegerType::get(ctx, 32), addrspace)));
+    attrs[KernArgMD_access_qual].push_back(llvm::MDString::get(ctx, accessQual));
+    attrs[KernArgMD_type].push_back(llvm::MDString::get(ctx, tyName));
+    attrs[KernArgMD_base_type].push_back(llvm::MDString::get(ctx, baseTyName));
+    attrs[KernArgMD_type_qual].push_back(llvm::MDString::get(ctx, typeQuals));
+    attrs[KernArgMD_name].push_back(llvm::MDString::get(ctx, v->ident->toChars()));
+#endif
+  }
+};
+} // anonymous namespace.
+
+DComputeTarget *createOCLTarget(llvm::LLVMContext &c, int oclver) {
+  return new TargetOCL(c, oclver);
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git



More information about the pkg-d-commits mailing list