1 //===- Target.cpp - MLIR SPIR-V target compilation --------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This files defines SPIR-V target related functions including registration
10 // calls for the `#spirv.target_env` compilation attribute.
12 //===----------------------------------------------------------------------===//
14 #include "mlir/Target/SPIRV/Target.h"
16 #include "mlir/Dialect/GPU/IR/GPUDialect.h"
17 #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
18 #include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h"
19 #include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
20 #include "mlir/Target/SPIRV/Serialization.h"
26 using namespace mlir::spirv
;
29 // SPIR-V implementation of the gpu:TargetAttrInterface.
30 class SPIRVTargetAttrImpl
31 : public gpu::TargetAttrInterface::FallbackModel
<SPIRVTargetAttrImpl
> {
33 std::optional
<SmallVector
<char, 0>>
34 serializeToObject(Attribute attribute
, Operation
*module
,
35 const gpu::TargetOptions
&options
) const;
37 Attribute
createObject(Attribute attribute
,
38 const SmallVector
<char, 0> &object
,
39 const gpu::TargetOptions
&options
) const;
43 // Register the SPIR-V dialect, the SPIR-V translation & the target interface.
44 void mlir::spirv::registerSPIRVTargetInterfaceExternalModels(
45 DialectRegistry
®istry
) {
46 registry
.addExtension(+[](MLIRContext
*ctx
, spirv::SPIRVDialect
*dialect
) {
47 spirv::TargetEnvAttr::attachInterface
<SPIRVTargetAttrImpl
>(*ctx
);
51 void mlir::spirv::registerSPIRVTargetInterfaceExternalModels(
52 MLIRContext
&context
) {
53 DialectRegistry registry
;
54 registerSPIRVTargetInterfaceExternalModels(registry
);
55 context
.appendDialectRegistry(registry
);
58 // Reuse from existing serializer
59 std::optional
<SmallVector
<char, 0>> SPIRVTargetAttrImpl::serializeToObject(
60 Attribute attribute
, Operation
*module
,
61 const gpu::TargetOptions
&options
) const {
64 auto gpuMod
= dyn_cast
<gpu::GPUModuleOp
>(module
);
66 module
->emitError("expected to be a gpu.module op");
69 auto spvMods
= gpuMod
.getOps
<spirv::ModuleOp
>();
73 auto spvMod
= *spvMods
.begin();
74 llvm::SmallVector
<uint32_t, 0> spvBinary
;
77 // Serialize the spirv.module op to SPIR-V blob.
78 if (mlir::failed(spirv::serialize(spvMod
, spvBinary
))) {
79 spvMod
.emitError() << "failed to serialize SPIR-V module";
83 SmallVector
<char, 0> spvData(spvBinary
.size() * sizeof(uint32_t), 0);
84 std::memcpy(spvData
.data(), spvBinary
.data(), spvData
.size());
90 // Prepare Attribute for gpu.binary with serialized kernel object
92 SPIRVTargetAttrImpl::createObject(Attribute attribute
,
93 const SmallVector
<char, 0> &object
,
94 const gpu::TargetOptions
&options
) const {
95 gpu::CompilationTarget format
= options
.getCompilationTarget();
96 DictionaryAttr objectProps
;
97 Builder
builder(attribute
.getContext());
98 return builder
.getAttr
<gpu::ObjectAttr
>(
100 builder
.getStringAttr(StringRef(object
.data(), object
.size())),