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 "DXILResourceAnalysis.h"
16 #include "DXILShaderFlags.h"
17 #include "DXILWriter/DXILWriterPass.h"
18 #include "DirectX.h"
19 #include "DirectXSubtarget.h"
20 #include "DirectXTargetTransformInfo.h"
21 #include "TargetInfo/DirectXTargetInfo.h"
22 #include "llvm/CodeGen/MachineModuleInfo.h"
23 #include "llvm/CodeGen/Passes.h"
24 #include "llvm/CodeGen/TargetPassConfig.h"
25 #include "llvm/IR/IRPrintingPasses.h"
26 #include "llvm/IR/LegacyPassManager.h"
27 #include "llvm/MC/MCSectionDXContainer.h"
28 #include "llvm/MC/SectionKind.h"
29 #include "llvm/MC/TargetRegistry.h"
30 #include "llvm/Passes/PassBuilder.h"
31 #include "llvm/Support/CodeGen.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Target/TargetLoweringObjectFile.h"
35 #include <optional>
36
37 using namespace llvm;
38
LLVMInitializeDirectXTarget()39 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() {
40 RegisterTargetMachine<DirectXTargetMachine> X(getTheDirectXTarget());
41 auto *PR = PassRegistry::getPassRegistry();
42 initializeDXILPrepareModulePass(*PR);
43 initializeEmbedDXILPassPass(*PR);
44 initializeWriteDXILPassPass(*PR);
45 initializeDXContainerGlobalsPass(*PR);
46 initializeDXILOpLoweringLegacyPass(*PR);
47 initializeDXILTranslateMetadataPass(*PR);
48 initializeDXILResourceWrapperPass(*PR);
49 initializeShaderFlagsAnalysisWrapperPass(*PR);
50 }
51
52 class DXILTargetObjectFile : public TargetLoweringObjectFile {
53 public:
54 DXILTargetObjectFile() = default;
55
getExplicitSectionGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const56 MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
57 const TargetMachine &TM) const override {
58 return getContext().getDXContainerSection(GO->getSection(), Kind);
59 }
60
61 protected:
SelectSectionForGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const62 MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
63 const TargetMachine &TM) const override {
64 llvm_unreachable("Not supported!");
65 }
66 };
67
68 class DirectXPassConfig : public TargetPassConfig {
69 public:
DirectXPassConfig(DirectXTargetMachine & TM,PassManagerBase & PM)70 DirectXPassConfig(DirectXTargetMachine &TM, PassManagerBase &PM)
71 : TargetPassConfig(TM, PM) {}
72
getDirectXTargetMachine() const73 DirectXTargetMachine &getDirectXTargetMachine() const {
74 return getTM<DirectXTargetMachine>();
75 }
76
createTargetRegisterAllocator(bool)77 FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; }
addCodeGenPrepare()78 void addCodeGenPrepare() override {
79 addPass(createDXILOpLoweringLegacyPass());
80 addPass(createDXILPrepareModulePass());
81 addPass(createDXILTranslateMetadataPass());
82 }
83 };
84
DirectXTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOptLevel OL,bool JIT)85 DirectXTargetMachine::DirectXTargetMachine(const Target &T, const Triple &TT,
86 StringRef CPU, StringRef FS,
87 const TargetOptions &Options,
88 std::optional<Reloc::Model> RM,
89 std::optional<CodeModel::Model> CM,
90 CodeGenOptLevel OL, bool JIT)
91 : LLVMTargetMachine(T,
92 "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-"
93 "f32:32-f64:64-n8:16:32:64",
94 TT, CPU, FS, Options, Reloc::Static, CodeModel::Small,
95 OL),
96 TLOF(std::make_unique<DXILTargetObjectFile>()),
97 Subtarget(std::make_unique<DirectXSubtarget>(TT, CPU, FS, *this)) {
98 initAsmInfo();
99 }
100
~DirectXTargetMachine()101 DirectXTargetMachine::~DirectXTargetMachine() {}
102
registerPassBuilderCallbacks(PassBuilder & PB,bool PopulateClassToPassNames)103 void DirectXTargetMachine::registerPassBuilderCallbacks(
104 PassBuilder &PB, bool PopulateClassToPassNames) {
105 PB.registerPipelineParsingCallback(
106 [](StringRef PassName, ModulePassManager &PM,
107 ArrayRef<PassBuilder::PipelineElement>) {
108 if (PassName == "print-dxil-resource") {
109 PM.addPass(DXILResourcePrinterPass(dbgs()));
110 return true;
111 }
112 if (PassName == "print-dx-shader-flags") {
113 PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs()));
114 return true;
115 }
116 return false;
117 });
118
119 PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) {
120 MAM.registerPass([&] { return DXILResourceAnalysis(); });
121 MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); });
122 });
123 }
124
addPassesToEmitFile(PassManagerBase & PM,raw_pwrite_stream & Out,raw_pwrite_stream * DwoOut,CodeGenFileType FileType,bool DisableVerify,MachineModuleInfoWrapperPass * MMIWP)125 bool DirectXTargetMachine::addPassesToEmitFile(
126 PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
127 CodeGenFileType FileType, bool DisableVerify,
128 MachineModuleInfoWrapperPass *MMIWP) {
129 TargetPassConfig *PassConfig = createPassConfig(PM);
130 PassConfig->addCodeGenPrepare();
131
132 switch (FileType) {
133 case CodeGenFileType::AssemblyFile:
134 PM.add(createDXILPrettyPrinterPass(Out));
135 PM.add(createPrintModulePass(Out, "", true));
136 break;
137 case CodeGenFileType::ObjectFile:
138 if (TargetPassConfig::willCompleteCodeGenPipeline()) {
139 PM.add(createDXILEmbedderPass());
140 // We embed the other DXContainer globals after embedding DXIL so that the
141 // globals don't pollute the DXIL.
142 PM.add(createDXContainerGlobalsPass());
143
144 if (!MMIWP)
145 MMIWP = new MachineModuleInfoWrapperPass(this);
146 PM.add(MMIWP);
147 if (addAsmPrinter(PM, Out, DwoOut, FileType,
148 MMIWP->getMMI().getContext()))
149 return true;
150 } else
151 PM.add(createDXILWriterPass(Out));
152 break;
153 case CodeGenFileType::Null:
154 break;
155 }
156 return false;
157 }
158
addPassesToEmitMC(PassManagerBase & PM,MCContext * & Ctx,raw_pwrite_stream & Out,bool DisableVerify)159 bool DirectXTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
160 MCContext *&Ctx,
161 raw_pwrite_stream &Out,
162 bool DisableVerify) {
163 return true;
164 }
165
createPassConfig(PassManagerBase & PM)166 TargetPassConfig *DirectXTargetMachine::createPassConfig(PassManagerBase &PM) {
167 return new DirectXPassConfig(*this, PM);
168 }
169
170 const DirectXSubtarget *
getSubtargetImpl(const Function &) const171 DirectXTargetMachine::getSubtargetImpl(const Function &) const {
172 return Subtarget.get();
173 }
174
175 TargetTransformInfo
getTargetTransformInfo(const Function & F) const176 DirectXTargetMachine::getTargetTransformInfo(const Function &F) const {
177 return TargetTransformInfo(DirectXTTIImpl(this, F));
178 }
179
DirectXTargetLowering(const DirectXTargetMachine & TM,const DirectXSubtarget & STI)180 DirectXTargetLowering::DirectXTargetLowering(const DirectXTargetMachine &TM,
181 const DirectXSubtarget &STI)
182 : TargetLowering(TM) {}
183