[llvm] 6c69427 - [SPIR-V](3/6) Add MC layer, object file support, and InstPrinter

Michal Paszkowski via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 19 16:28:09 PDT 2022


Author: Ilia Diachkov
Date: 2022-04-20T01:10:25+02:00
New Revision: 6c69427e880bf7bbcb711d24c65961f062256f2d

URL: https://github.com/llvm/llvm-project/commit/6c69427e880bf7bbcb711d24c65961f062256f2d
DIFF: https://github.com/llvm/llvm-project/commit/6c69427e880bf7bbcb711d24c65961f062256f2d.diff

LOG: [SPIR-V](3/6) Add MC layer, object file support, and InstPrinter

The patch adds SPIRV-specific MC layer implementation, SPIRV object
file support and SPIRVInstPrinter.

Differential Revision: https://reviews.llvm.org/D116462

Authors: Aleksandr Bezzubikov, Lewis Crawford, Ilia Diachkov,
Michal Paszkowski, Andrey Tretyakov, Konrad Trifunovic

Co-authored-by: Aleksandr Bezzubikov <zuban32s at gmail.com>
Co-authored-by: Ilia Diachkov <iliya.diyachkov at intel.com>
Co-authored-by: Michal Paszkowski <michal.paszkowski at outlook.com>
Co-authored-by: Andrey Tretyakov <andrey1.tretyakov at intel.com>
Co-authored-by: Konrad Trifunovic <konrad.trifunovic at intel.com>

Added: 
    llvm/include/llvm/MC/MCSPIRVObjectWriter.h
    llvm/include/llvm/MC/MCSPIRVStreamer.h
    llvm/include/llvm/MC/MCSectionSPIRV.h
    llvm/lib/MC/MCSPIRVStreamer.cpp
    llvm/lib/MC/SPIRVObjectWriter.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/CMakeLists.txt
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVAsmBackend.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.h
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCCodeEmitter.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.h
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVObjectTargetWriter.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.cpp
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.h

Modified: 
    llvm/include/llvm/ADT/Triple.h
    llvm/include/llvm/MC/MCContext.h
    llvm/include/llvm/MC/MCObjectFileInfo.h
    llvm/include/llvm/MC/MCSection.h
    llvm/include/llvm/MC/TargetRegistry.h
    llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/lib/MC/CMakeLists.txt
    llvm/lib/MC/MCAsmBackend.cpp
    llvm/lib/MC/MCContext.cpp
    llvm/lib/MC/MCObjectFileInfo.cpp
    llvm/lib/MC/MCParser/AsmParser.cpp
    llvm/lib/Support/Triple.cpp
    llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/lib/Target/SPIRV/CMakeLists.txt
    llvm/lib/Target/SPIRV/TargetInfo/SPIRVTargetInfo.cpp
    llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
    llvm/unittests/ADT/TripleTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h
index a42dbf853da0a..e140331b2b86f 100644
--- a/llvm/include/llvm/ADT/Triple.h
+++ b/llvm/include/llvm/ADT/Triple.h
@@ -266,6 +266,7 @@ class Triple {
     ELF,
     GOFF,
     MachO,
+    SPIRV,
     Wasm,
     XCOFF,
   };

diff  --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 861681551678d..b639473b2d8e7 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -52,6 +52,7 @@ class MCSectionCOFF;
 class MCSectionELF;
 class MCSectionGOFF;
 class MCSectionMachO;
+class MCSectionSPIRV;
 class MCSectionWasm;
 class MCSectionXCOFF;
 class MCStreamer;
@@ -81,6 +82,7 @@ class MCContext {
     IsELF,
     IsGOFF,
     IsCOFF,
+    IsSPIRV,
     IsWasm,
     IsXCOFF,
     IsDXContainer
@@ -129,6 +131,7 @@ class MCContext {
   SpecificBumpPtrAllocator<MCSectionELF> ELFAllocator;
   SpecificBumpPtrAllocator<MCSectionMachO> MachOAllocator;
   SpecificBumpPtrAllocator<MCSectionGOFF> GOFFAllocator;
+  SpecificBumpPtrAllocator<MCSectionSPIRV> SPIRVAllocator;
   SpecificBumpPtrAllocator<MCSectionWasm> WasmAllocator;
   SpecificBumpPtrAllocator<MCSectionXCOFF> XCOFFAllocator;
   SpecificBumpPtrAllocator<MCInst> MCInstAllocator;
@@ -630,6 +633,8 @@ class MCContext {
   getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym,
                             unsigned UniqueID = GenericSectionID);
 
+  MCSectionSPIRV *getSPIRVSection();
+
   MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K,
                                 unsigned Flags = 0) {
     return getWasmSection(Section, K, Flags, nullptr);

diff  --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index 8c13bb91c63d5..a4cb21636b57b 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -448,6 +448,7 @@ class MCObjectFileInfo {
   void initELFMCObjectFileInfo(const Triple &T, bool Large);
   void initGOFFMCObjectFileInfo(const Triple &T);
   void initCOFFMCObjectFileInfo(const Triple &T);
+  void initSPIRVMCObjectFileInfo(const Triple &T);
   void initWasmMCObjectFileInfo(const Triple &T);
   void initXCOFFMCObjectFileInfo(const Triple &T);
   MCSection *getDwarfComdatSection(const char *Name, uint64_t Hash) const;

diff  --git a/llvm/include/llvm/MC/MCSPIRVObjectWriter.h b/llvm/include/llvm/MC/MCSPIRVObjectWriter.h
new file mode 100644
index 0000000000000..a8baf96b83842
--- /dev/null
+++ b/llvm/include/llvm/MC/MCSPIRVObjectWriter.h
@@ -0,0 +1,40 @@
+//===-- llvm/MC/MCSPIRVObjectWriter.h - SPIR-V 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCSPIRVOBJECTWRITER_H
+#define LLVM_MC_MCSPIRVOBJECTWRITER_H
+
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+
+namespace llvm {
+
+class MCSPIRVObjectTargetWriter : public MCObjectTargetWriter {
+protected:
+  explicit MCSPIRVObjectTargetWriter() {}
+
+public:
+  Triple::ObjectFormatType getFormat() const override { return Triple::SPIRV; }
+  static bool classof(const MCObjectTargetWriter *W) {
+    return W->getFormat() == Triple::SPIRV;
+  }
+};
+
+/// Construct a new SPIR-V writer instance.
+///
+/// \param MOTW - The target specific SPIR-V writer subclass.
+/// \param OS - The stream to write to.
+/// \returns The constructed object writer.
+std::unique_ptr<MCObjectWriter>
+createSPIRVObjectWriter(std::unique_ptr<MCSPIRVObjectTargetWriter> MOTW,
+                        raw_pwrite_stream &OS);
+
+} // namespace llvm
+
+#endif

diff  --git a/llvm/include/llvm/MC/MCSPIRVStreamer.h b/llvm/include/llvm/MC/MCSPIRVStreamer.h
new file mode 100644
index 0000000000000..7366e0a9d82c4
--- /dev/null
+++ b/llvm/include/llvm/MC/MCSPIRVStreamer.h
@@ -0,0 +1,50 @@
+//===- MCSPIRVStreamer.h - MCStreamer SPIR-V Object File Interface -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Overrides MCObjectStreamer to disable all unnecessary features with stubs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCSPIRVSTREAMER_H
+#define LLVM_MC_MCSPIRVSTREAMER_H
+
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCObjectWriter.h"
+
+namespace llvm {
+class MCAssembler;
+class MCExpr;
+class MCInst;
+class raw_ostream;
+
+class MCSPIRVStreamer : public MCObjectStreamer {
+public:
+  MCSPIRVStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
+                  std::unique_ptr<MCObjectWriter> OW,
+                  std::unique_ptr<MCCodeEmitter> Emitter)
+      : MCObjectStreamer(Context, std::move(TAB), std::move(OW),
+                         std::move(Emitter)) {}
+
+  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
+    return false;
+  }
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+                        unsigned ByteAlignment) override {}
+  void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+                    uint64_t Size = 0, unsigned ByteAlignment = 0,
+                    SMLoc Loc = SMLoc()) override {}
+
+private:
+  void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
+};
+
+} // end namespace llvm
+
+#endif

diff  --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h
index ab038ab617bd9..46ccd9f85d9e0 100644
--- a/llvm/include/llvm/MC/MCSection.h
+++ b/llvm/include/llvm/MC/MCSection.h
@@ -46,7 +46,8 @@ class MCSection {
     SV_GOFF,
     SV_MachO,
     SV_Wasm,
-    SV_XCOFF
+    SV_XCOFF,
+    SV_SPIRV,
   };
 
   /// Express the state of bundle locked groups while emitting code.

diff  --git a/llvm/include/llvm/MC/MCSectionSPIRV.h b/llvm/include/llvm/MC/MCSectionSPIRV.h
new file mode 100644
index 0000000000000..6534599d2091c
--- /dev/null
+++ b/llvm/include/llvm/MC/MCSectionSPIRV.h
@@ -0,0 +1,41 @@
+//===- MCSectionSPIRV.h - SPIR-V Machine Code Sections ----------*- 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 declares the MCSectionSPIRV class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCSECTIONSPIRV_H
+#define LLVM_MC_MCSECTIONSPIRV_H
+
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/SectionKind.h"
+
+namespace llvm {
+
+class MCSymbol;
+
+class MCSectionSPIRV final : public MCSection {
+  friend class MCContext;
+
+  MCSectionSPIRV(SectionKind K, MCSymbol *Begin)
+      : MCSection(SV_SPIRV, "", K, Begin) {}
+  // TODO: Add StringRef Name to MCSectionSPIRV.
+
+public:
+  ~MCSectionSPIRV() = default;
+  void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
+                            raw_ostream &OS,
+                            const MCExpr *Subsection) const override {}
+  bool useCodeAlign() const override { return false; }
+  bool isVirtualSection() const override { return false; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_MC_MCSECTIONSPIRV_H

diff  --git a/llvm/include/llvm/MC/TargetRegistry.h b/llvm/include/llvm/MC/TargetRegistry.h
index e2d90b9169e0b..0b1a0fec667ff 100644
--- a/llvm/include/llvm/MC/TargetRegistry.h
+++ b/llvm/include/llvm/MC/TargetRegistry.h
@@ -109,6 +109,11 @@ MCStreamer *createXCOFFStreamer(MCContext &Ctx,
                                 std::unique_ptr<MCObjectWriter> &&OW,
                                 std::unique_ptr<MCCodeEmitter> &&CE,
                                 bool RelaxAll);
+MCStreamer *createSPIRVStreamer(MCContext &Ctx,
+                                std::unique_ptr<MCAsmBackend> &&TAB,
+                                std::unique_ptr<MCObjectWriter> &&OW,
+                                std::unique_ptr<MCCodeEmitter> &&CE,
+                                bool RelaxAll);
 
 MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx);
 
@@ -201,6 +206,11 @@ class Target {
                       std::unique_ptr<MCAsmBackend> &&TAB,
                       std::unique_ptr<MCObjectWriter> &&OW,
                       std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
+  using SPIRVStreamerCtorTy =
+      MCStreamer *(*)(const Triple &T, MCContext &Ctx,
+                      std::unique_ptr<MCAsmBackend> &&TAB,
+                      std::unique_ptr<MCObjectWriter> &&OW,
+                      std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
 
   using NullTargetStreamerCtorTy = MCTargetStreamer *(*)(MCStreamer &S);
   using AsmTargetStreamerCtorTy = MCTargetStreamer *(*)(
@@ -302,6 +312,7 @@ class Target {
   ELFStreamerCtorTy ELFStreamerCtorFn = nullptr;
   WasmStreamerCtorTy WasmStreamerCtorFn = nullptr;
   XCOFFStreamerCtorTy XCOFFStreamerCtorFn = nullptr;
+  SPIRVStreamerCtorTy SPIRVStreamerCtorFn = nullptr;
 
   /// Construction function for this target's null TargetStreamer, if
   /// registered (default = nullptr).
@@ -574,6 +585,14 @@ class Target {
         S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW),
                                 std::move(Emitter), RelaxAll);
       break;
+    case Triple::SPIRV:
+      if (SPIRVStreamerCtorFn)
+        S = SPIRVStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW),
+                                std::move(Emitter), RelaxAll);
+      else
+        S = createSPIRVStreamer(Ctx, std::move(TAB), std::move(OW),
+                                std::move(Emitter), RelaxAll);
+      break;
     }
     if (ObjectTargetStreamerCtorFn)
       ObjectTargetStreamerCtorFn(*S, STI);
@@ -954,6 +973,10 @@ struct TargetRegistry {
     T.ELFStreamerCtorFn = Fn;
   }
 
+  static void RegisterSPIRVStreamer(Target &T, Target::SPIRVStreamerCtorTy Fn) {
+    T.SPIRVStreamerCtorFn = Fn;
+  }
+
   static void RegisterWasmStreamer(Target &T, Target::WasmStreamerCtorTy Fn) {
     T.WasmStreamerCtorFn = Fn;
   }

diff  --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 84f60f47ee53b..8131c1cfb6f86 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -4890,6 +4890,9 @@ static const char *getSectionNameForBitcode(const Triple &T) {
   case Triple::GOFF:
     llvm_unreachable("GOFF is not yet implemented");
     break;
+  case Triple::SPIRV:
+    llvm_unreachable("SPIRV is not yet implemented");
+    break;
   case Triple::XCOFF:
     llvm_unreachable("XCOFF is not yet implemented");
     break;
@@ -4912,6 +4915,9 @@ static const char *getSectionNameForCommandline(const Triple &T) {
   case Triple::GOFF:
     llvm_unreachable("GOFF is not yet implemented");
     break;
+  case Triple::SPIRV:
+    llvm_unreachable("SPIRV is not yet implemented");
+    break;
   case Triple::XCOFF:
     llvm_unreachable("XCOFF is not yet implemented");
     break;

diff  --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index ca376b340e160..bb245172fdc9a 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -43,6 +43,7 @@ add_llvm_component_library(LLVMMC
   MCSectionWasm.cpp
   MCSectionXCOFF.cpp
   MCStreamer.cpp
+  MCSPIRVStreamer.cpp
   MCSubtargetInfo.cpp
   MCSymbol.cpp
   MCSymbolELF.cpp
@@ -58,6 +59,7 @@ add_llvm_component_library(LLVMMC
   MCXCOFFObjectTargetWriter.cpp
   MCXCOFFStreamer.cpp
   MachObjectWriter.cpp
+  SPIRVObjectWriter.cpp
   StringTableBuilder.cpp
   SubtargetFeature.cpp
   TargetRegistry.cpp

diff  --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp
index 7e2516758a05d..df07f06205401 100644
--- a/llvm/lib/MC/MCAsmBackend.cpp
+++ b/llvm/lib/MC/MCAsmBackend.cpp
@@ -13,6 +13,7 @@
 #include "llvm/MC/MCFixupKindInfo.h"
 #include "llvm/MC/MCMachObjectWriter.h"
 #include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSPIRVObjectWriter.h"
 #include "llvm/MC/MCWasmObjectWriter.h"
 #include "llvm/MC/MCWinCOFFObjectWriter.h"
 #include "llvm/MC/MCXCOFFObjectWriter.h"
@@ -39,6 +40,9 @@ MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
   case Triple::COFF:
     return createWinCOFFObjectWriter(
         cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS);
+  case Triple::SPIRV:
+    return createSPIRVObjectWriter(
+        cast<MCSPIRVObjectTargetWriter>(std::move(TW)), OS);
   case Triple::Wasm:
     return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)),
                                   OS);

diff  --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 1ebd80d86f3fc..827fe691fc44f 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -29,6 +29,7 @@
 #include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCSectionSPIRV.h"
 #include "llvm/MC/MCSectionWasm.h"
 #include "llvm/MC/MCSectionXCOFF.h"
 #include "llvm/MC/MCStreamer.h"
@@ -110,6 +111,9 @@ MCContext::MCContext(const Triple &TheTriple, const MCAsmInfo *mai,
   case Triple::DXContainer:
     Env = IsDXContainer;
     break;
+  case Triple::SPIRV:
+    Env = IsSPIRV;
+    break;
   case Triple::UnknownObjectFormat:
     report_fatal_error("Cannot initialize MC for unknown object file format.");
     break;
@@ -147,6 +151,7 @@ void MCContext::reset() {
   WasmAllocator.DestroyAll();
   XCOFFAllocator.DestroyAll();
   MCInstAllocator.DestroyAll();
+  SPIRVAllocator.DestroyAll();
 
   MCSubtargetAllocator.DestroyAll();
   InlineAsmUsedLabelNames.clear();
@@ -253,6 +258,9 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name,
     return createXCOFFSymbolImpl(Name, IsTemporary);
   case MCContext::IsDXContainer:
     break;
+  case MCContext::IsSPIRV:
+    return new (Name, *this)
+        MCSymbol(MCSymbol::SymbolKindUnset, Name, IsTemporary);
   }
   return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name,
                                     IsTemporary);
@@ -812,6 +820,21 @@ MCSectionXCOFF *MCContext::getXCOFFSection(
   return Result;
 }
 
+MCSectionSPIRV *MCContext::getSPIRVSection() {
+  MCSymbol *Begin = nullptr;
+  MCSectionSPIRV *Result = new (SPIRVAllocator.Allocate())
+      MCSectionSPIRV(SectionKind::getText(), Begin);
+
+  auto *F = new MCDataFragment();
+  Result->getFragmentList().insert(Result->begin(), F);
+  F->setParent(Result);
+
+  if (Begin)
+    Begin->setFragment(F);
+
+  return Result;
+}
+
 MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
   return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI);
 }

diff  --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 3da477d90887a..5bd3fcceadb94 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -19,6 +19,7 @@
 #include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCSectionGOFF.h"
 #include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCSectionSPIRV.h"
 #include "llvm/MC/MCSectionWasm.h"
 #include "llvm/MC/MCSectionXCOFF.h"
 #include "llvm/Support/Casting.h"
@@ -804,6 +805,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
                                         SectionKind::getReadOnly());
 }
 
+void MCObjectFileInfo::initSPIRVMCObjectFileInfo(const Triple &T) {
+  // Put everything in a single binary section.
+  TextSection = Ctx->getSPIRVSection();
+}
+
 void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
   TextSection = Ctx->getWasmSection(".text", SectionKind::getText());
   DataSection = Ctx->getWasmSection(".data", SectionKind::getData());
@@ -1032,6 +1038,9 @@ void MCObjectFileInfo::initMCObjectFileInfo(MCContext &MCCtx, bool PIC,
   case MCContext::IsGOFF:
     initGOFFMCObjectFileInfo(TheTriple);
     break;
+  case MCContext::IsSPIRV:
+    initSPIRVMCObjectFileInfo(TheTriple);
+    break;
   case MCContext::IsWasm:
     initWasmMCObjectFileInfo(TheTriple);
     break;
@@ -1055,6 +1064,7 @@ MCSection *MCObjectFileInfo::getDwarfComdatSection(const char *Name,
   case Triple::MachO:
   case Triple::COFF:
   case Triple::GOFF:
+  case Triple::SPIRV:
   case Triple::XCOFF:
   case Triple::DXContainer:
   case Triple::UnknownObjectFormat:

diff  --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index defc86e06aa60..8869faef30dfe 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -792,6 +792,10 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
   case MCContext::IsGOFF:
     PlatformParser.reset(createGOFFAsmParser());
     break;
+  case MCContext::IsSPIRV:
+    report_fatal_error(
+        "Need to implement createSPIRVAsmParser for SPIRV format.");
+    break;
   case MCContext::IsWasm:
     PlatformParser.reset(createWasmAsmParser());
     break;

diff  --git a/llvm/lib/MC/MCSPIRVStreamer.cpp b/llvm/lib/MC/MCSPIRVStreamer.cpp
new file mode 100644
index 0000000000000..863db7f36f29e
--- /dev/null
+++ b/llvm/lib/MC/MCSPIRVStreamer.cpp
@@ -0,0 +1,45 @@
+//===- lib/MC/MCSPIRVStreamer.cpp - SPIR-V Object Output ------*- 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 assembles .s files and emits SPIR-V .o object files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSPIRVStreamer.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/TargetRegistry.h"
+
+using namespace llvm;
+
+void MCSPIRVStreamer::emitInstToData(const MCInst &Inst,
+                                     const MCSubtargetInfo &STI) {
+  MCAssembler &Assembler = getAssembler();
+  SmallVector<MCFixup, 0> Fixups;
+  SmallString<256> Code;
+  raw_svector_ostream VecOS(Code);
+  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+
+  // Append the encoded instruction to the current data fragment (or create a
+  // new such fragment if the current fragment is not a data fragment).
+  MCDataFragment *DF = getOrCreateDataFragment();
+
+  DF->setHasInstructions(STI);
+  DF->getContents().append(Code.begin(), Code.end());
+}
+
+MCStreamer *llvm::createSPIRVStreamer(MCContext &Context,
+                                      std::unique_ptr<MCAsmBackend> &&MAB,
+                                      std::unique_ptr<MCObjectWriter> &&OW,
+                                      std::unique_ptr<MCCodeEmitter> &&CE,
+                                      bool RelaxAll) {
+  MCSPIRVStreamer *S = new MCSPIRVStreamer(Context, std::move(MAB),
+                                           std::move(OW), std::move(CE));
+  if (RelaxAll)
+    S->getAssembler().setRelaxAll(true);
+  return S;
+}

diff  --git a/llvm/lib/MC/SPIRVObjectWriter.cpp b/llvm/lib/MC/SPIRVObjectWriter.cpp
new file mode 100644
index 0000000000000..4a07740e8d143
--- /dev/null
+++ b/llvm/lib/MC/SPIRVObjectWriter.cpp
@@ -0,0 +1,76 @@
+//===- llvm/MC/MCSPIRVObjectWriter.cpp - SPIR-V 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCSPIRVObjectWriter.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/EndianStream.h"
+
+using namespace llvm;
+
+class SPIRVObjectWriter : public MCObjectWriter {
+  ::support::endian::Writer W;
+
+  /// The target specific SPIR-V writer instance.
+  std::unique_ptr<MCSPIRVObjectTargetWriter> TargetObjectWriter;
+
+public:
+  SPIRVObjectWriter(std::unique_ptr<MCSPIRVObjectTargetWriter> MOTW,
+                    raw_pwrite_stream &OS)
+      : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {}
+
+  ~SPIRVObjectWriter() override {}
+
+private:
+  void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
+                        const MCFragment *Fragment, const MCFixup &Fixup,
+                        MCValue Target, uint64_t &FixedValue) override {}
+
+  void executePostLayoutBinding(MCAssembler &Asm,
+                                const MCAsmLayout &Layout) override {}
+
+  uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+  void writeHeader(const MCAssembler &Asm);
+};
+
+void SPIRVObjectWriter::writeHeader(const MCAssembler &Asm) {
+  constexpr uint32_t MagicNumber = 0x07230203;
+
+  // TODO: set the version on a min-necessary basis (just like the translator
+  // does) requires some refactoring of MCAssembler::VersionInfoType.
+  constexpr uint32_t Major = 1;
+  constexpr uint32_t Minor = 0;
+  constexpr uint32_t VersionNumber = 0 | (Major << 16) | (Minor << 8);
+  // TODO: check if we could use anything other than 0 (spec allows).
+  constexpr uint32_t GeneratorMagicNumber = 0;
+  // TODO: do not hardcode this as well.
+  constexpr uint32_t Bound = 900;
+  constexpr uint32_t Schema = 0;
+
+  W.write<uint32_t>(MagicNumber);
+  W.write<uint32_t>(VersionNumber);
+  W.write<uint32_t>(GeneratorMagicNumber);
+  W.write<uint32_t>(Bound);
+  W.write<uint32_t>(Schema);
+}
+
+uint64_t SPIRVObjectWriter::writeObject(MCAssembler &Asm,
+                                        const MCAsmLayout &Layout) {
+  uint64_t StartOffset = W.OS.tell();
+  writeHeader(Asm);
+  for (const MCSection &S : Asm)
+    Asm.writeSectionData(W.OS, &S, Layout);
+  return W.OS.tell() - StartOffset;
+}
+
+std::unique_ptr<MCObjectWriter>
+llvm::createSPIRVObjectWriter(std::unique_ptr<MCSPIRVObjectTargetWriter> MOTW,
+                              raw_pwrite_stream &OS) {
+  return std::make_unique<SPIRVObjectWriter>(std::move(MOTW), OS);
+}

diff  --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp
index d70a4210cbff2..4aacad40c05e8 100644
--- a/llvm/lib/Support/Triple.cpp
+++ b/llvm/lib/Support/Triple.cpp
@@ -631,15 +631,16 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
 
 static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) {
   return StringSwitch<Triple::ObjectFormatType>(EnvironmentName)
-    // "xcoff" must come before "coff" because of the order-dependendent
-    // pattern matching.
-    .EndsWith("xcoff", Triple::XCOFF)
-    .EndsWith("coff", Triple::COFF)
-    .EndsWith("elf", Triple::ELF)
-    .EndsWith("goff", Triple::GOFF)
-    .EndsWith("macho", Triple::MachO)
-    .EndsWith("wasm", Triple::Wasm)
-    .Default(Triple::UnknownObjectFormat);
+      // "xcoff" must come before "coff" because of the order-dependendent
+      // pattern matching.
+      .EndsWith("xcoff", Triple::XCOFF)
+      .EndsWith("coff", Triple::COFF)
+      .EndsWith("elf", Triple::ELF)
+      .EndsWith("goff", Triple::GOFF)
+      .EndsWith("macho", Triple::MachO)
+      .EndsWith("wasm", Triple::Wasm)
+      .EndsWith("spirv", Triple::SPIRV)
+      .Default(Triple::UnknownObjectFormat);
 }
 
 static Triple::SubArchType parseSubArch(StringRef SubArchName) {
@@ -740,14 +741,24 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
 
 static StringRef getObjectFormatTypeName(Triple::ObjectFormatType Kind) {
   switch (Kind) {
-  case Triple::UnknownObjectFormat: return "";
-  case Triple::COFF:  return "coff";
-  case Triple::ELF:   return "elf";
-  case Triple::GOFF:  return "goff";
-  case Triple::MachO: return "macho";
-  case Triple::Wasm:  return "wasm";
-  case Triple::XCOFF: return "xcoff";
-  case Triple::DXContainer:  return "dxcontainer";
+  case Triple::UnknownObjectFormat:
+    return "";
+  case Triple::COFF:
+    return "coff";
+  case Triple::ELF:
+    return "elf";
+  case Triple::GOFF:
+    return "goff";
+  case Triple::MachO:
+    return "macho";
+  case Triple::Wasm:
+    return "wasm";
+  case Triple::XCOFF:
+    return "xcoff";
+  case Triple::DXContainer:
+    return "dxcontainer";
+  case Triple::SPIRV:
+    return "spirv";
   }
   llvm_unreachable("unknown object format type");
 }
@@ -831,8 +842,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
 
   case Triple::spirv32:
   case Triple::spirv64:
-    // TODO: In future this will be Triple::SPIRV.
-    return Triple::UnknownObjectFormat;
+    return Triple::SPIRV;
 
   case Triple::dxil:
     return Triple::DXContainer;

diff  --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index fdac90c0680a3..01c8d402c0d7c 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -6377,6 +6377,7 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
     CurrentFormat = WASM;
     break;
   case MCContext::IsGOFF:
+  case MCContext::IsSPIRV:
   case MCContext::IsXCOFF:
   case MCContext::IsDXContainer:
     llvm_unreachable("unexpected object format");

diff  --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt
index a0b3fe50df134..a6bef10bd4743 100644
--- a/llvm/lib/Target/SPIRV/CMakeLists.txt
+++ b/llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -18,6 +18,8 @@ add_llvm_target(SPIRVCodeGen
   LINK_COMPONENTS
   CodeGen
   Core
+  MC
+  SPIRVDesc
   SPIRVInfo
   Support
   Target
@@ -26,4 +28,5 @@ add_llvm_target(SPIRVCodeGen
   SPIRV
   )
 
+add_subdirectory(MCTargetDesc)
 add_subdirectory(TargetInfo)

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SPIRV/MCTargetDesc/CMakeLists.txt
new file mode 100644
index 0000000000000..fb56ffdd376b3
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_llvm_component_library(LLVMSPIRVDesc
+  SPIRVMCAsmInfo.cpp
+  SPIRVMCTargetDesc.cpp
+  SPIRVTargetStreamer.cpp
+  SPIRVAsmBackend.cpp
+  SPIRVMCCodeEmitter.cpp
+  SPIRVObjectTargetWriter.cpp
+  SPIRVInstPrinter.cpp
+
+  LINK_COMPONENTS
+  MC
+  SPIRVInfo
+  Support
+
+  ADD_TO_COMPONENT
+  SPIRV
+  )

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVAsmBackend.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVAsmBackend.cpp
new file mode 100644
index 0000000000000..4156a00264115
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVAsmBackend.cpp
@@ -0,0 +1,63 @@
+//===-- SPIRVAsmBackend.cpp - SPIR-V Assembler Backend ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SPIRVMCTargetDesc.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/EndianStream.h"
+
+using namespace llvm;
+
+namespace {
+
+class SPIRVAsmBackend : public MCAsmBackend {
+public:
+  SPIRVAsmBackend(support::endianness Endian) : MCAsmBackend(Endian) {}
+
+  void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+                  const MCValue &Target, MutableArrayRef<char> Data,
+                  uint64_t Value, bool IsResolved,
+                  const MCSubtargetInfo *STI) const override {}
+
+  std::unique_ptr<MCObjectTargetWriter>
+  createObjectTargetWriter() const override {
+    return createSPIRVObjectTargetWriter();
+  }
+
+  // No instruction requires relaxation.
+  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+                            const MCRelaxableFragment *DF,
+                            const MCAsmLayout &Layout) const override {
+    return false;
+  }
+
+  unsigned getNumFixupKinds() const override { return 1; }
+
+  bool mayNeedRelaxation(const MCInst &Inst,
+                         const MCSubtargetInfo &STI) const override {
+    return false;
+  }
+
+  void relaxInstruction(MCInst &Inst,
+                        const MCSubtargetInfo &STI) const override {}
+
+  bool writeNopData(raw_ostream &OS, uint64_t Count,
+                    const MCSubtargetInfo *STI) const override {
+    return false;
+  }
+};
+
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createSPIRVAsmBackend(const Target &T,
+                                          const MCSubtargetInfo &STI,
+                                          const MCRegisterInfo &MRI,
+                                          const MCTargetOptions &) {
+  return new SPIRVAsmBackend(support::little);
+}

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
new file mode 100644
index 0000000000000..dd3a5f0e82d50
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
@@ -0,0 +1,157 @@
+//===-- SPIRVInstPrinter.cpp - Output SPIR-V MCInsts as ASM -----*- 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 class prints a SPIR-V MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVInstPrinter.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+// Include the auto-generated portion of the assembly writer.
+#include "SPIRVGenAsmWriter.inc"
+
+void SPIRVInstPrinter::printRemainingVariableOps(const MCInst *MI,
+                                                 unsigned StartIndex,
+                                                 raw_ostream &O,
+                                                 bool SkipFirstSpace,
+                                                 bool SkipImmediates) {
+  const unsigned NumOps = MI->getNumOperands();
+  for (unsigned i = StartIndex; i < NumOps; ++i) {
+    if (!SkipImmediates || !MI->getOperand(i).isImm()) {
+      if (!SkipFirstSpace || i != StartIndex)
+        O << ' ';
+      printOperand(MI, i, O);
+    }
+  }
+}
+
+void SPIRVInstPrinter::printOpConstantVarOps(const MCInst *MI,
+                                             unsigned StartIndex,
+                                             raw_ostream &O) {
+  O << ' ';
+  if (MI->getNumOperands() - StartIndex == 2) { // Handle 64 bit literals.
+    uint64_t Imm = MI->getOperand(StartIndex).getImm();
+    Imm |= (MI->getOperand(StartIndex + 1).getImm() << 32);
+    O << Imm;
+  } else {
+    printRemainingVariableOps(MI, StartIndex, O, true, false);
+  }
+}
+
+void SPIRVInstPrinter::recordOpExtInstImport(const MCInst *MI) {
+  llvm_unreachable("Unimplemented recordOpExtInstImport");
+}
+
+void SPIRVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
+                                 StringRef Annot, const MCSubtargetInfo &STI,
+                                 raw_ostream &OS) {
+  printInstruction(MI, Address, OS);
+  printAnnotation(OS, Annot);
+}
+
+void SPIRVInstPrinter::printOpExtInst(const MCInst *MI, raw_ostream &O) {
+  llvm_unreachable("Unimplemented printOpExtInst");
+}
+
+void SPIRVInstPrinter::printOpDecorate(const MCInst *MI, raw_ostream &O) {
+  llvm_unreachable("Unimplemented printOpDecorate");
+}
+
+static void printExpr(const MCExpr *Expr, raw_ostream &O) {
+#ifndef NDEBUG
+  const MCSymbolRefExpr *SRE;
+
+  if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr))
+    SRE = cast<MCSymbolRefExpr>(BE->getLHS());
+  else
+    SRE = cast<MCSymbolRefExpr>(Expr);
+
+  MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
+
+  assert(Kind == MCSymbolRefExpr::VK_None);
+#endif
+  O << *Expr;
+}
+
+void SPIRVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
+                                    raw_ostream &O, const char *Modifier) {
+  assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
+  if (OpNo < MI->getNumOperands()) {
+    const MCOperand &Op = MI->getOperand(OpNo);
+    if (Op.isReg())
+      O << '%' << (Register::virtReg2Index(Op.getReg()) + 1);
+    else if (Op.isImm())
+      O << formatImm((int64_t)Op.getImm());
+    else if (Op.isDFPImm())
+      O << formatImm((double)Op.getDFPImm());
+    else if (Op.isExpr())
+      printExpr(Op.getExpr(), O);
+    else
+      llvm_unreachable("Unexpected operand type");
+  }
+}
+
+void SPIRVInstPrinter::printStringImm(const MCInst *MI, unsigned OpNo,
+                                      raw_ostream &O) {
+  llvm_unreachable("Unimplemented printStringImm");
+}
+
+void SPIRVInstPrinter::printExtInst(const MCInst *MI, unsigned OpNo,
+                                    raw_ostream &O) {
+  llvm_unreachable("Unimplemented printExtInst");
+}
+
+// Methods for printing textual names of SPIR-V enums.
+#define GEN_INSTR_PRINTER_IMPL(EnumName)                                       \
+  void SPIRVInstPrinter::print##EnumName(const MCInst *MI, unsigned OpNo,      \
+                                         raw_ostream &O) {                     \
+    llvm_unreachable("Unimplemented print" #EnumName);                         \
+  }
+GEN_INSTR_PRINTER_IMPL(Capability)
+GEN_INSTR_PRINTER_IMPL(SourceLanguage)
+GEN_INSTR_PRINTER_IMPL(ExecutionModel)
+GEN_INSTR_PRINTER_IMPL(AddressingModel)
+GEN_INSTR_PRINTER_IMPL(MemoryModel)
+GEN_INSTR_PRINTER_IMPL(ExecutionMode)
+GEN_INSTR_PRINTER_IMPL(StorageClass)
+GEN_INSTR_PRINTER_IMPL(Dim)
+GEN_INSTR_PRINTER_IMPL(SamplerAddressingMode)
+GEN_INSTR_PRINTER_IMPL(SamplerFilterMode)
+GEN_INSTR_PRINTER_IMPL(ImageFormat)
+GEN_INSTR_PRINTER_IMPL(ImageChannelOrder)
+GEN_INSTR_PRINTER_IMPL(ImageChannelDataType)
+GEN_INSTR_PRINTER_IMPL(ImageOperand)
+GEN_INSTR_PRINTER_IMPL(FPFastMathMode)
+GEN_INSTR_PRINTER_IMPL(FPRoundingMode)
+GEN_INSTR_PRINTER_IMPL(LinkageType)
+GEN_INSTR_PRINTER_IMPL(AccessQualifier)
+GEN_INSTR_PRINTER_IMPL(FunctionParameterAttribute)
+GEN_INSTR_PRINTER_IMPL(Decoration)
+GEN_INSTR_PRINTER_IMPL(BuiltIn)
+GEN_INSTR_PRINTER_IMPL(SelectionControl)
+GEN_INSTR_PRINTER_IMPL(LoopControl)
+GEN_INSTR_PRINTER_IMPL(FunctionControl)
+GEN_INSTR_PRINTER_IMPL(MemorySemantics)
+GEN_INSTR_PRINTER_IMPL(MemoryOperand)
+GEN_INSTR_PRINTER_IMPL(Scope)
+GEN_INSTR_PRINTER_IMPL(GroupOperation)
+GEN_INSTR_PRINTER_IMPL(KernelEnqueueFlags)
+GEN_INSTR_PRINTER_IMPL(KernelProfilingInfo)

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
new file mode 100644
index 0000000000000..cd3b6f1e6d665
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
@@ -0,0 +1,94 @@
+//===-- SPIRVInstPrinter.h - Output SPIR-V MCInsts as ASM -------*- 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 class prints a SPIR-V MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_INSTPRINTER_SPIRVINSTPRINTER_H
+#define LLVM_LIB_TARGET_SPIRV_INSTPRINTER_SPIRVINSTPRINTER_H
+
+#include "llvm/MC/MCInstPrinter.h"
+
+namespace llvm {
+class SPIRVInstPrinter : public MCInstPrinter {
+private:
+  void recordOpExtInstImport(const MCInst *MI);
+
+public:
+  using MCInstPrinter::MCInstPrinter;
+
+  void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+                 const MCSubtargetInfo &STI, raw_ostream &OS) override;
+  void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
+                    const char *Modifier = nullptr);
+
+  void printStringImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printOpDecorate(const MCInst *MI, raw_ostream &O);
+  void printOpExtInst(const MCInst *MI, raw_ostream &O);
+  void printRemainingVariableOps(const MCInst *MI, unsigned StartIndex,
+                                 raw_ostream &O, bool SkipFirstSpace = false,
+                                 bool SkipImmediates = false);
+  void printOpConstantVarOps(const MCInst *MI, unsigned StartIndex,
+                             raw_ostream &O);
+
+  void printExtInst(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  // SPIR-V enumerations printing.
+  void printCapability(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printSourceLanguage(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printExecutionModel(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printAddressingModel(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printMemoryModel(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printExecutionMode(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printStorageClass(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printDim(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printSamplerAddressingMode(const MCInst *MI, unsigned OpNo,
+                                  raw_ostream &O);
+  void printSamplerFilterMode(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printImageFormat(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printImageChannelOrder(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printImageChannelDataType(const MCInst *MI, unsigned OpNo,
+                                 raw_ostream &O);
+  void printImageOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printFPFastMathMode(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printFPRoundingMode(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printLinkageType(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printAccessQualifier(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printFunctionParameterAttribute(const MCInst *MI, unsigned OpNo,
+                                       raw_ostream &O);
+
+  void printDecoration(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printBuiltIn(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printSelectionControl(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printLoopControl(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printFunctionControl(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printMemorySemantics(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printMemoryOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printScope(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printGroupOperation(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  void printKernelEnqueueFlags(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printKernelProfilingInfo(const MCInst *MI, unsigned OpNo,
+                                raw_ostream &O);
+  // Autogenerated by tblgen.
+  std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
+  void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
+  static const char *getRegisterName(unsigned RegNo);
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_INSTPRINTER_SPIRVINSTPRINTER_H

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp
new file mode 100644
index 0000000000000..2f3462f419e5a
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp
@@ -0,0 +1,34 @@
+//===-- SPIRVMCAsmInfo.h - SPIR-V asm properties --------------*- 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 the declarations of the SPIRVMCAsmInfo properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVMCAsmInfo.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace llvm;
+
+SPIRVMCAsmInfo::SPIRVMCAsmInfo(const Triple &TT,
+                               const MCTargetOptions &Options) {
+  IsLittleEndian = true;
+
+  HasSingleParameterDotFile = false;
+  HasDotTypeDotSizeDirective = false;
+
+  MinInstAlignment = 4;
+
+  CodePointerSize = 4;
+  CommentString = ";";
+  HasFunctionAlignment = false;
+}
+
+bool SPIRVMCAsmInfo::shouldOmitSectionDirective(StringRef SectionName) const {
+  return true;
+}

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.h
new file mode 100644
index 0000000000000..08e579e1c32c8
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.h
@@ -0,0 +1,29 @@
+//===-- SPIRVMCAsmInfo.h - SPIR-V asm properties --------------*- 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 the declaration of the SPIRVMCAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCASMINFO_H
+#define LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCASMINFO_H
+
+#include "llvm/MC/MCAsmInfo.h"
+
+namespace llvm {
+
+class Triple;
+
+class SPIRVMCAsmInfo : public MCAsmInfo {
+public:
+  explicit SPIRVMCAsmInfo(const Triple &TT, const MCTargetOptions &Options);
+  bool shouldOmitSectionDirective(StringRef SectionName) const override;
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCASMINFO_H

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCCodeEmitter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCCodeEmitter.cpp
new file mode 100644
index 0000000000000..d953bc590473f
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCCodeEmitter.cpp
@@ -0,0 +1,132 @@
+//===-- SPIRVMCCodeEmitter.cpp - Emit SPIR-V machine code -------*- 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 implements the SPIRVMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SPIRVMCTargetDesc.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "spirv-mccodeemitter"
+
+namespace {
+
+class SPIRVMCCodeEmitter : public MCCodeEmitter {
+  const MCInstrInfo &MCII;
+
+public:
+  SPIRVMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {}
+  SPIRVMCCodeEmitter(const SPIRVMCCodeEmitter &) = delete;
+  void operator=(const SPIRVMCCodeEmitter &) = delete;
+  ~SPIRVMCCodeEmitter() override = default;
+
+  // getBinaryCodeForInstr - TableGen'erated function for getting the
+  // binary encoding for an instruction.
+  uint64_t getBinaryCodeForInstr(const MCInst &MI,
+                                 SmallVectorImpl<MCFixup> &Fixups,
+                                 const MCSubtargetInfo &STI) const;
+
+  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
+                         SmallVectorImpl<MCFixup> &Fixups,
+                         const MCSubtargetInfo &STI) const override;
+
+private:
+  FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
+  void
+  verifyInstructionPredicates(const MCInst &MI,
+                              const FeatureBitset &AvailableFeatures) const;
+};
+
+} // end anonymous namespace
+
+MCCodeEmitter *llvm::createSPIRVMCCodeEmitter(const MCInstrInfo &MCII,
+                                              MCContext &Ctx) {
+  return new SPIRVMCCodeEmitter(MCII);
+}
+
+using EndianWriter = support::endian::Writer;
+
+// Check if the instruction has a type argument for operand 1, and defines an ID
+// output register in operand 0. If so, we need to swap operands 0 and 1 so the
+// type comes first in the output, despide coming second in the MCInst.
+static bool hasType(const MCInst &MI, const MCInstrInfo &MII) {
+  MCInstrDesc MCDesc = MII.get(MI.getOpcode());
+  // If we define an output, and have at least one other argument.
+  if (MCDesc.getNumDefs() == 1 && MCDesc.getNumOperands() >= 2) {
+    // Check if we define an ID, and take a type as operand 1.
+    auto DefOpInfo = MCDesc.opInfo_begin();
+    auto FirstArgOpInfo = MCDesc.opInfo_begin() + 1;
+    return (DefOpInfo->RegClass == SPIRV::IDRegClassID ||
+            DefOpInfo->RegClass == SPIRV::ANYIDRegClassID) &&
+           FirstArgOpInfo->RegClass == SPIRV::TYPERegClassID;
+  }
+  return false;
+}
+
+static void emitOperand(const MCOperand &Op, EndianWriter &OSE) {
+  if (Op.isReg()) {
+    // Emit the id index starting at 1 (0 is an invalid index).
+    OSE.write<uint32_t>(Register::virtReg2Index(Op.getReg()) + 1);
+  } else if (Op.isImm()) {
+    OSE.write<uint32_t>(Op.getImm());
+  } else {
+    llvm_unreachable("Unexpected operand type in VReg");
+  }
+}
+
+// Emit the type in operand 1 before the ID in operand 0 it defines, and all
+// remaining operands in the order they come naturally.
+static void emitTypedInstrOperands(const MCInst &MI, EndianWriter &OSE) {
+  unsigned NumOps = MI.getNumOperands();
+  emitOperand(MI.getOperand(1), OSE);
+  emitOperand(MI.getOperand(0), OSE);
+  for (unsigned i = 2; i < NumOps; ++i)
+    emitOperand(MI.getOperand(i), OSE);
+}
+
+// Emit operands in the order they come naturally.
+static void emitUntypedInstrOperands(const MCInst &MI, EndianWriter &OSE) {
+  for (const auto &Op : MI)
+    emitOperand(Op, OSE);
+}
+
+void SPIRVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
+                                           SmallVectorImpl<MCFixup> &Fixups,
+                                           const MCSubtargetInfo &STI) const {
+  auto Features = computeAvailableFeatures(STI.getFeatureBits());
+  verifyInstructionPredicates(MI, Features);
+
+  EndianWriter OSE(OS, support::little);
+
+  // Encode the first 32 SPIR-V bytes with the number of args and the opcode.
+  const uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+  const uint32_t NumWords = MI.getNumOperands() + 1;
+  const uint32_t FirstWord = (NumWords << 16) | OpCode;
+  OSE.write<uint32_t>(FirstWord);
+
+  // Emit the instruction arguments (emitting the output type first if present).
+  if (hasType(MI, MCII))
+    emitTypedInstrOperands(MI, OSE);
+  else
+    emitUntypedInstrOperands(MI, OSE);
+}
+
+#define ENABLE_INSTR_PREDICATE_VERIFIER
+#include "SPIRVGenMCCodeEmitter.inc"

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.cpp
new file mode 100644
index 0000000000000..6b8b4a73af928
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.cpp
@@ -0,0 +1,102 @@
+//===-- SPIRVMCTargetDesc.cpp - SPIR-V Target Descriptions ----*- 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 provides SPIR-V specific target descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVMCTargetDesc.h"
+#include "SPIRVInstPrinter.h"
+#include "SPIRVMCAsmInfo.h"
+#include "SPIRVTargetStreamer.h"
+#include "TargetInfo/SPIRVTargetInfo.h"
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/TargetRegistry.h"
+
+#define GET_INSTRINFO_MC_DESC
+#include "SPIRVGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_MC_DESC
+#include "SPIRVGenSubtargetInfo.inc"
+
+#define GET_REGINFO_MC_DESC
+#include "SPIRVGenRegisterInfo.inc"
+
+using namespace llvm;
+
+static MCInstrInfo *createSPIRVMCInstrInfo() {
+  MCInstrInfo *X = new MCInstrInfo();
+  InitSPIRVMCInstrInfo(X);
+  return X;
+}
+
+static MCRegisterInfo *createSPIRVMCRegisterInfo(const Triple &TT) {
+  MCRegisterInfo *X = new MCRegisterInfo();
+  return X;
+}
+
+static MCSubtargetInfo *
+createSPIRVMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
+  return createSPIRVMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
+}
+
+static MCStreamer *
+createSPIRVMCStreamer(const Triple &T, MCContext &Ctx,
+                      std::unique_ptr<MCAsmBackend> &&MAB,
+                      std::unique_ptr<MCObjectWriter> &&OW,
+                      std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) {
+  return createSPIRVStreamer(Ctx, std::move(MAB), std::move(OW),
+                             std::move(Emitter), RelaxAll);
+}
+
+static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S,
+                                                 formatted_raw_ostream &,
+                                                 MCInstPrinter *, bool) {
+  return new SPIRVTargetStreamer(S);
+}
+
+static MCInstPrinter *createSPIRVMCInstPrinter(const Triple &T,
+                                               unsigned SyntaxVariant,
+                                               const MCAsmInfo &MAI,
+                                               const MCInstrInfo &MII,
+                                               const MCRegisterInfo &MRI) {
+  assert(SyntaxVariant == 0);
+  return new SPIRVInstPrinter(MAI, MII, MRI);
+}
+
+namespace {
+
+class SPIRVMCInstrAnalysis : public MCInstrAnalysis {
+public:
+  explicit SPIRVMCInstrAnalysis(const MCInstrInfo *Info)
+      : MCInstrAnalysis(Info) {}
+};
+
+} // end anonymous namespace
+
+static MCInstrAnalysis *createSPIRVInstrAnalysis(const MCInstrInfo *Info) {
+  return new SPIRVMCInstrAnalysis(Info);
+}
+
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTargetMC() {
+  for (Target *T : {&getTheSPIRV32Target(), &getTheSPIRV64Target()}) {
+    RegisterMCAsmInfo<SPIRVMCAsmInfo> X(*T);
+    TargetRegistry::RegisterMCInstrInfo(*T, createSPIRVMCInstrInfo);
+    TargetRegistry::RegisterMCRegInfo(*T, createSPIRVMCRegisterInfo);
+    TargetRegistry::RegisterMCSubtargetInfo(*T, createSPIRVMCSubtargetInfo);
+    TargetRegistry::RegisterSPIRVStreamer(*T, createSPIRVMCStreamer);
+    TargetRegistry::RegisterMCInstPrinter(*T, createSPIRVMCInstPrinter);
+    TargetRegistry::RegisterMCInstrAnalysis(*T, createSPIRVInstrAnalysis);
+    TargetRegistry::RegisterMCCodeEmitter(*T, createSPIRVMCCodeEmitter);
+    TargetRegistry::RegisterMCAsmBackend(*T, createSPIRVAsmBackend);
+    TargetRegistry::RegisterAsmTargetStreamer(*T, createTargetAsmStreamer);
+  }
+}

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.h
new file mode 100644
index 0000000000000..4009fa96aa68b
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCTargetDesc.h
@@ -0,0 +1,52 @@
+//===-- SPIRVMCTargetDesc.h - SPIR-V Target Descriptions --------*- 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 provides SPIR-V specific target descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCTARGETDESC_H
+#define LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCTARGETDESC_H
+
+#include "llvm/Support/DataTypes.h"
+#include <memory>
+
+namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCObjectTargetWriter;
+class MCRegisterInfo;
+class MCSubtargetInfo;
+class MCTargetOptions;
+class Target;
+
+MCCodeEmitter *createSPIRVMCCodeEmitter(const MCInstrInfo &MCII,
+                                        MCContext &Ctx);
+
+MCAsmBackend *createSPIRVAsmBackend(const Target &T, const MCSubtargetInfo &STI,
+                                    const MCRegisterInfo &MRI,
+                                    const MCTargetOptions &Options);
+
+std::unique_ptr<MCObjectTargetWriter> createSPIRVObjectTargetWriter();
+} // namespace llvm
+
+// Defines symbolic names for SPIR-V registers.  This defines a mapping from
+// register name to register number.
+#define GET_REGINFO_ENUM
+#include "SPIRVGenRegisterInfo.inc"
+
+// Defines symbolic names for the SPIR-V instructions.
+#define GET_INSTRINFO_ENUM
+#include "SPIRVGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "SPIRVGenSubtargetInfo.inc"
+
+#endif // LLVM_LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVMCTARGETDESC_H

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVObjectTargetWriter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVObjectTargetWriter.cpp
new file mode 100644
index 0000000000000..685168b4073d7
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVObjectTargetWriter.cpp
@@ -0,0 +1,25 @@
+//===- SPIRVObjectTargetWriter.cpp - SPIR-V Object Target 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVMCTargetDesc.h"
+#include "llvm/MC/MCSPIRVObjectWriter.h"
+
+using namespace llvm;
+
+namespace {
+
+class SPIRVObjectTargetWriter : public MCSPIRVObjectTargetWriter {
+public:
+  SPIRVObjectTargetWriter() = default;
+};
+
+} // namespace
+
+std::unique_ptr<MCObjectTargetWriter> llvm::createSPIRVObjectTargetWriter() {
+  return std::make_unique<SPIRVObjectTargetWriter>();
+}

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.cpp
new file mode 100644
index 0000000000000..0a318e0e01e59
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.cpp
@@ -0,0 +1,18 @@
+//=====- SPIRVTargetStreamer.cpp - SPIRVTargetStreamer class ------------=====//
+//
+// 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 implements the SPIRVTargetStreamer class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVTargetStreamer.h"
+
+using namespace llvm;
+
+SPIRVTargetStreamer::SPIRVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
+SPIRVTargetStreamer::~SPIRVTargetStreamer() {}

diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.h
new file mode 100644
index 0000000000000..2cc8f50aba679
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVTargetStreamer.h
@@ -0,0 +1,28 @@
+//===-- SPIRVTargetStreamer.h - SPIRV Target Streamer ----------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVTARGETSTREAMER_H
+#define LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVTARGETSTREAMER_H
+
+#include "llvm/MC/MCStreamer.h"
+
+namespace llvm {
+
+class MCSection;
+
+class SPIRVTargetStreamer : public MCTargetStreamer {
+public:
+  SPIRVTargetStreamer(MCStreamer &S);
+  ~SPIRVTargetStreamer() override;
+
+  void changeSection(const MCSection *CurSection, MCSection *Section,
+                     const MCExpr *SubSection, raw_ostream &OS) override{};
+};
+} // namespace llvm
+
+#endif // LIB_TARGET_SPIRV_MCTARGETDESC_SPIRVTARGETSTREAMER_H_

diff  --git a/llvm/lib/Target/SPIRV/TargetInfo/SPIRVTargetInfo.cpp b/llvm/lib/Target/SPIRV/TargetInfo/SPIRVTargetInfo.cpp
index 12ca131477a7b..fb7cab4fe779c 100644
--- a/llvm/lib/Target/SPIRV/TargetInfo/SPIRVTargetInfo.cpp
+++ b/llvm/lib/Target/SPIRV/TargetInfo/SPIRVTargetInfo.cpp
@@ -26,8 +26,3 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTargetInfo() {
   RegisterTarget<Triple::spirv64> Y(getTheSPIRV64Target(), "spirv64",
                                     "SPIR-V 64-bit", "SPIRV");
 }
-
-// FIXME: Temporary stub - this function must be defined for linking
-// to succeed and will be called unconditionally by llc, so must be a no-op.
-// Remove once this function is properly implemented.
-extern "C" void LLVMInitializeSPIRVTargetMC() {}

diff  --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 9216e8d274232..7dfe98c1a92a0 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -2110,6 +2110,7 @@ StringRef ModuleAddressSanitizer::getGlobalMetadataSection() const {
   case Triple::MachO: return "__DATA,__asan_globals,regular";
   case Triple::Wasm:
   case Triple::GOFF:
+  case Triple::SPIRV:
   case Triple::XCOFF:
   case Triple::DXContainer:
     report_fatal_error(

diff  --git a/llvm/unittests/ADT/TripleTest.cpp b/llvm/unittests/ADT/TripleTest.cpp
index 30785292029cd..19e5978acedf3 100644
--- a/llvm/unittests/ADT/TripleTest.cpp
+++ b/llvm/unittests/ADT/TripleTest.cpp
@@ -999,11 +999,13 @@ TEST(TripleTest, BitWidthPredicates) {
   EXPECT_FALSE(T.isArch16Bit());
   EXPECT_TRUE(T.isArch32Bit());
   EXPECT_FALSE(T.isArch64Bit());
+  EXPECT_TRUE(T.isSPIRV());
 
   T.setArch(Triple::spirv64);
   EXPECT_FALSE(T.isArch16Bit());
   EXPECT_FALSE(T.isArch32Bit());
   EXPECT_TRUE(T.isArch64Bit());
+  EXPECT_TRUE(T.isSPIRV());
 
   T.setArch(Triple::sparc);
   EXPECT_FALSE(T.isArch16Bit());
@@ -1671,6 +1673,9 @@ TEST(TripleTest, FileFormat) {
   EXPECT_EQ(Triple::ELF, Triple("csky-unknown-unknown").getObjectFormat());
   EXPECT_EQ(Triple::ELF, Triple("csky-unknown-linux").getObjectFormat());
 
+  EXPECT_EQ(Triple::SPIRV, Triple("spirv32-unknown-unknown").getObjectFormat());
+  EXPECT_EQ(Triple::SPIRV, Triple("spirv64-unknown-unknown").getObjectFormat());
+
   EXPECT_EQ(Triple::ELF,
             Triple("loongarch32-unknown-unknown").getObjectFormat());
   EXPECT_EQ(Triple::ELF, Triple("loongarch64-unknown-linux").getObjectFormat());
@@ -1702,6 +1707,9 @@ TEST(TripleTest, FileFormat) {
 
   T.setObjectFormat(Triple::GOFF);
   EXPECT_EQ(Triple::GOFF, T.getObjectFormat());
+
+  T.setObjectFormat(Triple::SPIRV);
+  EXPECT_EQ(Triple::SPIRV, T.getObjectFormat());
 }
 
 TEST(TripleTest, NormalizeWindows) {


        


More information about the llvm-commits mailing list