181ad6265SDimitry Andric //===- DirectXTargetMachine.cpp - DirectX Target Implementation -*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric ///
981ad6265SDimitry Andric /// \file
1081ad6265SDimitry Andric /// This file contains DirectX target initializer.
1181ad6265SDimitry Andric ///
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric
1481ad6265SDimitry Andric #include "DirectXTargetMachine.h"
15bdd1243dSDimitry Andric #include "DXILResourceAnalysis.h"
16bdd1243dSDimitry Andric #include "DXILShaderFlags.h"
1781ad6265SDimitry Andric #include "DXILWriter/DXILWriterPass.h"
1881ad6265SDimitry Andric #include "DirectX.h"
1981ad6265SDimitry Andric #include "DirectXSubtarget.h"
2081ad6265SDimitry Andric #include "DirectXTargetTransformInfo.h"
2181ad6265SDimitry Andric #include "TargetInfo/DirectXTargetInfo.h"
2281ad6265SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
2381ad6265SDimitry Andric #include "llvm/CodeGen/Passes.h"
2481ad6265SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
2581ad6265SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
2681ad6265SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
2781ad6265SDimitry Andric #include "llvm/MC/MCSectionDXContainer.h"
2881ad6265SDimitry Andric #include "llvm/MC/SectionKind.h"
2981ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h"
30bdd1243dSDimitry Andric #include "llvm/Passes/PassBuilder.h"
3181ad6265SDimitry Andric #include "llvm/Support/CodeGen.h"
3281ad6265SDimitry Andric #include "llvm/Support/Compiler.h"
3381ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h"
3481ad6265SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
35bdd1243dSDimitry Andric #include <optional>
3681ad6265SDimitry Andric
3781ad6265SDimitry Andric using namespace llvm;
3881ad6265SDimitry Andric
LLVMInitializeDirectXTarget()3981ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() {
4081ad6265SDimitry Andric RegisterTargetMachine<DirectXTargetMachine> X(getTheDirectXTarget());
4181ad6265SDimitry Andric auto *PR = PassRegistry::getPassRegistry();
4281ad6265SDimitry Andric initializeDXILPrepareModulePass(*PR);
4381ad6265SDimitry Andric initializeEmbedDXILPassPass(*PR);
44bdd1243dSDimitry Andric initializeWriteDXILPassPass(*PR);
45c9157d92SDimitry Andric initializeDXContainerGlobalsPass(*PR);
4681ad6265SDimitry Andric initializeDXILOpLoweringLegacyPass(*PR);
4781ad6265SDimitry Andric initializeDXILTranslateMetadataPass(*PR);
48bdd1243dSDimitry Andric initializeDXILResourceWrapperPass(*PR);
49bdd1243dSDimitry Andric initializeShaderFlagsAnalysisWrapperPass(*PR);
5081ad6265SDimitry Andric }
5181ad6265SDimitry Andric
5281ad6265SDimitry Andric class DXILTargetObjectFile : public TargetLoweringObjectFile {
5381ad6265SDimitry Andric public:
5481ad6265SDimitry Andric DXILTargetObjectFile() = default;
5581ad6265SDimitry Andric
getExplicitSectionGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const5681ad6265SDimitry Andric MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
5781ad6265SDimitry Andric const TargetMachine &TM) const override {
5881ad6265SDimitry Andric return getContext().getDXContainerSection(GO->getSection(), Kind);
5981ad6265SDimitry Andric }
6081ad6265SDimitry Andric
6181ad6265SDimitry Andric protected:
SelectSectionForGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const6281ad6265SDimitry Andric MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
6381ad6265SDimitry Andric const TargetMachine &TM) const override {
6481ad6265SDimitry Andric llvm_unreachable("Not supported!");
6581ad6265SDimitry Andric }
6681ad6265SDimitry Andric };
6781ad6265SDimitry Andric
6881ad6265SDimitry Andric class DirectXPassConfig : public TargetPassConfig {
6981ad6265SDimitry Andric public:
DirectXPassConfig(DirectXTargetMachine & TM,PassManagerBase & PM)7081ad6265SDimitry Andric DirectXPassConfig(DirectXTargetMachine &TM, PassManagerBase &PM)
7181ad6265SDimitry Andric : TargetPassConfig(TM, PM) {}
7281ad6265SDimitry Andric
getDirectXTargetMachine() const7381ad6265SDimitry Andric DirectXTargetMachine &getDirectXTargetMachine() const {
7481ad6265SDimitry Andric return getTM<DirectXTargetMachine>();
7581ad6265SDimitry Andric }
7681ad6265SDimitry Andric
createTargetRegisterAllocator(bool)7781ad6265SDimitry Andric FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; }
addCodeGenPrepare()78bdd1243dSDimitry Andric void addCodeGenPrepare() override {
79bdd1243dSDimitry Andric addPass(createDXILOpLoweringLegacyPass());
80bdd1243dSDimitry Andric addPass(createDXILPrepareModulePass());
81bdd1243dSDimitry Andric addPass(createDXILTranslateMetadataPass());
82bdd1243dSDimitry Andric }
8381ad6265SDimitry Andric };
8481ad6265SDimitry Andric
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)8581ad6265SDimitry Andric DirectXTargetMachine::DirectXTargetMachine(const Target &T, const Triple &TT,
8681ad6265SDimitry Andric StringRef CPU, StringRef FS,
8781ad6265SDimitry Andric const TargetOptions &Options,
88bdd1243dSDimitry Andric std::optional<Reloc::Model> RM,
89bdd1243dSDimitry Andric std::optional<CodeModel::Model> CM,
90c9157d92SDimitry Andric CodeGenOptLevel OL, bool JIT)
9181ad6265SDimitry Andric : LLVMTargetMachine(T,
9281ad6265SDimitry Andric "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-"
9381ad6265SDimitry Andric "f32:32-f64:64-n8:16:32:64",
9481ad6265SDimitry Andric TT, CPU, FS, Options, Reloc::Static, CodeModel::Small,
9581ad6265SDimitry Andric OL),
9681ad6265SDimitry Andric TLOF(std::make_unique<DXILTargetObjectFile>()),
9781ad6265SDimitry Andric Subtarget(std::make_unique<DirectXSubtarget>(TT, CPU, FS, *this)) {
9881ad6265SDimitry Andric initAsmInfo();
9981ad6265SDimitry Andric }
10081ad6265SDimitry Andric
~DirectXTargetMachine()10181ad6265SDimitry Andric DirectXTargetMachine::~DirectXTargetMachine() {}
10281ad6265SDimitry Andric
registerPassBuilderCallbacks(PassBuilder & PB,bool PopulateClassToPassNames)103*cdc20ff6SDimitry Andric void DirectXTargetMachine::registerPassBuilderCallbacks(
104*cdc20ff6SDimitry Andric PassBuilder &PB, bool PopulateClassToPassNames) {
105bdd1243dSDimitry Andric PB.registerPipelineParsingCallback(
106bdd1243dSDimitry Andric [](StringRef PassName, ModulePassManager &PM,
107bdd1243dSDimitry Andric ArrayRef<PassBuilder::PipelineElement>) {
108bdd1243dSDimitry Andric if (PassName == "print-dxil-resource") {
109bdd1243dSDimitry Andric PM.addPass(DXILResourcePrinterPass(dbgs()));
110bdd1243dSDimitry Andric return true;
111bdd1243dSDimitry Andric }
112bdd1243dSDimitry Andric if (PassName == "print-dx-shader-flags") {
113bdd1243dSDimitry Andric PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs()));
114bdd1243dSDimitry Andric return true;
115bdd1243dSDimitry Andric }
116bdd1243dSDimitry Andric return false;
117bdd1243dSDimitry Andric });
118bdd1243dSDimitry Andric
119bdd1243dSDimitry Andric PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) {
120bdd1243dSDimitry Andric MAM.registerPass([&] { return DXILResourceAnalysis(); });
121bdd1243dSDimitry Andric MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); });
122bdd1243dSDimitry Andric });
123bdd1243dSDimitry Andric }
124bdd1243dSDimitry Andric
addPassesToEmitFile(PassManagerBase & PM,raw_pwrite_stream & Out,raw_pwrite_stream * DwoOut,CodeGenFileType FileType,bool DisableVerify,MachineModuleInfoWrapperPass * MMIWP)12581ad6265SDimitry Andric bool DirectXTargetMachine::addPassesToEmitFile(
12681ad6265SDimitry Andric PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
12781ad6265SDimitry Andric CodeGenFileType FileType, bool DisableVerify,
12881ad6265SDimitry Andric MachineModuleInfoWrapperPass *MMIWP) {
129bdd1243dSDimitry Andric TargetPassConfig *PassConfig = createPassConfig(PM);
130bdd1243dSDimitry Andric PassConfig->addCodeGenPrepare();
131bdd1243dSDimitry Andric
132c9157d92SDimitry Andric switch (FileType) {
133c9157d92SDimitry Andric case CodeGenFileType::AssemblyFile:
134c9157d92SDimitry Andric PM.add(createDXILPrettyPrinterPass(Out));
135c9157d92SDimitry Andric PM.add(createPrintModulePass(Out, "", true));
136c9157d92SDimitry Andric break;
137c9157d92SDimitry Andric case CodeGenFileType::ObjectFile:
13881ad6265SDimitry Andric if (TargetPassConfig::willCompleteCodeGenPipeline()) {
13981ad6265SDimitry Andric PM.add(createDXILEmbedderPass());
140bdd1243dSDimitry Andric // We embed the other DXContainer globals after embedding DXIL so that the
141bdd1243dSDimitry Andric // globals don't pollute the DXIL.
142bdd1243dSDimitry Andric PM.add(createDXContainerGlobalsPass());
143c9157d92SDimitry Andric
14481ad6265SDimitry Andric if (!MMIWP)
14581ad6265SDimitry Andric MMIWP = new MachineModuleInfoWrapperPass(this);
14681ad6265SDimitry Andric PM.add(MMIWP);
14781ad6265SDimitry Andric if (addAsmPrinter(PM, Out, DwoOut, FileType,
14881ad6265SDimitry Andric MMIWP->getMMI().getContext()))
14981ad6265SDimitry Andric return true;
15081ad6265SDimitry Andric } else
15181ad6265SDimitry Andric PM.add(createDXILWriterPass(Out));
15281ad6265SDimitry Andric break;
153c9157d92SDimitry Andric case CodeGenFileType::Null:
15481ad6265SDimitry Andric break;
15581ad6265SDimitry Andric }
15681ad6265SDimitry Andric return false;
15781ad6265SDimitry Andric }
15881ad6265SDimitry Andric
addPassesToEmitMC(PassManagerBase & PM,MCContext * & Ctx,raw_pwrite_stream & Out,bool DisableVerify)15981ad6265SDimitry Andric bool DirectXTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
16081ad6265SDimitry Andric MCContext *&Ctx,
16181ad6265SDimitry Andric raw_pwrite_stream &Out,
16281ad6265SDimitry Andric bool DisableVerify) {
16381ad6265SDimitry Andric return true;
16481ad6265SDimitry Andric }
16581ad6265SDimitry Andric
createPassConfig(PassManagerBase & PM)16681ad6265SDimitry Andric TargetPassConfig *DirectXTargetMachine::createPassConfig(PassManagerBase &PM) {
16781ad6265SDimitry Andric return new DirectXPassConfig(*this, PM);
16881ad6265SDimitry Andric }
16981ad6265SDimitry Andric
17081ad6265SDimitry Andric const DirectXSubtarget *
getSubtargetImpl(const Function &) const17181ad6265SDimitry Andric DirectXTargetMachine::getSubtargetImpl(const Function &) const {
17281ad6265SDimitry Andric return Subtarget.get();
17381ad6265SDimitry Andric }
17481ad6265SDimitry Andric
17581ad6265SDimitry Andric TargetTransformInfo
getTargetTransformInfo(const Function & F) const17681ad6265SDimitry Andric DirectXTargetMachine::getTargetTransformInfo(const Function &F) const {
17781ad6265SDimitry Andric return TargetTransformInfo(DirectXTTIImpl(this, F));
17881ad6265SDimitry Andric }
17981ad6265SDimitry Andric
DirectXTargetLowering(const DirectXTargetMachine & TM,const DirectXSubtarget & STI)18081ad6265SDimitry Andric DirectXTargetLowering::DirectXTargetLowering(const DirectXTargetMachine &TM,
18181ad6265SDimitry Andric const DirectXSubtarget &STI)
18281ad6265SDimitry Andric : TargetLowering(TM) {}
183