1//===- DirectXTargetMachine.cpp - DirectX Target Implementation -*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file contains DirectX target initializer.
11///
12//===----------------------------------------------------------------------===//
13
14#include "DirectXTargetMachine.h"
15#include "DXILCBufferAccess.h"
16#include "DXILDataScalarization.h"
17#include "DXILFinalizeLinkage.h"
18#include "DXILFlattenArrays.h"
19#include "DXILForwardHandleAccesses.h"
20#include "DXILIntrinsicExpansion.h"
21#include "DXILLegalizePass.h"
22#include "DXILMemIntrinsics.h"
23#include "DXILOpLowering.h"
24#include "DXILPostOptimizationValidation.h"
25#include "DXILPrettyPrinter.h"
26#include "DXILRemoveUnusedResources.h"
27#include "DXILResourceAccess.h"
28#include "DXILResourceImplicitBinding.h"
29#include "DXILRootSignature.h"
30#include "DXILShaderFlags.h"
31#include "DXILTranslateMetadata.h"
32#include "DXILWriter/DXILWriterPass.h"
33#include "DirectX.h"
34#include "DirectXIRPasses/DXILDebugInfo.h"
35#include "DirectXSubtarget.h"
36#include "DirectXTargetTransformInfo.h"
37#include "TargetInfo/DirectXTargetInfo.h"
38#include "llvm/Analysis/TargetTransformInfo.h"
39#include "llvm/CodeGen/MachineModuleInfo.h"
40#include "llvm/CodeGen/Passes.h"
41#include "llvm/CodeGen/TargetPassConfig.h"
42#include "llvm/IR/IRPrintingPasses.h"
43#include "llvm/IR/LegacyPassManager.h"
44#include "llvm/InitializePasses.h"
45#include "llvm/MC/MCSectionDXContainer.h"
46#include "llvm/MC/SectionKind.h"
47#include "llvm/MC/TargetRegistry.h"
48#include "llvm/Passes/PassBuilder.h"
49#include "llvm/Support/CodeGen.h"
50#include "llvm/Support/Compiler.h"
51#include "llvm/Support/ErrorHandling.h"
52#include "llvm/Support/VersionTuple.h"
53#include "llvm/Target/TargetLoweringObjectFile.h"
54#include "llvm/Transforms/IPO/GlobalDCE.h"
55#include "llvm/Transforms/Scalar.h"
56#include "llvm/Transforms/Scalar/Scalarizer.h"
57#include "llvm/Transforms/Utils.h"
58#include <optional>
59
60using namespace llvm;
61
62extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
63LLVMInitializeDirectXTarget() {
64 RegisterTargetMachine<DirectXTargetMachine> X(getTheDirectXTarget());
65 auto *PR = PassRegistry::getPassRegistry();
66 initializeDXILDebugInfoLegacyPass(*PR);
67 initializeDXILIntrinsicExpansionLegacyPass(*PR);
68 initializeDXILMemIntrinsicsLegacyPass(*PR);
69 initializeDXILDataScalarizationLegacyPass(*PR);
70 initializeDXILFlattenArraysLegacyPass(*PR);
71 initializeScalarizerLegacyPassPass(*PR);
72 initializeDXILLegalizeLegacyPass(*PR);
73 initializeDXILPrepareModulePass(*PR);
74 initializeEmbedDXILPassPass(*PR);
75 initializeWriteDXILPassPass(*PR);
76 initializeDXContainerGlobalsPass(*PR);
77 initializeDXContainerPDBPass(*PR);
78 initializeGlobalDCELegacyPassPass(*PR);
79 initializeDXILOpLoweringLegacyPass(*PR);
80 initializeDXILRemoveUnusedResourcesLegacyPass(*PR);
81 initializeDXILResourceAccessLegacyPass(*PR);
82 initializeDXILResourceImplicitBindingLegacyPass(*PR);
83 initializeDXILTranslateMetadataLegacyPass(*PR);
84 initializeDXILPostOptimizationValidationLegacyPass(*PR);
85 initializeShaderFlagsAnalysisWrapperPass(*PR);
86 initializeRootSignatureAnalysisWrapperPass(*PR);
87 initializeDXILFinalizeLinkageLegacyPass(*PR);
88 initializeDXILPrettyPrinterLegacyPass(*PR);
89 initializeDXILForwardHandleAccessesLegacyPass(*PR);
90 initializeDSELegacyPassPass(*PR);
91 initializeDXILCBufferAccessLegacyPass(*PR);
92 initializeStripConvergenceIntrinsicsLegacyPassPass(*PR);
93}
94
95class DXILTargetObjectFile : public TargetLoweringObjectFile {
96public:
97 DXILTargetObjectFile() = default;
98
99 MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
100 const TargetMachine &TM) const override {
101 return getContext().getDXContainerSection(Section: GO->getSection(), K: Kind);
102 }
103
104protected:
105 MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
106 const TargetMachine &TM) const override {
107 llvm_unreachable("Not supported!");
108 }
109};
110
111class DirectXPassConfig : public TargetPassConfig {
112public:
113 DirectXPassConfig(DirectXTargetMachine &TM, PassManagerBase &PM)
114 : TargetPassConfig(TM, PM) {}
115
116 DirectXTargetMachine &getDirectXTargetMachine() const {
117 return getTM<DirectXTargetMachine>();
118 }
119
120 FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; }
121 void addCodeGenPrepare() override {
122 CodeGenOptLevel OptLevel = getDirectXTargetMachine().getOptLevel();
123
124 addPass(P: createStripConvergenceIntrinsicsPass());
125 addPass(P: createDXILFinalizeLinkageLegacyPass());
126 if (OptLevel != CodeGenOptLevel::None) {
127 addPass(P: createGlobalDCEPass());
128 }
129 addPass(P: createDXILMemIntrinsicsLegacyPass());
130 addPass(P: createDXILCBufferAccessLegacyPass());
131 addPass(P: createDXILRemoveUnusedResourcesLegacyPass());
132 addPass(P: createDXILResourceAccessLegacyPass());
133 addPass(P: createDXILIntrinsicExpansionLegacyPass());
134 addPass(P: createDXILDataScalarizationLegacyPass());
135 if (getDirectXTargetMachine().getTargetTriple().getOSVersion() <
136 VersionTuple(6, 9)) {
137 ScalarizerPassOptions DxilScalarOptions;
138 DxilScalarOptions.ScalarizeLoadStore = true;
139 addPass(P: createScalarizerPass(Options: DxilScalarOptions));
140 }
141 addPass(P: createDXILFlattenArraysLegacyPass());
142 addPass(P: createDXILForwardHandleAccessesLegacyPass());
143 if (OptLevel != CodeGenOptLevel::None) {
144 addPass(P: createDeadStoreEliminationPass());
145 }
146 addPass(P: createDXILLegalizeLegacyPass());
147 addPass(P: createDXILResourceImplicitBindingLegacyPass());
148 addPass(P: createDXILTranslateMetadataLegacyPass());
149 addPass(P: createDXILPostOptimizationValidationLegacyPass());
150 addPass(P: createDXILOpLoweringLegacyPass());
151 addPass(P: createDXILPrepareModulePass());
152 addPass(P: createDXILDebugInfoLegacyPass());
153 }
154};
155
156DirectXTargetMachine::DirectXTargetMachine(const Target &T, const Triple &TT,
157 StringRef CPU, StringRef FS,
158 const TargetOptions &Options,
159 std::optional<Reloc::Model> RM,
160 std::optional<CodeModel::Model> CM,
161 CodeGenOptLevel OL, bool JIT)
162 : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
163 Reloc::Static, CodeModel::Small, OL),
164 TLOF(std::make_unique<DXILTargetObjectFile>()),
165 Subtarget(std::make_unique<DirectXSubtarget>(args: TT, args&: CPU, args&: FS, args&: *this)) {
166 initAsmInfo();
167}
168
169DirectXTargetMachine::~DirectXTargetMachine() {}
170
171void DirectXTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
172#define GET_PASS_REGISTRY "DirectXPassRegistry.def"
173#include "llvm/Passes/TargetPassRegistry.inc"
174}
175
176bool DirectXTargetMachine::addPassesToEmitFile(
177 PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
178 CodeGenFileType FileType, bool DisableVerify,
179 MachineModuleInfoWrapperPass *MMIWP) {
180 TargetPassConfig *PassConfig = createPassConfig(PM);
181 PM.add(P: PassConfig);
182
183 if (!MMIWP)
184 MMIWP = new MachineModuleInfoWrapperPass(this);
185 PM.add(P: MMIWP);
186
187 PM.add(P: createTargetTransformInfoWrapperPass(TIRA: getTargetIRAnalysis()));
188 PassConfig->addCodeGenPrepare();
189
190 switch (FileType) {
191 case CodeGenFileType::AssemblyFile:
192 PM.add(P: createDXILPrettyPrinterLegacyPass(OS&: Out));
193 break;
194 case CodeGenFileType::ObjectFile:
195 if (TargetPassConfig::willCompleteCodeGenPipeline()) {
196 PM.add(P: createDXILEmbedderPass());
197 // We embed the other DXContainer globals after embedding DXIL so that the
198 // globals don't pollute the DXIL.
199 PM.add(P: createDXContainerGlobalsPass());
200 PM.add(P: createDXContainerPDBPass());
201
202 if (addAsmPrinter(PM, Out, DwoOut, FileType,
203 Context&: MMIWP->getMMI().getContext()))
204 return true;
205 } else
206 PM.add(P: createDXILWriterPass(Str&: Out));
207 break;
208 case CodeGenFileType::Null:
209 break;
210 }
211 return false;
212}
213
214bool DirectXTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
215 MCContext *&Ctx,
216 raw_pwrite_stream &Out,
217 bool DisableVerify) {
218 return true;
219}
220
221TargetPassConfig *DirectXTargetMachine::createPassConfig(PassManagerBase &PM) {
222 return new DirectXPassConfig(*this, PM);
223}
224
225const DirectXSubtarget *
226DirectXTargetMachine::getSubtargetImpl(const Function &) const {
227 return Subtarget.get();
228}
229
230TargetTransformInfo
231DirectXTargetMachine::getTargetTransformInfo(const Function &F) const {
232 return TargetTransformInfo(std::make_unique<DirectXTTIImpl>(args: this, args: F));
233}
234
235DirectXTargetLowering::DirectXTargetLowering(const DirectXTargetMachine &TM,
236 const DirectXSubtarget &STI)
237 : TargetLowering(TM, STI) {
238 addRegisterClass(VT: MVT::i32, RC: &dxil::DXILClassRegClass);
239 computeRegisterProperties(TRI: STI.getRegisterInfo());
240}
241