-
-
Notifications
You must be signed in to change notification settings - Fork 283
Initial Metal backend support to dcompute #5118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
805ad58
3420ee8
eb96124
bf0016e
182df17
eae34b9
05c37fc
7fe3396
5906ad4
955b6ec
172eda2
fce3b8e
3615c1b
e98a9c3
13ba222
d6b2612
392acdf
cfb8a02
4c30105
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,7 +38,6 @@ | |
| #include "llvm/Transforms/Utils/Cloning.h" | ||
| #include "llvm/IR/Module.h" | ||
| #include <cstddef> | ||
| #include <fstream> | ||
|
|
||
| namespace llvm { | ||
| namespace codegen { | ||
|
|
@@ -73,6 +72,57 @@ void codegenModule(llvm::TargetMachine &Target, llvm::Module &m, | |
| #endif | ||
| } | ||
|
|
||
| #ifdef LDC_LLVM_SUPPORTED_TARGET_AArch64 | ||
| if (cb == ComputeBackend::METAL) { | ||
| { | ||
| std::error_code errinfo; | ||
| llvm::ToolOutputFile out(filename, errinfo, llvm::sys::fs::OF_None); | ||
| if (errinfo) { | ||
| error(Loc(), "cannot write file '%s': %s", filename, | ||
| errinfo.message().c_str()); | ||
| fatal(); | ||
| } | ||
|
|
||
| llvm::WriteBitcodeToFile(m, out.os()); | ||
|
|
||
| out.keep(); | ||
|
|
||
| // Terminate upon errors during the LLVM passes. | ||
| if (global.errors || global.warnings) { | ||
| Logger::println("Aborting because of errors/warnings during LLVM passes"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be an error not a logger print |
||
| fatal(); | ||
| } | ||
| } | ||
|
|
||
| auto xcrunpath = llvm::sys::findProgramByName("xcrun"); | ||
| if (!xcrunpath) { | ||
| error(Loc(), "xcrun not found - XCode should be installed first!"); | ||
| fatal(); | ||
| } | ||
|
|
||
| llvm::SmallString<256> metallibOutPath; | ||
| llvm::sys::fs::current_path(metallibOutPath); | ||
| llvm::sys::path::append(metallibOutPath, llvm::sys::path::filename(filename)); | ||
| llvm::sys::path::replace_extension(metallibOutPath, "metallib"); | ||
|
|
||
| std::vector<std::string> args = { | ||
| xcrunpath.get(), "-sdk", "macosx", "metallib", filename, "-o", metallibOutPath.c_str() | ||
| }; | ||
|
|
||
| std::string errorMsg; | ||
|
|
||
| int status = executeToolAndWait(Loc(), args[0], args); | ||
|
|
||
| if (status < 0) { | ||
| error(Loc(), "program received signal %d (%s)", -status, | ||
| strsignal(-status)); | ||
| fatal(); | ||
| } | ||
|
|
||
| return; | ||
| } | ||
| #endif | ||
|
|
||
| std::error_code errinfo; | ||
| llvm::ToolOutputFile out(filename, errinfo, llvm::sys::fs::OF_None); | ||
| if (errinfo) { | ||
|
|
@@ -468,5 +518,5 @@ void writeModule(llvm::Module *m, const char *filename) { | |
| if (useIR2ObjCache) { | ||
| cache::cacheObjectFile(filename, moduleHash); | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whitespace |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| //===-- gen/abi-metal.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/abi.h" | ||
| #include "gen/dcompute/druntime.h" | ||
| #include "gen/dcompute/abi-rewrites.h" | ||
| #include "ir/irfuncty.h" | ||
| #include "dmd/mtype.h" | ||
| #include <optional> | ||
|
|
||
| using namespace dmd; | ||
|
|
||
| struct MetalABI : TargetABI { | ||
| DComputePointerRewrite pointerRewite; | ||
| DcomputeMetalScalarRewrite metalScalarRewrite; | ||
|
|
||
| auto returnInArg(TypeFunction *tf, bool needsThis) -> bool override { | ||
| return false; | ||
| } | ||
|
|
||
| auto passByVal(TypeFunction *tf, Type*t) -> bool override { | ||
| return false; | ||
| } | ||
|
|
||
| void rewriteFunctionType(IrFuncTy &fty) override { | ||
| for (auto arg : fty.args) { | ||
| if (!arg->byref) { | ||
| rewriteArgument(fty, *arg); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override { | ||
| TargetABI::rewriteArgument(fty, arg); | ||
|
|
||
| if (arg.rewrite) { | ||
| return; | ||
| } | ||
|
|
||
| Type *ty = arg.type->toBasetype(); | ||
| std::optional<DcomputePointer> ptr; | ||
|
|
||
| if (ty->ty == TY::Tstruct && | ||
| (ptr = toDcomputePointer(static_cast<TypeStruct *>(ty)->sym))) { | ||
| pointerRewite.applyTo(arg); | ||
| } | ||
|
|
||
| if (ty->isScalar()) { | ||
| metalScalarRewrite.applyTo(arg); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| TargetABI* createMetalABI() { return new MetalABI(); } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,3 +32,19 @@ struct DComputePointerRewrite : ABIRewrite { | |
| return ptr->toLLVMType(true); | ||
| } | ||
| }; | ||
|
|
||
| struct DcomputeMetalScalarRewrite : ABIRewrite { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this now unused?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it still used in It is used to make scalar objects turn into a pointer in constant memory address space. Although it turns out scalars can also be stored in device level address space which will be
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. scalar arguments to kernels are just passed as parameters |
||
| LLType *type(Type* t) override { | ||
| // XXX: Scalar variables are stored in the constant memory space for Metal GPU | ||
| return llvm::PointerType::get(gIR->context(), 2/*Constant Memory space*/); | ||
| } | ||
|
|
||
| LLValue *getLVal(Type *dty, LLValue *v) override { | ||
| return v; | ||
| } | ||
|
|
||
| LLValue *put(DValue *v, bool isLValueExp, bool) override { | ||
| auto value = DtoRVal(v); | ||
| return value; | ||
| } | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems unused