diff --git a/llvm/lib/Target/DirectX/DirectXSubtarget.h b/llvm/lib/Target/DirectX/DirectXSubtarget.h --- a/llvm/lib/Target/DirectX/DirectXSubtarget.h +++ b/llvm/lib/Target/DirectX/DirectXSubtarget.h @@ -13,6 +13,8 @@ #ifndef LLVM_DIRECTX_DIRECTXSUBTARGET_H #define LLVM_DIRECTX_DIRECTXSUBTARGET_H +#include "DirectXFrameLowering.h" +#include "DirectXInstrInfo.h" #include "DirectXTargetLowering.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" @@ -26,7 +28,11 @@ class DirectXTargetMachine; class DirectXSubtarget : public DirectXGenSubtargetInfo { + DirectXFrameLowering FL; DirectXTargetLowering TL; + DirectXInstrInfo InstrInfo; + + virtual void anchor(); // virtual anchor method public: DirectXSubtarget(const Triple &TT, StringRef CPU, StringRef FS, @@ -39,6 +45,10 @@ const DirectXTargetLowering *getTargetLowering() const override { return &TL; } + + const DirectXFrameLowering *getFrameLowering() const override { return &FL; } + + const DirectXInstrInfo *getInstrInfo() const override { return &InstrInfo; } }; } // end namespace llvm diff --git a/llvm/lib/Target/DirectX/DirectXSubtarget.cpp b/llvm/lib/Target/DirectX/DirectXSubtarget.cpp --- a/llvm/lib/Target/DirectX/DirectXSubtarget.cpp +++ b/llvm/lib/Target/DirectX/DirectXSubtarget.cpp @@ -24,4 +24,6 @@ DirectXSubtarget::DirectXSubtarget(const Triple &TT, StringRef CPU, StringRef FS, const DirectXTargetMachine &TM) - : DirectXGenSubtargetInfo(TT, CPU, CPU, FS), TL(TM, *this) {} + : DirectXGenSubtargetInfo(TT, CPU, CPU, FS), FL(*this), TL(TM, *this) {} + +void DirectXSubtarget::anchor() {} diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -17,10 +17,12 @@ #include "DirectXSubtarget.h" #include "DirectXTargetTransformInfo.h" #include "TargetInfo/DirectXTargetInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/MC/MCSectionDXContainer.h" #include "llvm/MC/SectionKind.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CodeGen.h" @@ -45,7 +47,7 @@ MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override { - llvm_unreachable("Not supported!"); + return getContext().getDXContainerSection(GO->getSection(), Kind); } protected: @@ -79,7 +81,9 @@ TT, CPU, FS, Options, Reloc::Static, CodeModel::Small, OL), TLOF(std::make_unique()), - Subtarget(std::make_unique(TT, CPU, FS, *this)) {} + Subtarget(std::make_unique(TT, CPU, FS, *this)) { + initAsmInfo(); +} DirectXTargetMachine::~DirectXTargetMachine() {} @@ -90,16 +94,23 @@ PM.add(createDXILOpLoweringLegacyPass()); PM.add(createDXILPrepareModulePass()); PM.add(createDXILTranslateMetadataPass()); + if (TargetPassConfig::willCompleteCodeGenPipeline()) { + PM.add(createDXILEmbedderPass()); + } switch (FileType) { case CGFT_AssemblyFile: - if (TargetPassConfig::willCompleteCodeGenPipeline()) { - PM.add(createDXILEmbedderPass()); - } PM.add(createPrintModulePass(Out, "", true)); break; case CGFT_ObjectFile: - // TODO: Use MC Object streamer to write DXContainer - PM.add(createDXILWriterPass(Out)); + if (TargetPassConfig::willCompleteCodeGenPipeline()) { + if (!MMIWP) + MMIWP = new MachineModuleInfoWrapperPass(this); + PM.add(MMIWP); + if (addAsmPrinter(PM, Out, DwoOut, FileType, + MMIWP->getMMI().getContext())) + return true; + } else + PM.add(createDXILWriterPass(Out)); break; case CGFT_Null: break; diff --git a/llvm/lib/Target/DirectX/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/DirectX/MCTargetDesc/CMakeLists.txt --- a/llvm/lib/Target/DirectX/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/MCTargetDesc/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_component_library(LLVMDirectXDesc + DirectXContainerObjectWriter.cpp DirectXMCTargetDesc.cpp LINK_COMPONENTS diff --git a/llvm/lib/Target/DirectX/MCTargetDesc/DirectXContainerObjectWriter.h b/llvm/lib/Target/DirectX/MCTargetDesc/DirectXContainerObjectWriter.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/DirectX/MCTargetDesc/DirectXContainerObjectWriter.h @@ -0,0 +1,24 @@ +//===-- DirectXContainerObjectWriter.h - DX object writer ------*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains DXContainer object writers for the DirectX backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DIRECTX_DIRECTXCONTAINEROBJECTWRITER_H +#define LLVM_DIRECTX_DIRECTXCONTAINEROBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" + +namespace llvm { + +std::unique_ptr createDXContainerTargetObjectWriter(); + +} + +#endif // LLVM_DIRECTX_DIRECTXCONTAINEROBJECTWRITER_H diff --git a/llvm/lib/Target/DirectX/MCTargetDesc/DirectXContainerObjectWriter.cpp b/llvm/lib/Target/DirectX/MCTargetDesc/DirectXContainerObjectWriter.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/DirectX/MCTargetDesc/DirectXContainerObjectWriter.cpp @@ -0,0 +1,28 @@ +//===-- DirectXContainerObjectWriter.cpp - DX object writer ----*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains DXContainer object writers for the DirectX backend. +// +//===----------------------------------------------------------------------===// + +#include "DirectXContainerObjectWriter.h" +#include "llvm/MC/MCDXContainerWriter.h" + +using namespace llvm; + +namespace { +class DirectXContainerObjectWriter : public MCDXContainerTargetWriter { +public: + DirectXContainerObjectWriter() : MCDXContainerTargetWriter() {} +}; +} // namespace + +std::unique_ptr +llvm::createDXContainerTargetObjectWriter() { + return std::make_unique(); +} diff --git a/llvm/lib/Target/DirectX/MCTargetDesc/DirectXMCTargetDesc.cpp b/llvm/lib/Target/DirectX/MCTargetDesc/DirectXMCTargetDesc.cpp --- a/llvm/lib/Target/DirectX/MCTargetDesc/DirectXMCTargetDesc.cpp +++ b/llvm/lib/Target/DirectX/MCTargetDesc/DirectXMCTargetDesc.cpp @@ -11,17 +11,142 @@ /// //===----------------------------------------------------------------------===// +#include "DirectXMCTargetDesc.h" +#include "DirectXContainerObjectWriter.h" +#include "TargetInfo/DirectXTargetInfo.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCDXContainerWriter.h" +#include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSchedule.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Compiler.h" +#include using namespace llvm; +#define GET_INSTRINFO_MC_DESC +#define GET_INSTRINFO_MC_HELPERS +#include "DirectXGenInstrInfo.inc" + #define GET_SUBTARGETINFO_MC_DESC #include "DirectXGenSubtargetInfo.inc" -extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTargetMC() {} +#define GET_REGINFO_MC_DESC +#include "DirectXGenRegisterInfo.inc" + +namespace { + +// DXILInstPrinter is a null stub because DXIL instructions aren't printed. +class DXILInstPrinter : public MCInstPrinter { +public: + DXILInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &O) override {} + + std::pair getMnemonic(const MCInst *MI) override { + return std::make_pair("", 0ull); + } + +private: +}; + +class DXILMCCodeEmitter : public MCCodeEmitter { +public: + DXILMCCodeEmitter() {} + + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override {} +}; + +class DXILAsmBackend : public MCAsmBackend { + +public: + DXILAsmBackend(const MCSubtargetInfo &STI) : MCAsmBackend(support::little) {} + ~DXILAsmBackend() override = default; + + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override {} + + std::unique_ptr + createObjectTargetWriter() const override { + return createDXContainerTargetObjectWriter(); + } + + unsigned getNumFixupKinds() const override { return 0; } + + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override { + return true; + } + + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + return true; + } +}; + +class DirectXMCAsmInfo : public MCAsmInfo { +public: + explicit DirectXMCAsmInfo(const Triple &TT, const MCTargetOptions &Options) + : MCAsmInfo() {} +}; + +} // namespace + +static MCInstPrinter *createDXILMCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + if (SyntaxVariant == 0) + return new DXILInstPrinter(MAI, MII, MRI); + return nullptr; +} + +MCCodeEmitter *createDXILMCCodeEmitter(const MCInstrInfo &MCII, + MCContext &Ctx) { + return new DXILMCCodeEmitter(); +} + +MCAsmBackend *createDXILMCAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options) { + return new DXILAsmBackend(STI); +} + +static MCSubtargetInfo * +createDirectXMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { + return createDirectXMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); +} + +static MCRegisterInfo *createDirectXMCRegisterInfo(const Triple &Triple) { + return new MCRegisterInfo(); +} + +static MCInstrInfo *createDirectXMCInstrInfo() { return new MCInstrInfo(); } + +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTargetMC() { + Target &T = getTheDirectXTarget(); + RegisterMCAsmInfo X(T); + TargetRegistry::RegisterMCInstrInfo(T, createDirectXMCInstrInfo); + TargetRegistry::RegisterMCInstPrinter(T, createDXILMCInstPrinter); + TargetRegistry::RegisterMCRegInfo(T, createDirectXMCRegisterInfo); + TargetRegistry::RegisterMCSubtargetInfo(T, createDirectXMCSubtargetInfo); + TargetRegistry::RegisterMCCodeEmitter(T, createDXILMCCodeEmitter); + TargetRegistry::RegisterMCAsmBackend(T, createDXILMCAsmBackend); +} diff --git a/llvm/test/CodeGen/DirectX/embed-dxil.ll b/llvm/test/CodeGen/DirectX/embed-dxil.ll --- a/llvm/test/CodeGen/DirectX/embed-dxil.ll +++ b/llvm/test/CodeGen/DirectX/embed-dxil.ll @@ -1,6 +1,7 @@ ; RUN: llc %s --filetype=asm -o - | FileCheck %s ; RUN: opt %s -dxil-embed -S -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC +target triple = "dxil-unknown-shadermodel6.5-library" define i32 @add(i32 %a, i32 %b) { %sum = add i32 %a, %b @@ -9,3 +10,34 @@ ; CHECK: @dx.dxil = private constant [[BC_TYPE:\[[0-9]+ x i8\]]] c"BC\C0\DE{{[^"]+}}", section "DXIL", align 4 ; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @dx.dxil], section "llvm.metadata" + +; This is using regex matches on some sizes, offsets and fields. These are all +; going to change as the DirectX backend continues to evolve and implement more +; features. Rather than extending this test to cover those future features, this +; test's matches are extremely fuzzy so that it won't break. + +; DXC: --- !dxcontainer +; DXC-NEXT: Header: +; DXC-NEXT: Hash: [ 0x0, 0x0, 0x0, +; DXC: Version: +; DXC-NEXT: Major: 1 +; DXC-NEXT: Minor: 0 +; DXC-NEXT: FileSize: [[#]] +; DXC-NEXT: PartCount: [[#]] +; DXC-NEXT: PartOffsets: [ {{[0-9, ]+}} ] +; DXC-NEXT: Parts: + +; In verifying the DXIL part, this test captures the size of the part, and +; derives the program header and dxil size fields from the part's size. + +; DXC: - Name: DXIL +; DXC-NEXT: Size: [[#SIZE:]] +; DXC-NEXT: Program: +; DXC-NEXT: MajorVersion: 6 +; DXC-NEXT: MinorVersion: 5 +; DXC-NEXT: ShaderKind: 6 +; DXC-NEXT: Size: [[#div(SIZE,4) - 2]] +; DXC-NEXT: DXILMajorVersion: [[#]] +; DXC-NEXT: DXILMinorVersion: [[#]] +; DXC-NEXT: DXILSize: [[#SIZE - 32]] +; DXC-NEXT: DXIL: [ 0x42, 0x43, 0xC0, 0xDE,