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 initializeDXILOpLoweringLegacyPass(*PR);
46 initializeDXILTranslateMetadataPass(*PR);
47 initializeDXILResourceWrapperPass(*PR);
48 initializeShaderFlagsAnalysisWrapperPass(*PR);
49 }
50
51 class DXILTargetObjectFile : public TargetLoweringObjectFile {
52 public:
53 DXILTargetObjectFile() = default;
54
getExplicitSectionGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const55 MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
56 const TargetMachine &TM) const override {
57 return getContext().getDXContainerSection(GO->getSection(), Kind);
58 }
59
60 protected:
SelectSectionForGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const61 MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
62 const TargetMachine &TM) const override {
63 llvm_unreachable("Not supported!");
64 }
65 };
66
67 class DirectXPassConfig : public TargetPassConfig {
68 public:
DirectXPassConfig(DirectXTargetMachine & TM,PassManagerBase & PM)69 DirectXPassConfig(DirectXTargetMachine &TM, PassManagerBase &PM)
70 : TargetPassConfig(TM, PM) {}
71
getDirectXTargetMachine() const72 DirectXTargetMachine &getDirectXTargetMachine() const {
73 return getTM<DirectXTargetMachine>();
74 }
75
createTargetRegisterAllocator(bool)76 FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; }
addCodeGenPrepare()77 void addCodeGenPrepare() override {
78 addPass(createDXILOpLoweringLegacyPass());
79 addPass(createDXILPrepareModulePass());
80 addPass(createDXILTranslateMetadataPass());
81 }
82 };
83
DirectXTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)84 DirectXTargetMachine::DirectXTargetMachine(const Target &T, const Triple &TT,
85 StringRef CPU, StringRef FS,
86 const TargetOptions &Options,
87 std::optional<Reloc::Model> RM,
88 std::optional<CodeModel::Model> CM,
89 CodeGenOpt::Level OL, bool JIT)
90 : LLVMTargetMachine(T,
91 "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-"
92 "f32:32-f64:64-n8:16:32:64",
93 TT, CPU, FS, Options, Reloc::Static, CodeModel::Small,
94 OL),
95 TLOF(std::make_unique<DXILTargetObjectFile>()),
96 Subtarget(std::make_unique<DirectXSubtarget>(TT, CPU, FS, *this)) {
97 initAsmInfo();
98 }
99
~DirectXTargetMachine()100 DirectXTargetMachine::~DirectXTargetMachine() {}
101
registerPassBuilderCallbacks(PassBuilder & PB)102 void DirectXTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
103 PB.registerPipelineParsingCallback(
104 [](StringRef PassName, ModulePassManager &PM,
105 ArrayRef<PassBuilder::PipelineElement>) {
106 if (PassName == "print-dxil-resource") {
107 PM.addPass(DXILResourcePrinterPass(dbgs()));
108 return true;
109 }
110 if (PassName == "print-dx-shader-flags") {
111 PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs()));
112 return true;
113 }
114 return false;
115 });
116
117 PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) {
118 MAM.registerPass([&] { return DXILResourceAnalysis(); });
119 MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); });
120 });
121 }
122
addPassesToEmitFile(PassManagerBase & PM,raw_pwrite_stream & Out,raw_pwrite_stream * DwoOut,CodeGenFileType FileType,bool DisableVerify,MachineModuleInfoWrapperPass * MMIWP)123 bool DirectXTargetMachine::addPassesToEmitFile(
124 PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
125 CodeGenFileType FileType, bool DisableVerify,
126 MachineModuleInfoWrapperPass *MMIWP) {
127 TargetPassConfig *PassConfig = createPassConfig(PM);
128 PassConfig->addCodeGenPrepare();
129
130 if (TargetPassConfig::willCompleteCodeGenPipeline()) {
131 PM.add(createDXILEmbedderPass());
132 // We embed the other DXContainer globals after embedding DXIL so that the
133 // globals don't pollute the DXIL.
134 PM.add(createDXContainerGlobalsPass());
135 }
136 switch (FileType) {
137 case CGFT_AssemblyFile:
138 PM.add(createDXILPrettyPrinterPass(Out));
139 PM.add(createPrintModulePass(Out, "", true));
140 break;
141 case CGFT_ObjectFile:
142 if (TargetPassConfig::willCompleteCodeGenPipeline()) {
143 if (!MMIWP)
144 MMIWP = new MachineModuleInfoWrapperPass(this);
145 PM.add(MMIWP);
146 if (addAsmPrinter(PM, Out, DwoOut, FileType,
147 MMIWP->getMMI().getContext()))
148 return true;
149 } else
150 PM.add(createDXILWriterPass(Out));
151 break;
152 case CGFT_Null:
153 break;
154 }
155 return false;
156 }
157
addPassesToEmitMC(PassManagerBase & PM,MCContext * & Ctx,raw_pwrite_stream & Out,bool DisableVerify)158 bool DirectXTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
159 MCContext *&Ctx,
160 raw_pwrite_stream &Out,
161 bool DisableVerify) {
162 return true;
163 }
164
createPassConfig(PassManagerBase & PM)165 TargetPassConfig *DirectXTargetMachine::createPassConfig(PassManagerBase &PM) {
166 return new DirectXPassConfig(*this, PM);
167 }
168
169 const DirectXSubtarget *
getSubtargetImpl(const Function &) const170 DirectXTargetMachine::getSubtargetImpl(const Function &) const {
171 return Subtarget.get();
172 }
173
174 TargetTransformInfo
getTargetTransformInfo(const Function & F) const175 DirectXTargetMachine::getTargetTransformInfo(const Function &F) const {
176 return TargetTransformInfo(DirectXTTIImpl(this, F));
177 }
178
DirectXTargetLowering(const DirectXTargetMachine & TM,const DirectXSubtarget & STI)179 DirectXTargetLowering::DirectXTargetLowering(const DirectXTargetMachine &TM,
180 const DirectXSubtarget &STI)
181 : TargetLowering(TM) {}
182