DCompute Metal Backend

Asadbek aosindarov at gmail.com
Sun Aug 16 21:02:00 UTC 2026


Hello everyone,

I wanted to share an update on my progress in adding a Metal GPU 
backend to DCompute.

Over the past few weeks, I’ve been researching how languages with 
mature Metal GPU backends: such as Julia, Mojo, and AdaptiveCpp, 
handle their compilation pipelines. I decided to adopt an 
approach inspired by the Julia compiler's architecture.

For context, the fundamental challenge with targeting Apple Metal 
GPU is that Apple relies on a custom, older fork of LLVM. While 
upstream LLVM supports backward compatibility for *reading* older 
bitcode formats, the LLVM bitcode writer cannot *emit* older 
bitcode versions.

To bypass this limitation, Julia’s maintainers copied an older 
LLVM IR bitcode writer and built an independent utility to 
"downgrade" modern LLVM bitcode into the Apple-compatible format 
(Apple IR / AIR). You can see their utility 
[here](https://github.com/JuliaLLVM/llvm-downgrade).

Their high-level device code compilation pipeline looks like this:
```text
[ Julia Source Code ]
         │
         ▼ (Frontend)
     [ LLVM IR ]
         │
         ▼
[ LLVM IR + Apple-specific Metadata ]
         │
         ▼ (Custom LLVM Downgrader)
[ Metal-Compatible LLVM Bitcode (AIR) ]
```
While Julia doesn't strictly separate host and device code at the 
user level, their lower-level infrastructure still performs two 
distinct compilations, ultimately passing the downgraded device 
binary to the GPU via host buffers

Inspired by Julia's 
[LLVMDowngrader_jll.jl](https://github.com/JuliaBinaryWrappers/LLVMDowngrader_jll.jl), I have created a D alternative: [llvm_downgrader](https://github.com/asindarov/llvm_downgrader).

With that being said, we only need the LDC compiler to generate 
device code with the necessary Apple-specific metadata attached 
(implementation 
[here](https://github.com/asindarov/ldc/blob/metal-backend/gen/dcompute/targetMetal.cpp) in my fork). Once LDC emits this IR, DCompute leverages the new LLVM downgrader to translate it into Apple IR. Finally, we use Apple's `xcrun metallib` linker to package it into a `.metallib` binary ready for execution.

Our final compilation pass for DCompute and LDC looks like this:
```text
[ D Device Code ]
                │
                ▼ (LDC Compiler)
[ LLVM IR + Apple-specific Metadata ]
                │
                ▼ (llvm_downgrader)
[ Apple-compatible LLVM Bitcode (AIR) ]
                │
                ▼ (xcrun metallib)
       [ .metallib Binary ]
```
Link to the linker integration 
[here](https://github.com/asindarov/dcompute/blob/584160a531640fadfb6653b1d4f5c504daf5a9c3/source/dcompute/driver/metal/program.d#L40-L66).

This is now fully functional, and basic kernels are successfully 
executing on Metal GPUs.

Here are the relevant PRs for those interested:

LDC: [#5118](https://github.com/ldc-developers/ldc/pull/5118)
Dcompute: [#99](https://github.com/libmir/dcompute/pull/99)

Thanks again to everyone who has provided feedback so far on the 
PRs! I will keep you updated as I continue to expand the 
functionality.


More information about the Digitalmars-d mailing list