[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