llvm-project/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
Fangrui Song 87c73f498d Move MCSection::printSwitchToSection to MCAsmInfo
This removes the only virtual function of MCSection.

NVPTXTargetStreamer::changeSection uses the MCSectionELF print method.
Change it to just print the section name.
2025-07-26 15:42:05 -07:00

288 lines
8.0 KiB
C++

//===- 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>
using namespace llvm;
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) {
MAI->printSwitchToSection(*Section, Subsection,
getContext().getTargetTriple(), OS);
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 Fill,
uint8_t FillLen,
unsigned MaxBytesToEmit) {
emitAlignmentDS(Alignment.value(), Fill, FillLen, 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 << '\'';
MAI->printExpr(OS, *Value);
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:
MAI->printExpr(OS, *Value);
return;
default:
if (Parens)
OS << "A(";
MAI->printExpr(OS, *Value);
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();
}
void SystemZHLASMAsmStreamer::emitEnd() {
OS << " END";
EmitEOL();
}