LLVM 22.0.0git
SystemZHLASMAsmStreamer.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
12#include "llvm/MC/MCExpr.h"
18#include <sstream>
19
20using namespace llvm;
21
23 Assembler->registerSymbol(Sym);
24}
25
27 // Comments are emitted on a new line before the instruction.
28 if (IsVerboseAsm)
30
31 std::istringstream Stream(Str);
33 std::string Line;
34 while (std::getline(Stream, Line, '\n'))
35 Lines.push_back(Line);
36
37 for (auto S : Lines) {
38 if (LLVM_LIKELY(S.length() < ContIndicatorColumn)) {
39 FOS << S;
40 // Each line in HLASM must fill the full 80 characters.
41 FOS.PadToColumn(InstLimit);
42 FOS << "\n";
43 } else {
44 // If last character before end of the line is not a space
45 // we must insert an additional non-space character that
46 // is not part of the statement coding. We just reuse
47 // the existing character by making the new substring start
48 // 1 character sooner, thus "duplicating" that character
49 // If The last character is a space. We insert an X instead.
50 std::string TmpSubStr = S.substr(0, ContIndicatorColumn);
51 if (!TmpSubStr.compare(ContIndicatorColumn - 1, 1, " "))
52 TmpSubStr.replace(ContIndicatorColumn - 1, 1, "X");
53
54 FOS << TmpSubStr;
55 FOS.PadToColumn(InstLimit);
56 FOS << "\n";
57
58 size_t Emitted = ContIndicatorColumn - 1;
59
60 while (Emitted < S.length()) {
61 if ((S.length() - Emitted) < ContLen)
62 TmpSubStr = S.substr(Emitted, S.length());
63 else {
64 TmpSubStr = S.substr(Emitted, ContLen);
65 if (!TmpSubStr.compare(ContLen - 1, 1, " "))
66 TmpSubStr.replace(ContLen - 1, 1, "X");
67 }
68 FOS.PadToColumn(ContStartColumn);
69 FOS << TmpSubStr;
70 FOS.PadToColumn(InstLimit);
71 FOS << "\n";
72 Emitted += ContLen - 1;
73 }
74 }
75 }
76 Str.clear();
77}
78
80 uint32_t Subsection) {
81 MAI->printSwitchToSection(*Section, Subsection,
82 getContext().getTargetTriple(), OS);
83 MCStreamer::changeSection(Section, Subsection);
84 EmitEOL();
85}
86
88 std::optional<int64_t> Value,
89 unsigned ValueSize,
90 unsigned MaxBytesToEmit) {
91 if (!isPowerOf2_64(ByteAlignment))
92 report_fatal_error("Only power-of-two alignments are supported ");
93
94 OS << " DS 0";
95 switch (ValueSize) {
96 default:
97 llvm_unreachable("Invalid size for machine code value!");
98 case 1:
99 OS << "B";
100 break;
101 case 2:
102 OS << "H";
103 break;
104 case 4:
105 OS << "F";
106 break;
107 case 8:
108 OS << "D";
109 break;
110 case 16:
111 OS << "Q";
112 break;
113 }
114
115 EmitEOL();
116}
117
119 if (!IsVerboseAsm)
120 return;
121
122 T.toVector(CommentToEmit);
123
124 if (EOL)
125 CommentToEmit.push_back('\n'); // Place comment in a new line.
126}
127
129 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0)
130 return;
131
132 StringRef Comments = CommentToEmit;
133
134 assert(Comments.back() == '\n' && "Comment array not newline terminated");
135 do {
136 // Emit a line of comments, but not exceeding 80 characters.
137 size_t Position = std::min(InstLimit - 2, Comments.find('\n'));
138 FOS << MAI->getCommentString() << ' ' << Comments.substr(0, Position)
139 << '\n';
140
141 if (Comments[Position] == '\n')
142 Position++;
143 Comments = Comments.substr(Position);
144 } while (!Comments.empty());
145
146 CommentToEmit.clear();
147}
148
150 int64_t Fill,
151 uint8_t FillLen,
152 unsigned MaxBytesToEmit) {
153 emitAlignmentDS(Alignment.value(), Fill, FillLen, MaxBytesToEmit);
154}
155
157 const MCSubtargetInfo *STI,
158 unsigned MaxBytesToEmit) {
159 // Emit with a text fill value.
160 if (MAI->getTextAlignFillValue())
161 emitAlignmentDS(Alignment.value(), MAI->getTextAlignFillValue(), 1,
162 MaxBytesToEmit);
163 else
164 emitAlignmentDS(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);
165}
166
169 "Cannot emit contents before setting section!");
170 if (Data.empty())
171 return;
172
173 OS << " DC ";
174 size_t Len = Data.size();
176 Chars.resize(Len);
177 OS << "XL" << Len;
178 uint32_t Index = 0;
179 for (uint8_t C : Data) {
180 Chars[Index] = C;
181 Index++;
182 }
183
184 OS << '\'' << toHex(Chars) << '\'';
185
186 EmitEOL();
187}
188
190 const MCSubtargetInfo &STI) {
191
192 InstPrinter->printInst(&Inst, 0, "", STI, OS);
193 EmitEOL();
194}
195
196static void emitXATTR(raw_ostream &OS, StringRef Name,
198 GOFF::ESDExecutable Executable,
199 GOFF::ESDBindingScope BindingScope) {
200 llvm::ListSeparator Sep(",");
201 OS << Name << " XATTR ";
202 OS << Sep << "LINKAGE(" << (Linkage == GOFF::ESD_LT_OS ? "OS" : "XPLINK")
203 << ")";
204 if (Executable != GOFF::ESD_EXE_Unspecified)
205 OS << Sep << "REFERENCE("
206 << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA") << ")";
207 if (BindingScope != GOFF::ESD_BSC_Unspecified) {
208 OS << Sep << "SCOPE(";
209 switch (BindingScope) {
211 OS << "SECTION";
212 break;
214 OS << "MODULE";
215 break;
217 OS << "LIBRARY";
218 break;
220 OS << "EXPORT";
221 break;
222 default:
223 break;
224 }
225 OS << ')';
226 }
227 OS << '\n';
228}
229
231 MCSymbolGOFF *Sym = static_cast<MCSymbolGOFF *>(Symbol);
232
234
235 // Emit ENTRY statement only if not implied by CSECT.
236 bool EmitEntry = true;
237 if (!Sym->isTemporary() && Sym->isInEDSection()) {
238 EmitEntry =
239 Sym->getName() !=
240 static_cast<MCSectionGOFF &>(Sym->getSection()).getParent()->getName();
241 if (EmitEntry) {
242 OS << " ENTRY " << Sym->getName();
243 EmitEOL();
244 }
245
246 emitXATTR(OS, Sym->getName(), Sym->getLinkage(), Sym->getCodeData(),
247 Sym->getBindingScope());
248 EmitEOL();
249 }
250
251 // TODO Need to adjust this based on Label type
252 if (EmitEntry) {
253 OS << Sym->getName() << " DS 0H";
254 // TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been
255 // moved to HLASM syntax.
256 // OS << MAI->getLabelSuffix();
257 EmitEOL();
258 }
259}
260
263 return static_cast<MCSymbolGOFF *>(Sym)->setSymbolAttribute(Attribute);
264}
265
267 String.consume_back("\n");
268 OS << String;
269 EmitEOL();
270}
271
272// Slight duplicate of MCExpr::print due to HLASM only recognizing limited
273// arithmetic operators (+-*/).
275 unsigned Size, bool Parens) {
276 switch (Value->getKind()) {
277 case MCExpr::Constant: {
278 OS << "XL" << Size << '\'';
279 MAI->printExpr(OS, *Value);
280 OS << '\'';
281 return;
282 }
283 case MCExpr::Binary: {
285 int64_t Const;
286 // Or is handled differently.
287 if (BE.getOpcode() == MCBinaryExpr::Or) {
288 emitHLASMValueImpl(BE.getLHS(), Size, true);
289 OS << ',';
290 emitHLASMValueImpl(BE.getRHS(), Size, true);
291 return;
292 }
293
294 if (Parens)
295 OS << "AD(";
297
298 switch (BE.getOpcode()) {
299 case MCBinaryExpr::LShr: {
300 Const = cast<MCConstantExpr>(BE.getRHS())->getValue();
301 OS << '/' << (1 << Const);
302 if (Parens)
303 OS << ')';
304 return;
305 }
307 OS << '+';
308 break;
310 OS << '/';
311 break;
313 OS << '*';
314 break;
316 OS << '-';
317 break;
318 default:
320 "Unrecognized HLASM arithmetic expression!");
321 }
323 if (Parens)
324 OS << ')';
325 return;
326 }
327 case MCExpr::Target:
328 MAI->printExpr(OS, *Value);
329 return;
330 default:
331 Parens &= isa<MCSymbolRefExpr>(Value);
332 if (Parens)
333 OS << "AD(";
334 MAI->printExpr(OS, *Value);
335 if (Parens)
336 OS << ')';
337 return;
338 }
339}
340
342 SMLoc Loc) {
343 assert(Size <= 8 && "Invalid size");
345 "Cannot emit contents before setting section!");
346
348 OS << " DC ";
350 EmitEOL();
351}
352
354 for (auto &Symbol : getAssembler().symbols()) {
355 if (Symbol.isTemporary() || !Symbol.isRegistered() || Symbol.isDefined())
356 continue;
357 auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
358 OS << " " << (Sym.isWeak() ? "WXTRN" : "EXTRN") << " " << Sym.getName();
359 EmitEOL();
360 emitXATTR(OS, Sym.getName(), Sym.getLinkage(), Sym.getCodeData(),
361 Sym.getBindingScope());
362 EmitEOL();
363 }
364
365 // Finish the assembly output.
366 OS << " END";
367 EmitEOL();
368}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:335
DXIL Finalize Linkage
static void emitXATTR(raw_ostream &OS, StringRef Name, GOFF::ESDLinkageType Linkage, GOFF::ESDExecutable Executable, GOFF::ESDBindingScope BindingScope)
This file contains the MCSymbolGOFF class.
#define T
This file contains some functions that are useful when dealing with strings.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:69
A helper class to return the specified delimiter string after the first invocation of operator String...
Binary assembler expressions.
Definition MCExpr.h:299
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition MCExpr.h:446
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition MCExpr.h:449
Opcode getOpcode() const
Get the kind of this binary expression.
Definition MCExpr.h:443
@ Div
Signed division.
Definition MCExpr.h:304
@ LShr
Logical shift right.
Definition MCExpr.h:323
@ Sub
Subtraction.
Definition MCExpr.h:324
@ Mul
Multiplication.
Definition MCExpr.h:317
@ Or
Bitwise or.
Definition MCExpr.h:319
@ Add
Addition.
Definition MCExpr.h:302
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
@ Constant
Constant expressions.
Definition MCExpr.h:42
@ Target
Target specific expression.
Definition MCExpr.h:46
@ Binary
Binary expressions.
Definition MCExpr.h:41
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
MCSectionGOFF * getParent() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:517
StringRef getName() const
Definition MCSection.h:586
MCContext & getContext() const
Definition MCStreamer.h:314
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCSection * getCurrentSectionOnly() const
Definition MCStreamer.h:421
virtual void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Emit the expression Value into the output as a native integer of the given Size bytes.
virtual void changeSection(MCSection *, uint32_t)
This is called by popSection and switchSection, if the current section changes.
Generic base class for all target subtargets.
GOFF::ESDExecutable getCodeData() const
bool isInEDSection() const
GOFF::ESDBindingScope getBindingScope() const
GOFF::ESDLinkageType getLinkage() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
Definition MCSymbol.h:251
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
Definition MCSymbol.h:205
Represents a location in source code.
Definition SMLoc.h:22
void resize(size_type N)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:573
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
char back() const
back - Get the last character in the string.
Definition StringRef.h:155
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:293
void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit=0) override
Emit nops until the byte alignment ByteAlignment is reached.
void emitHLASMValueImpl(const MCExpr *Value, unsigned Size, bool Parens=false)
void emitRawTextImpl(StringRef String) override
EmitRawText - If this file is backed by an assembly streamer, this dumps the specified string in the ...
void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override
Emit the expression Value into the output as a native integer of the given Size bytes.
void emitBytes(StringRef Data) override
Emit the bytes in Data into the output.
void emitAlignmentDS(uint64_t ByteAlignment, std::optional< int64_t > Value, unsigned ValueSize, unsigned MaxBytesToEmit)
void finishImpl() override
Streamer specific finalization.
void visitUsedSymbol(const MCSymbol &Sym) override
void AddComment(const Twine &T, bool EOL=true) override
Add a comment that can be emitted to the generated .s file to make the output of the compiler more re...
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override
Emit the given Instruction into the current section.
void emitValueToAlignment(Align Alignment, int64_t Fill, uint8_t FillLen, unsigned MaxBytesToEmit) override
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void changeSection(MCSection *Section, uint32_t Subsection) override
This is called by popSection and switchSection, if the current section changes.
void emitLabel(MCSymbol *Symbol, SMLoc Loc) override
Emit a label for Symbol into the current section.
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override
Add the given Attribute to Symbol.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
ESDExecutable
Definition GOFF.h:109
@ ESD_EXE_Unspecified
Definition GOFF.h:110
@ ESD_EXE_CODE
Definition GOFF.h:112
ESDBindingScope
Definition GOFF.h:134
@ ESD_BSC_Library
Definition GOFF.h:138
@ ESD_BSC_Module
Definition GOFF.h:137
@ ESD_BSC_Unspecified
Definition GOFF.h:135
@ ESD_BSC_ImportExport
Definition GOFF.h:139
@ ESD_BSC_Section
Definition GOFF.h:136
ESDLinkageType
Definition GOFF.h:142
@ ESD_LT_OS
Definition GOFF.h:142
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)
Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77