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 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); 45*5f757f3fSDimitry 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 5681ad6265SDimitry 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: 6281ad6265SDimitry 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: 7081ad6265SDimitry Andric DirectXPassConfig(DirectXTargetMachine &TM, PassManagerBase &PM) 7181ad6265SDimitry Andric : TargetPassConfig(TM, PM) {} 7281ad6265SDimitry Andric 7381ad6265SDimitry Andric DirectXTargetMachine &getDirectXTargetMachine() const { 7481ad6265SDimitry Andric return getTM<DirectXTargetMachine>(); 7581ad6265SDimitry Andric } 7681ad6265SDimitry Andric 7781ad6265SDimitry Andric FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; } 78bdd1243dSDimitry Andric void addCodeGenPrepare() override { 79bdd1243dSDimitry Andric addPass(createDXILOpLoweringLegacyPass()); 80bdd1243dSDimitry Andric addPass(createDXILPrepareModulePass()); 81bdd1243dSDimitry Andric addPass(createDXILTranslateMetadataPass()); 82bdd1243dSDimitry Andric } 8381ad6265SDimitry Andric }; 8481ad6265SDimitry Andric 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, 90*5f757f3fSDimitry 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 10181ad6265SDimitry Andric DirectXTargetMachine::~DirectXTargetMachine() {} 10281ad6265SDimitry Andric 103bdd1243dSDimitry Andric void DirectXTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) { 104bdd1243dSDimitry Andric PB.registerPipelineParsingCallback( 105bdd1243dSDimitry Andric [](StringRef PassName, ModulePassManager &PM, 106bdd1243dSDimitry Andric ArrayRef<PassBuilder::PipelineElement>) { 107bdd1243dSDimitry Andric if (PassName == "print-dxil-resource") { 108bdd1243dSDimitry Andric PM.addPass(DXILResourcePrinterPass(dbgs())); 109bdd1243dSDimitry Andric return true; 110bdd1243dSDimitry Andric } 111bdd1243dSDimitry Andric if (PassName == "print-dx-shader-flags") { 112bdd1243dSDimitry Andric PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs())); 113bdd1243dSDimitry Andric return true; 114bdd1243dSDimitry Andric } 115bdd1243dSDimitry Andric return false; 116bdd1243dSDimitry Andric }); 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) { 119bdd1243dSDimitry Andric MAM.registerPass([&] { return DXILResourceAnalysis(); }); 120bdd1243dSDimitry Andric MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); }); 121bdd1243dSDimitry Andric }); 122bdd1243dSDimitry Andric } 123bdd1243dSDimitry Andric 12481ad6265SDimitry Andric bool DirectXTargetMachine::addPassesToEmitFile( 12581ad6265SDimitry Andric PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, 12681ad6265SDimitry Andric CodeGenFileType FileType, bool DisableVerify, 12781ad6265SDimitry Andric MachineModuleInfoWrapperPass *MMIWP) { 128bdd1243dSDimitry Andric TargetPassConfig *PassConfig = createPassConfig(PM); 129bdd1243dSDimitry Andric PassConfig->addCodeGenPrepare(); 130bdd1243dSDimitry Andric 131*5f757f3fSDimitry Andric switch (FileType) { 132*5f757f3fSDimitry Andric case CodeGenFileType::AssemblyFile: 133*5f757f3fSDimitry Andric PM.add(createDXILPrettyPrinterPass(Out)); 134*5f757f3fSDimitry Andric PM.add(createPrintModulePass(Out, "", true)); 135*5f757f3fSDimitry Andric break; 136*5f757f3fSDimitry Andric case CodeGenFileType::ObjectFile: 13781ad6265SDimitry Andric if (TargetPassConfig::willCompleteCodeGenPipeline()) { 13881ad6265SDimitry Andric PM.add(createDXILEmbedderPass()); 139bdd1243dSDimitry Andric // We embed the other DXContainer globals after embedding DXIL so that the 140bdd1243dSDimitry Andric // globals don't pollute the DXIL. 141bdd1243dSDimitry Andric PM.add(createDXContainerGlobalsPass()); 142*5f757f3fSDimitry Andric 14381ad6265SDimitry Andric if (!MMIWP) 14481ad6265SDimitry Andric MMIWP = new MachineModuleInfoWrapperPass(this); 14581ad6265SDimitry Andric PM.add(MMIWP); 14681ad6265SDimitry Andric if (addAsmPrinter(PM, Out, DwoOut, FileType, 14781ad6265SDimitry Andric MMIWP->getMMI().getContext())) 14881ad6265SDimitry Andric return true; 14981ad6265SDimitry Andric } else 15081ad6265SDimitry Andric PM.add(createDXILWriterPass(Out)); 15181ad6265SDimitry Andric break; 152*5f757f3fSDimitry Andric case CodeGenFileType::Null: 15381ad6265SDimitry Andric break; 15481ad6265SDimitry Andric } 15581ad6265SDimitry Andric return false; 15681ad6265SDimitry Andric } 15781ad6265SDimitry Andric 15881ad6265SDimitry Andric bool DirectXTargetMachine::addPassesToEmitMC(PassManagerBase &PM, 15981ad6265SDimitry Andric MCContext *&Ctx, 16081ad6265SDimitry Andric raw_pwrite_stream &Out, 16181ad6265SDimitry Andric bool DisableVerify) { 16281ad6265SDimitry Andric return true; 16381ad6265SDimitry Andric } 16481ad6265SDimitry Andric 16581ad6265SDimitry Andric TargetPassConfig *DirectXTargetMachine::createPassConfig(PassManagerBase &PM) { 16681ad6265SDimitry Andric return new DirectXPassConfig(*this, PM); 16781ad6265SDimitry Andric } 16881ad6265SDimitry Andric 16981ad6265SDimitry Andric const DirectXSubtarget * 17081ad6265SDimitry Andric DirectXTargetMachine::getSubtargetImpl(const Function &) const { 17181ad6265SDimitry Andric return Subtarget.get(); 17281ad6265SDimitry Andric } 17381ad6265SDimitry Andric 17481ad6265SDimitry Andric TargetTransformInfo 17581ad6265SDimitry Andric DirectXTargetMachine::getTargetTransformInfo(const Function &F) const { 17681ad6265SDimitry Andric return TargetTransformInfo(DirectXTTIImpl(this, F)); 17781ad6265SDimitry Andric } 17881ad6265SDimitry Andric 17981ad6265SDimitry Andric DirectXTargetLowering::DirectXTargetLowering(const DirectXTargetMachine &TM, 18081ad6265SDimitry Andric const DirectXSubtarget &STI) 18181ad6265SDimitry Andric : TargetLowering(TM) {} 182