288 lines · cpp
1//===- SystemZHLASMAsmStreamer.cpp - HLASM Assembly Text Output -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SystemZHLASMAsmStreamer.h"10#include "llvm/ADT/StringExtras.h"11#include "llvm/Support/Casting.h"12#include "llvm/Support/Signals.h"13#include <sstream>14 15using namespace llvm;16 17void SystemZHLASMAsmStreamer::EmitEOL() {18 // Comments are emitted on a new line before the instruction.19 if (IsVerboseAsm)20 EmitComment();21 22 std::istringstream Stream(Str);23 SmallVector<std::string> Lines;24 std::string Line;25 while (std::getline(Stream, Line, '\n'))26 Lines.push_back(Line);27 28 for (auto S : Lines) {29 if (LLVM_LIKELY(S.length() < ContIndicatorColumn)) {30 FOS << S;31 // Each line in HLASM must fill the full 80 characters.32 FOS.PadToColumn(InstLimit);33 FOS << "\n";34 } else {35 // If last character before end of the line is not a space36 // we must insert an additional non-space character that37 // is not part of the statement coding. We just reuse38 // the existing character by making the new substring start39 // 1 character sooner, thus "duplicating" that character40 // If The last character is a space. We insert an X instead.41 std::string TmpSubStr = S.substr(0, ContIndicatorColumn);42 if (!TmpSubStr.compare(ContIndicatorColumn - 1, 1, " "))43 TmpSubStr.replace(ContIndicatorColumn - 1, 1, "X");44 45 FOS << TmpSubStr;46 FOS.PadToColumn(InstLimit);47 FOS << "\n";48 49 size_t Emitted = ContIndicatorColumn - 1;50 51 while (Emitted < S.length()) {52 if ((S.length() - Emitted) < ContLen)53 TmpSubStr = S.substr(Emitted, S.length());54 else {55 TmpSubStr = S.substr(Emitted, ContLen);56 if (!TmpSubStr.compare(ContLen - 1, 1, " "))57 TmpSubStr.replace(ContLen - 1, 1, "X");58 }59 FOS.PadToColumn(ContStartColumn);60 FOS << TmpSubStr;61 FOS.PadToColumn(InstLimit);62 FOS << "\n";63 Emitted += ContLen - 1;64 }65 }66 }67 Str.clear();68}69 70void SystemZHLASMAsmStreamer::changeSection(MCSection *Section,71 uint32_t Subsection) {72 MAI->printSwitchToSection(*Section, Subsection,73 getContext().getTargetTriple(), OS);74 MCStreamer::changeSection(Section, Subsection);75}76 77void SystemZHLASMAsmStreamer::emitAlignmentDS(uint64_t ByteAlignment,78 std::optional<int64_t> Value,79 unsigned ValueSize,80 unsigned MaxBytesToEmit) {81 if (!isPowerOf2_64(ByteAlignment))82 report_fatal_error("Only power-of-two alignments are supported ");83 84 OS << " DS 0";85 switch (ValueSize) {86 default:87 llvm_unreachable("Invalid size for machine code value!");88 case 1:89 OS << "B";90 break;91 case 2:92 OS << "H";93 break;94 case 4:95 OS << "F";96 break;97 case 8:98 OS << "D";99 break;100 case 16:101 OS << "Q";102 break;103 }104 105 EmitEOL();106}107 108void SystemZHLASMAsmStreamer::AddComment(const Twine &T, bool EOL) {109 if (!IsVerboseAsm)110 return;111 112 T.toVector(CommentToEmit);113 114 if (EOL)115 CommentToEmit.push_back('\n'); // Place comment in a new line.116}117 118void SystemZHLASMAsmStreamer::EmitComment() {119 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0)120 return;121 122 StringRef Comments = CommentToEmit;123 124 assert(Comments.back() == '\n' && "Comment array not newline terminated");125 do {126 // Emit a line of comments, but not exceeding 80 characters.127 size_t Position = std::min(InstLimit - 2, Comments.find('\n'));128 FOS << MAI->getCommentString() << ' ' << Comments.substr(0, Position)129 << '\n';130 131 if (Comments[Position] == '\n')132 Position++;133 Comments = Comments.substr(Position);134 } while (!Comments.empty());135 136 CommentToEmit.clear();137}138 139void SystemZHLASMAsmStreamer::emitValueToAlignment(Align Alignment,140 int64_t Fill,141 uint8_t FillLen,142 unsigned MaxBytesToEmit) {143 emitAlignmentDS(Alignment.value(), Fill, FillLen, MaxBytesToEmit);144}145 146void SystemZHLASMAsmStreamer::emitCodeAlignment(Align Alignment,147 const MCSubtargetInfo *STI,148 unsigned MaxBytesToEmit) {149 // Emit with a text fill value.150 if (MAI->getTextAlignFillValue())151 emitAlignmentDS(Alignment.value(), MAI->getTextAlignFillValue(), 1,152 MaxBytesToEmit);153 else154 emitAlignmentDS(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);155}156 157void SystemZHLASMAsmStreamer::emitBytes(StringRef Data) {158 assert(getCurrentSectionOnly() &&159 "Cannot emit contents before setting section!");160 if (Data.empty())161 return;162 163 OS << " DC ";164 size_t Len = Data.size();165 SmallVector<uint8_t> Chars;166 Chars.resize(Len);167 OS << "XL" << Len;168 uint32_t Index = 0;169 for (uint8_t C : Data) {170 Chars[Index] = C;171 Index++;172 }173 174 OS << '\'' << toHex(Chars) << '\'';175 176 EmitEOL();177}178 179void SystemZHLASMAsmStreamer::emitInstruction(const MCInst &Inst,180 const MCSubtargetInfo &STI) {181 182 InstPrinter->printInst(&Inst, 0, "", STI, OS);183 EmitEOL();184}185 186void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {187 188 MCStreamer::emitLabel(Symbol, Loc);189 190 Symbol->print(OS, MAI);191 // TODO Need to adjust this based on Label type192 OS << " DS 0H";193 // TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been194 // moved to HLASM syntax.195 // OS << MAI->getLabelSuffix();196 EmitEOL();197}198 199void SystemZHLASMAsmStreamer::emitRawTextImpl(StringRef String) {200 String.consume_back("\n");201 OS << String;202 EmitEOL();203}204 205// Slight duplicate of MCExpr::print due to HLASM only recognizing limited206// arithmetic operators (+-*/).207void SystemZHLASMAsmStreamer::emitHLASMValueImpl(const MCExpr *Value,208 unsigned Size, bool Parens) {209 switch (Value->getKind()) {210 case MCExpr::Constant: {211 OS << "XL" << Size << '\'';212 MAI->printExpr(OS, *Value);213 OS << '\'';214 return;215 }216 case MCExpr::Binary: {217 const MCBinaryExpr &BE = cast<MCBinaryExpr>(*Value);218 int64_t Const;219 // Or is handled differently.220 if (BE.getOpcode() == MCBinaryExpr::Or) {221 emitHLASMValueImpl(BE.getLHS(), Size, true);222 OS << ',';223 emitHLASMValueImpl(BE.getRHS(), Size, true);224 return;225 }226 227 if (Parens)228 OS << "A(";229 emitHLASMValueImpl(BE.getLHS(), Size);230 231 switch (BE.getOpcode()) {232 case MCBinaryExpr::LShr: {233 Const = cast<MCConstantExpr>(BE.getRHS())->getValue();234 OS << '/' << (1 << Const);235 if (Parens)236 OS << ')';237 return;238 }239 case MCBinaryExpr::Add:240 OS << '+';241 break;242 case MCBinaryExpr::Div:243 OS << '/';244 break;245 case MCBinaryExpr::Mul:246 OS << '*';247 break;248 case MCBinaryExpr::Sub:249 OS << '-';250 break;251 default:252 getContext().reportError(SMLoc(),253 "Unrecognized HLASM arithmetic expression!");254 }255 emitHLASMValueImpl(BE.getRHS(), Size);256 if (Parens)257 OS << ')';258 return;259 }260 case MCExpr::Target:261 MAI->printExpr(OS, *Value);262 return;263 default:264 if (Parens)265 OS << "A(";266 MAI->printExpr(OS, *Value);267 if (Parens)268 OS << ')';269 return;270 }271}272 273void SystemZHLASMAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,274 SMLoc Loc) {275 assert(Size <= 8 && "Invalid size");276 assert(getCurrentSectionOnly() &&277 "Cannot emit contents before setting section!");278 279 OS << " DC ";280 emitHLASMValueImpl(Value, Size, true);281 EmitEOL();282}283 284void SystemZHLASMAsmStreamer::emitEnd() {285 OS << " END";286 EmitEOL();287}288