Skip to content

Commit f7a32b8

Browse files
tltaoTony Tao
andauthored
[MC][SystemZ] Introduce Target Specific HLASM Streamer for z/OS (llvm#130535)
A more fleshed out version of a previous PR llvm#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 <[email protected]>
1 parent d4ce57c commit f7a32b8

File tree

9 files changed

+591
-10
lines changed

9 files changed

+591
-10
lines changed

llvm/include/llvm/MC/TargetRegistry.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,19 @@ class Target {
208208
using AsmTargetStreamerCtorTy =
209209
MCTargetStreamer *(*)(MCStreamer &S, formatted_raw_ostream &OS,
210210
MCInstPrinter *InstPrint);
211-
using ObjectTargetStreamerCtorTy = MCTargetStreamer *(*)(
212-
MCStreamer &S, const MCSubtargetInfo &STI);
211+
using AsmStreamerCtorTy =
212+
MCStreamer *(*)(MCContext &Ctx, std::unique_ptr<formatted_raw_ostream> OS,
213+
MCInstPrinter *IP, std::unique_ptr<MCCodeEmitter> CE,
214+
std::unique_ptr<MCAsmBackend> TAB);
215+
using ObjectTargetStreamerCtorTy =
216+
MCTargetStreamer *(*)(MCStreamer &S, const MCSubtargetInfo &STI);
213217
using MCRelocationInfoCtorTy = MCRelocationInfo *(*)(const Triple &TT,
214218
MCContext &Ctx);
215-
using MCSymbolizerCtorTy = MCSymbolizer *(*)(
216-
const Triple &TT, LLVMOpInfoCallback GetOpInfo,
217-
LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx,
218-
std::unique_ptr<MCRelocationInfo> &&RelInfo);
219+
using MCSymbolizerCtorTy =
220+
MCSymbolizer *(*)(const Triple &TT, LLVMOpInfoCallback GetOpInfo,
221+
LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo,
222+
MCContext *Ctx,
223+
std::unique_ptr<MCRelocationInfo> &&RelInfo);
219224

220225
using CustomBehaviourCtorTy =
221226
mca::CustomBehaviour *(*)(const MCSubtargetInfo &STI,
@@ -316,6 +321,10 @@ class Target {
316321
/// registered (default = nullptr).
317322
AsmTargetStreamerCtorTy AsmTargetStreamerCtorFn = nullptr;
318323

324+
/// Construction function for this target's AsmStreamer, if
325+
/// registered (default = nullptr).
326+
AsmStreamerCtorTy AsmStreamerCtorFn = nullptr;
327+
319328
/// Construction function for this target's obj TargetStreamer, if
320329
/// registered (default = nullptr).
321330
ObjectTargetStreamerCtorTy ObjectTargetStreamerCtorFn = nullptr;
@@ -948,6 +957,10 @@ struct TargetRegistry {
948957
T.NullTargetStreamerCtorFn = Fn;
949958
}
950959

960+
static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) {
961+
T.AsmStreamerCtorFn = Fn;
962+
}
963+
951964
static void RegisterAsmTargetStreamer(Target &T,
952965
Target::AsmTargetStreamerCtorTy Fn) {
953966
T.AsmTargetStreamerCtorFn = Fn;

llvm/lib/MC/TargetRegistry.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,14 @@ MCStreamer *Target::createAsmStreamer(MCContext &Ctx,
9292
std::unique_ptr<MCCodeEmitter> CE,
9393
std::unique_ptr<MCAsmBackend> TAB) const {
9494
formatted_raw_ostream &OSRef = *OS;
95-
MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IP,
96-
std::move(CE), std::move(TAB));
95+
MCStreamer *S;
96+
if (AsmStreamerCtorFn)
97+
S = AsmStreamerCtorFn(Ctx, std::move(OS), IP, std::move(CE),
98+
std::move(TAB));
99+
else
100+
S = llvm::createAsmStreamer(Ctx, std::move(OS), IP, std::move(CE),
101+
std::move(TAB));
102+
97103
createAsmTargetStreamer(*S, OSRef, IP);
98104
return S;
99105
}

llvm/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ add_llvm_component_library(LLVMSystemZDesc
22
SystemZELFObjectWriter.cpp
33
SystemZGNUInstPrinter.cpp
44
SystemZGOFFObjectWriter.cpp
5+
SystemZHLASMAsmStreamer.cpp
56
SystemZHLASMInstPrinter.cpp
67
SystemZInstPrinterCommon.cpp
78
SystemZMCAsmBackend.cpp
89
SystemZMCAsmInfo.cpp
910
SystemZMCCodeEmitter.cpp
1011
SystemZMCExpr.cpp
1112
SystemZMCTargetDesc.cpp
13+
SystemZTargetStreamer.cpp
1214

1315
LINK_COMPONENTS
1416
CodeGenTypes
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
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+
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+
15+
#include <cmath>
16+
17+
void 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 space
36+
// we must insert an additional non-space character that
37+
// is not part of the statement coding. We just reuse
38+
// the existing character by making the new substring start
39+
// 1 character sooner, thus "duplicating" that character
40+
// 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+
70+
void SystemZHLASMAsmStreamer::changeSection(MCSection *Section,
71+
uint32_t Subsection) {
72+
Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS,
73+
Subsection);
74+
MCStreamer::changeSection(Section, Subsection);
75+
}
76+
77+
void 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+
108+
void 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+
118+
void 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+
139+
void SystemZHLASMAsmStreamer::emitValueToAlignment(Align Alignment,
140+
int64_t Value,
141+
unsigned ValueSize,
142+
unsigned MaxBytesToEmit) {
143+
emitAlignmentDS(Alignment.value(), Value, ValueSize, MaxBytesToEmit);
144+
}
145+
146+
void 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+
else
154+
emitAlignmentDS(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);
155+
}
156+
157+
void 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+
179+
void SystemZHLASMAsmStreamer::emitInstruction(const MCInst &Inst,
180+
const MCSubtargetInfo &STI) {
181+
182+
InstPrinter->printInst(&Inst, 0, "", STI, OS);
183+
EmitEOL();
184+
}
185+
186+
void 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 type
192+
OS << " DS 0H";
193+
// TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been
194+
// moved to HLASM syntax.
195+
// OS << MAI->getLabelSuffix();
196+
EmitEOL();
197+
}
198+
199+
void 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 limited
206+
// arithmetic operators (+-*/).
207+
void SystemZHLASMAsmStreamer::emitHLASMValueImpl(const MCExpr *Value,
208+
unsigned Size, bool Parens) {
209+
switch (Value->getKind()) {
210+
case MCExpr::Constant: {
211+
OS << "XL" << Size << '\'';
212+
Value->print(OS, MAI);
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+
Value->print(OS, MAI);
262+
return;
263+
default:
264+
if (Parens)
265+
OS << "A(";
266+
Value->print(OS, MAI);
267+
if (Parens)
268+
OS << ')';
269+
return;
270+
}
271+
}
272+
273+
void 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+
}

0 commit comments

Comments
 (0)