diff options
author | tltao <tony.le.tao@gmail.com> | 2025-03-21 11:36:35 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-21 11:36:35 -0400 |
commit | f7a32b85b56b20382a8100498874ef9d3c5b0b77 (patch) | |
tree | 71a96e145a409a59b2fd126be43b9e50d04a903e /llvm/lib | |
parent | d4ce57cb98dbe753d246ae5395cc5ac6da8afa88 (diff) | |
download | llvm-f7a32b85b56b20382a8100498874ef9d3c5b0b77.zip llvm-f7a32b85b56b20382a8100498874ef9d3c5b0b77.tar.gz llvm-f7a32b85b56b20382a8100498874ef9d3c5b0b77.tar.bz2 |
[MC][SystemZ] Introduce Target Specific HLASM Streamer for z/OS (#130535)
A more fleshed out version of a previous PR
https://github.com/llvm/llvm-project/pull/107415. The goal is to provide
platforms an alternative to the current MCAsmStreamer which only
supports the GNU Asm syntax.
RFC:
https://discourse.llvm.org/t/rfc-llvm-add-support-for-target-specific-asm-streamer/85095
---------
Co-authored-by: Tony Tao <tonytao@ca.ibm.com>
Diffstat (limited to 'llvm/lib')
7 files changed, 521 insertions, 4 deletions
diff --git a/llvm/lib/MC/TargetRegistry.cpp b/llvm/lib/MC/TargetRegistry.cpp index 8f25326..ec1c5a9 100644 --- a/llvm/lib/MC/TargetRegistry.cpp +++ b/llvm/lib/MC/TargetRegistry.cpp @@ -92,8 +92,14 @@ MCStreamer *Target::createAsmStreamer(MCContext &Ctx, std::unique_ptr<MCCodeEmitter> CE, std::unique_ptr<MCAsmBackend> TAB) const { formatted_raw_ostream &OSRef = *OS; - MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IP, - std::move(CE), std::move(TAB)); + MCStreamer *S; + if (AsmStreamerCtorFn) + S = AsmStreamerCtorFn(Ctx, std::move(OS), IP, std::move(CE), + std::move(TAB)); + else + S = llvm::createAsmStreamer(Ctx, std::move(OS), IP, std::move(CE), + std::move(TAB)); + createAsmTargetStreamer(*S, OSRef, IP); return S; } diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt index 9c00706..c954456 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_component_library(LLVMSystemZDesc SystemZELFObjectWriter.cpp SystemZGNUInstPrinter.cpp SystemZGOFFObjectWriter.cpp + SystemZHLASMAsmStreamer.cpp SystemZHLASMInstPrinter.cpp SystemZInstPrinterCommon.cpp SystemZMCAsmBackend.cpp @@ -9,6 +10,7 @@ add_llvm_component_library(LLVMSystemZDesc SystemZMCCodeEmitter.cpp SystemZMCExpr.cpp SystemZMCTargetDesc.cpp + SystemZTargetStreamer.cpp LINK_COMPONENTS CodeGenTypes diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp new file mode 100644 index 0000000..165feec --- /dev/null +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp @@ -0,0 +1,282 @@ +//===- SystemZHLASMAsmStreamer.cpp - HLASM Assembly Text Output -----------===// +// +// 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 "SystemZHLASMAsmStreamer.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Signals.h" +#include <sstream> + +#include <cmath> + +void SystemZHLASMAsmStreamer::EmitEOL() { + // Comments are emitted on a new line before the instruction. + if (IsVerboseAsm) + EmitComment(); + + std::istringstream Stream(Str); + SmallVector<std::string> Lines; + std::string Line; + while (std::getline(Stream, Line, '\n')) + Lines.push_back(Line); + + for (auto S : Lines) { + if (LLVM_LIKELY(S.length() < ContIndicatorColumn)) { + FOS << S; + // Each line in HLASM must fill the full 80 characters. + FOS.PadToColumn(InstLimit); + FOS << "\n"; + } else { + // If last character before end of the line is not a space + // we must insert an additional non-space character that + // is not part of the statement coding. We just reuse + // the existing character by making the new substring start + // 1 character sooner, thus "duplicating" that character + // If The last character is a space. We insert an X instead. + std::string TmpSubStr = S.substr(0, ContIndicatorColumn); + if (!TmpSubStr.compare(ContIndicatorColumn - 1, 1, " ")) + TmpSubStr.replace(ContIndicatorColumn - 1, 1, "X"); + + FOS << TmpSubStr; + FOS.PadToColumn(InstLimit); + FOS << "\n"; + + size_t Emitted = ContIndicatorColumn - 1; + + while (Emitted < S.length()) { + if ((S.length() - Emitted) < ContLen) + TmpSubStr = S.substr(Emitted, S.length()); + else { + TmpSubStr = S.substr(Emitted, ContLen); + if (!TmpSubStr.compare(ContLen - 1, 1, " ")) + TmpSubStr.replace(ContLen - 1, 1, "X"); + } + FOS.PadToColumn(ContStartColumn); + FOS << TmpSubStr; + FOS.PadToColumn(InstLimit); + FOS << "\n"; + Emitted += ContLen - 1; + } + } + } + Str.clear(); +} + +void SystemZHLASMAsmStreamer::changeSection(MCSection *Section, + uint32_t Subsection) { + Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS, + Subsection); + MCStreamer::changeSection(Section, Subsection); +} + +void SystemZHLASMAsmStreamer::emitAlignmentDS(uint64_t ByteAlignment, + std::optional<int64_t> Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) { + if (!isPowerOf2_64(ByteAlignment)) + report_fatal_error("Only power-of-two alignments are supported "); + + OS << " DS 0"; + switch (ValueSize) { + default: + llvm_unreachable("Invalid size for machine code value!"); + case 1: + OS << "B"; + break; + case 2: + OS << "H"; + break; + case 4: + OS << "F"; + break; + case 8: + OS << "D"; + break; + case 16: + OS << "Q"; + break; + } + + EmitEOL(); +} + +void SystemZHLASMAsmStreamer::AddComment(const Twine &T, bool EOL) { + if (!IsVerboseAsm) + return; + + T.toVector(CommentToEmit); + + if (EOL) + CommentToEmit.push_back('\n'); // Place comment in a new line. +} + +void SystemZHLASMAsmStreamer::EmitComment() { + if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) + return; + + StringRef Comments = CommentToEmit; + + assert(Comments.back() == '\n' && "Comment array not newline terminated"); + do { + // Emit a line of comments, but not exceeding 80 characters. + size_t Position = std::min(InstLimit - 2, Comments.find('\n')); + FOS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) + << '\n'; + + if (Comments[Position] == '\n') + Position++; + Comments = Comments.substr(Position); + } while (!Comments.empty()); + + CommentToEmit.clear(); +} + +void SystemZHLASMAsmStreamer::emitValueToAlignment(Align Alignment, + int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) { + emitAlignmentDS(Alignment.value(), Value, ValueSize, MaxBytesToEmit); +} + +void SystemZHLASMAsmStreamer::emitCodeAlignment(Align Alignment, + const MCSubtargetInfo *STI, + unsigned MaxBytesToEmit) { + // Emit with a text fill value. + if (MAI->getTextAlignFillValue()) + emitAlignmentDS(Alignment.value(), MAI->getTextAlignFillValue(), 1, + MaxBytesToEmit); + else + emitAlignmentDS(Alignment.value(), std::nullopt, 1, MaxBytesToEmit); +} + +void SystemZHLASMAsmStreamer::emitBytes(StringRef Data) { + assert(getCurrentSectionOnly() && + "Cannot emit contents before setting section!"); + if (Data.empty()) + return; + + OS << " DC "; + size_t Len = Data.size(); + SmallVector<uint8_t> Chars; + Chars.resize(Len); + OS << "XL" << Len; + uint32_t Index = 0; + for (uint8_t C : Data) { + Chars[Index] = C; + Index++; + } + + OS << '\'' << toHex(Chars) << '\''; + + EmitEOL(); +} + +void SystemZHLASMAsmStreamer::emitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + + InstPrinter->printInst(&Inst, 0, "", STI, OS); + EmitEOL(); +} + +void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { + + MCStreamer::emitLabel(Symbol, Loc); + + Symbol->print(OS, MAI); + // TODO Need to adjust this based on Label type + OS << " DS 0H"; + // TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been + // moved to HLASM syntax. + // OS << MAI->getLabelSuffix(); + EmitEOL(); +} + +void SystemZHLASMAsmStreamer::emitRawTextImpl(StringRef String) { + String.consume_back("\n"); + OS << String; + EmitEOL(); +} + +// Slight duplicate of MCExpr::print due to HLASM only recognizing limited +// arithmetic operators (+-*/). +void SystemZHLASMAsmStreamer::emitHLASMValueImpl(const MCExpr *Value, + unsigned Size, bool Parens) { + switch (Value->getKind()) { + case MCExpr::Constant: { + OS << "XL" << Size << '\''; + Value->print(OS, MAI); + OS << '\''; + return; + } + case MCExpr::Binary: { + const MCBinaryExpr &BE = cast<MCBinaryExpr>(*Value); + int64_t Const; + // Or is handled differently. + if (BE.getOpcode() == MCBinaryExpr::Or) { + emitHLASMValueImpl(BE.getLHS(), Size, true); + OS << ','; + emitHLASMValueImpl(BE.getRHS(), Size, true); + return; + } + + if (Parens) + OS << "A("; + emitHLASMValueImpl(BE.getLHS(), Size); + + switch (BE.getOpcode()) { + case MCBinaryExpr::LShr: { + Const = cast<MCConstantExpr>(BE.getRHS())->getValue(); + OS << '/' << (1 << Const); + if (Parens) + OS << ')'; + return; + } + case MCBinaryExpr::Add: + OS << '+'; + break; + case MCBinaryExpr::Div: + OS << '/'; + break; + case MCBinaryExpr::Mul: + OS << '*'; + break; + case MCBinaryExpr::Sub: + OS << '-'; + break; + default: + getContext().reportError(SMLoc(), + "Unrecognized HLASM arithmetic expression!"); + } + emitHLASMValueImpl(BE.getRHS(), Size); + if (Parens) + OS << ')'; + return; + } + case MCExpr::Target: + Value->print(OS, MAI); + return; + default: + if (Parens) + OS << "A("; + Value->print(OS, MAI); + if (Parens) + OS << ')'; + return; + } +} + +void SystemZHLASMAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc) { + assert(Size <= 8 && "Invalid size"); + assert(getCurrentSectionOnly() && + "Cannot emit contents before setting section!"); + + OS << " DC "; + emitHLASMValueImpl(Value, Size, true); + EmitEOL(); +} diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h new file mode 100644 index 0000000..bf04eb8 --- /dev/null +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h @@ -0,0 +1,122 @@ +//===- SystemZHLASMAsmStreamer.h - HLASM Assembly Text 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 declares the SystemZHLASMAsmStreamer class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +class SystemZHLASMAsmStreamer final : public MCStreamer { + constexpr static size_t InstLimit = 80; + constexpr static size_t ContIndicatorColumn = 72; + constexpr static size_t ContStartColumn = 15; + constexpr static size_t ContLen = ContIndicatorColumn - ContStartColumn; + std::unique_ptr<formatted_raw_ostream> FOSOwner; + formatted_raw_ostream &FOS; + std::string Str; + raw_string_ostream OS; + const MCAsmInfo *MAI; + std::unique_ptr<MCInstPrinter> InstPrinter; + std::unique_ptr<MCAssembler> Assembler; + SmallString<128> CommentToEmit; + raw_svector_ostream CommentStream; + raw_null_ostream NullStream; + bool IsVerboseAsm = false; + +public: + SystemZHLASMAsmStreamer(MCContext &Context, + std::unique_ptr<formatted_raw_ostream> os, + MCInstPrinter *printer, + std::unique_ptr<MCCodeEmitter> emitter, + std::unique_ptr<MCAsmBackend> asmbackend) + : MCStreamer(Context), FOSOwner(std::move(os)), FOS(*FOSOwner), OS(Str), + MAI(Context.getAsmInfo()), InstPrinter(printer), + Assembler(std::make_unique<MCAssembler>( + Context, std::move(asmbackend), std::move(emitter), + (asmbackend) ? asmbackend->createObjectWriter(NullStream) + : nullptr)), + CommentStream(CommentToEmit) { + assert(InstPrinter); + if (Assembler->getBackendPtr()) + setAllowAutoPadding(Assembler->getBackend().allowAutoPadding()); + + Context.setUseNamesOnTempLabels(true); + auto *TO = Context.getTargetOptions(); + if (!TO) + return; + IsVerboseAsm = TO->AsmVerbose; + if (IsVerboseAsm) + InstPrinter->setCommentStream(CommentStream); + } + + MCAssembler &getAssembler() { return *Assembler; } + + void EmitEOL(); + void EmitComment(); + + /// Add a comment that can be emitted to the generated .s file to make the + /// output of the compiler more readable. This only affects the MCAsmStreamer + /// and only when verbose assembly output is enabled. + void AddComment(const Twine &T, bool EOL = true) override; + + void emitBytes(StringRef Data) override; + + void emitAlignmentDS(uint64_t ByteAlignment, std::optional<int64_t> Value, + unsigned ValueSize, unsigned MaxBytesToEmit); + void emitValueToAlignment(Align Alignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) override; + + void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, + unsigned MaxBytesToEmit = 0) override; + + /// Return true if this streamer supports verbose assembly at all. + bool isVerboseAsm() const override { return IsVerboseAsm; } + + /// Do we support EmitRawText? + bool hasRawTextSupport() const override { return true; } + + /// @name MCStreamer Interface + /// @{ + + void changeSection(MCSection *Section, uint32_t Subsection) override; + + void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + void emitLabel(MCSymbol *Symbol, SMLoc Loc) override; + bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { + return false; + } + + void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + Align ByteAlignment) override {} + + void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, Align ByteAlignment = Align(1), + SMLoc Loc = SMLoc()) override {} + void emitRawTextImpl(StringRef String) override; + void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; + + void emitHLASMValueImpl(const MCExpr *Value, unsigned Size, + bool Parens = false); + /// @} +}; diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp index e84368c..0fb5c30 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp @@ -8,6 +8,7 @@ #include "SystemZMCTargetDesc.h" #include "SystemZGNUInstPrinter.h" +#include "SystemZHLASMAsmStreamer.h" #include "SystemZHLASMInstPrinter.h" #include "SystemZMCAsmInfo.h" #include "SystemZTargetStreamer.h" @@ -21,6 +22,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; @@ -34,6 +36,12 @@ using namespace llvm; #define GET_REGINFO_MC_DESC #include "SystemZGenRegisterInfo.inc" +// Temporary option to assist with the migration to a new HLASMAsmStreamer on +// z/OS +static cl::opt<bool> GNUAsOnzOSCL("emit-gnuas-syntax-on-zos", + cl::desc("Emit GNU Assembly Syntax on z/OS."), + cl::init(true)); + const unsigned SystemZMC::GR32Regs[16] = { SystemZ::R0L, SystemZ::R1L, SystemZ::R2L, SystemZ::R3L, SystemZ::R4L, SystemZ::R5L, SystemZ::R6L, SystemZ::R7L, @@ -212,12 +220,33 @@ public: static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint) { - return new SystemZTargetAsmStreamer(S, OS); + if (S.getContext().getTargetTriple().isOSzOS()) + return new SystemZTargetHLASMStreamer(S, OS); + else + return new SystemZTargetAsmStreamer(S, OS); +} + +static MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, + MCInstPrinter *IP, + std::unique_ptr<MCCodeEmitter> CE, + std::unique_ptr<MCAsmBackend> TAB) { + + auto TT = Ctx.getTargetTriple(); + if (TT.isOSzOS() && !GNUAsOnzOSCL) + return new SystemZHLASMAsmStreamer(Ctx, std::move(OS), IP, std::move(CE), + std::move(TAB)); + + return llvm::createAsmStreamer(Ctx, std::move(OS), IP, std::move(CE), + std::move(TAB)); } static MCTargetStreamer * createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { - return new SystemZTargetELFStreamer(S); + if (S.getContext().getTargetTriple().isOSzOS()) + return new SystemZTargetGOFFStreamer(S); + else + return new SystemZTargetELFStreamer(S); } static MCTargetStreamer * @@ -259,6 +288,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZTargetMC() { createSystemZMCInstPrinter); // Register the asm streamer. + TargetRegistry::RegisterAsmStreamer(getTheSystemZTarget(), createAsmStreamer); + + // Register the asm target streamer. TargetRegistry::RegisterAsmTargetStreamer(getTheSystemZTarget(), createAsmTargetStreamer); diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp new file mode 100644 index 0000000..1946cd1 --- /dev/null +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp @@ -0,0 +1,44 @@ +//==-- SystemZTargetStreamer.cpp - SystemZ Target Streamer Methods ----------=// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines SystemZ-specific target streamer classes. +/// These are for implementing support for target-specific assembly directives. +/// +//===----------------------------------------------------------------------===// + +#include "SystemZTargetStreamer.h" + +using namespace llvm; + +void SystemZTargetHLASMStreamer::emitExtern(StringRef Sym) { + getStreamer().emitRawText(Twine(" EXTRN ") + Twine(Sym)); +} + +// HLASM statements can only perform a single operation at a time +const MCExpr *SystemZTargetHLASMStreamer::createWordDiffExpr( + MCContext &Ctx, const MCSymbol *Hi, const MCSymbol *Lo) { + assert(Hi && Lo && "Symbols required to calculate expression"); + MCSymbol *Temp = Ctx.createTempSymbol(); + OS << Temp->getName() << " EQU "; + const MCBinaryExpr *TempExpr = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(Hi, Ctx), MCSymbolRefExpr::create(Lo, Ctx), Ctx); + TempExpr->print(OS, Ctx.getAsmInfo()); + OS << "\n"; + return MCBinaryExpr::createLShr(MCSymbolRefExpr::create(Temp, Ctx), + MCConstantExpr::create(1, Ctx), Ctx); +} + +const MCExpr *SystemZTargetGOFFStreamer::createWordDiffExpr( + MCContext &Ctx, const MCSymbol *Hi, const MCSymbol *Lo) { + assert(Hi && Lo && "Symbols required to calculate expression"); + return MCBinaryExpr::createLShr( + MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Ctx), + MCSymbolRefExpr::create(Lo, Ctx), Ctx), + MCConstantExpr::create(1, Ctx), Ctx); +} diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h index 4c7a6ca..26be26e 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h @@ -10,8 +10,12 @@ #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZTARGETSTREAMER_H #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/FormattedStream.h" #include <map> #include <utility> @@ -51,6 +55,31 @@ public: void emitConstantPools() override; virtual void emitMachine(StringRef CPU) {}; + + virtual void emitExtern(StringRef Str) {}; + + virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi, + const MCSymbol *Lo) { + return nullptr; + } +}; + +class SystemZTargetGOFFStreamer : public SystemZTargetStreamer { +public: + SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {} + const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi, + const MCSymbol *Lo) override; +}; + +class SystemZTargetHLASMStreamer : public SystemZTargetStreamer { + formatted_raw_ostream &OS; + +public: + SystemZTargetHLASMStreamer(MCStreamer &S, formatted_raw_ostream &OS) + : SystemZTargetStreamer(S), OS(OS) {} + void emitExtern(StringRef Sym) override; + const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi, + const MCSymbol *Lo) override; }; } // end namespace llvm |