1//===- MCAsmInfoGOFF.cpp - MCGOFFAsmInfo properties -----------------------===//
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/// \file
10/// This file defines certain target specific asm properties for GOFF (z/OS)
11/// based targets.
12///
13//===----------------------------------------------------------------------===//
14
15#include "llvm/MC/MCAsmInfoGOFF.h"
16#include "llvm/ADT/StringExtras.h"
17#include "llvm/BinaryFormat/GOFF.h"
18#include "llvm/MC/MCSectionGOFF.h"
19#include "llvm/MC/MCSymbolGOFF.h"
20#include "llvm/Support/raw_ostream.h"
21
22using namespace llvm;
23
24MCAsmInfoGOFF::MCAsmInfoGOFF() {
25 Data64bitsDirective = "\t.quad\t";
26 WeakRefDirective = "WXTRN";
27 InternalSymbolPrefix = "L#";
28 PrivateLabelPrefix = "L#";
29 ZeroDirective = "\t.space\t";
30}
31
32static void emitCATTR(raw_ostream &OS, StringRef Name, GOFF::ESDRmode Rmode,
33 GOFF::ESDAlignment Alignment,
34 GOFF::ESDLoadingBehavior LoadBehavior,
35 GOFF::ESDExecutable Executable, bool IsReadOnly,
36 uint32_t SortKey, uint8_t FillByteValue,
37 StringRef PartName) {
38 OS << Name << " CATTR ";
39 OS << "ALIGN(" << static_cast<unsigned>(Alignment) << "),"
40 << "FILL(" << static_cast<unsigned>(FillByteValue) << ")";
41 switch (LoadBehavior) {
42 case GOFF::ESD_LB_Deferred:
43 OS << ",DEFLOAD";
44 break;
45 case GOFF::ESD_LB_NoLoad:
46 OS << ",NOLOAD";
47 break;
48 default:
49 break;
50 }
51 switch (Executable) {
52 case GOFF::ESD_EXE_CODE:
53 OS << ",EXECUTABLE";
54 break;
55 case GOFF::ESD_EXE_DATA:
56 OS << ",NOTEXECUTABLE";
57 break;
58 default:
59 break;
60 }
61 if (IsReadOnly)
62 OS << ",READONLY";
63 if (Rmode != GOFF::ESD_RMODE_None) {
64 OS << ',';
65 OS << "RMODE(";
66 switch (Rmode) {
67 case GOFF::ESD_RMODE_None:
68 llvm_unreachable("");
69 case GOFF::ESD_RMODE_24:
70 OS << "24";
71 break;
72 case GOFF::ESD_RMODE_31:
73 OS << "31";
74 break;
75 case GOFF::ESD_RMODE_64:
76 OS << "64";
77 break;
78 }
79 OS << ')';
80 }
81 if (SortKey)
82 OS << ",PRIORITY(" << SortKey << ")";
83 if (!PartName.empty())
84 OS << ",PART(" << PartName << ")";
85 OS << '\n';
86}
87
88static void emitXATTR(raw_ostream &OS, StringRef Name, MCSectionGOFF *ADA,
89 GOFF::ESDLinkageType Linkage,
90 GOFF::ESDExecutable Executable,
91 GOFF::ESDBindingScope BindingScope) {
92 llvm::ListSeparator Sep(",");
93 OS << Name << " XATTR ";
94 OS << Sep << "LINKAGE(" << (Linkage == GOFF::ESD_LT_OS ? "OS" : "XPLINK")
95 << ")";
96 if (Executable != GOFF::ESD_EXE_Unspecified)
97 OS << Sep << "REFERENCE("
98 << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA") << ")";
99 if (ADA)
100 OS << Sep << "PSECT(" << ADA->getName() << ")";
101 if (BindingScope != GOFF::ESD_BSC_Unspecified) {
102 OS << Sep << "SCOPE(";
103 switch (BindingScope) {
104 case GOFF::ESD_BSC_Section:
105 OS << "SECTION";
106 break;
107 case GOFF::ESD_BSC_Module:
108 OS << "MODULE";
109 break;
110 case GOFF::ESD_BSC_Library:
111 OS << "LIBRARY";
112 break;
113 case GOFF::ESD_BSC_ImportExport:
114 OS << "EXPORT";
115 break;
116 default:
117 break;
118 }
119 OS << ')';
120 }
121 OS << '\n';
122}
123
124void MCAsmInfoGOFF::printSwitchToSection(const MCSection &Section,
125 uint32_t Subsection, const Triple &T,
126 raw_ostream &OS) const {
127 auto &Sec =
128 const_cast<MCSectionGOFF &>(static_cast<const MCSectionGOFF &>(Section));
129 auto EmitExternalName = [&Sec, &OS]() {
130 if (Sec.hasExternalName())
131 OS << Sec.getName() << " ALIAS C'" << Sec.getExternalName() << "'\n";
132 };
133 switch (Sec.SymbolType) {
134 case GOFF::ESD_ST_SectionDefinition: {
135 OS << Sec.getName() << " CSECT\n";
136 Sec.Emitted = true;
137 EmitExternalName();
138 break;
139 }
140 case GOFF::ESD_ST_ElementDefinition: {
141 printSwitchToSection(Section: *Sec.getParent(), Subsection, T, OS);
142 if (!Sec.Emitted) {
143 emitCATTR(OS, Name: Sec.getName(), Rmode: Sec.EDAttributes.Rmode,
144 Alignment: Sec.EDAttributes.Alignment, LoadBehavior: Sec.EDAttributes.LoadBehavior,
145 Executable: GOFF::ESD_EXE_Unspecified, IsReadOnly: Sec.EDAttributes.IsReadOnly, SortKey: 0,
146 FillByteValue: Sec.EDAttributes.FillByteValue, PartName: StringRef());
147 if (auto *BeginSym = static_cast<MCSymbolGOFF *>(Sec.getBeginSymbol())) {
148 if (BeginSym->getADA())
149 emitXATTR(OS, Name: BeginSym->getName(), ADA: BeginSym->getADA(),
150 Linkage: GOFF::ESD_LT_XPLink, Executable: GOFF::ESD_EXE_Unspecified,
151 BindingScope: GOFF::ESD_BSC_Section);
152 }
153 Sec.Emitted = true;
154 EmitExternalName();
155 } else
156 OS << Sec.getName() << " CATTR\n";
157 break;
158 }
159 case GOFF::ESD_ST_PartReference: {
160 MCSectionGOFF *ED = Sec.getParent();
161 printSwitchToSection(Section: *ED->getParent(), Subsection, T, OS);
162 if (!Sec.Emitted) {
163 emitCATTR(OS, Name: ED->getName(), Rmode: ED->getEDAttributes().Rmode,
164 Alignment: ED->EDAttributes.Alignment, LoadBehavior: ED->EDAttributes.LoadBehavior,
165 Executable: Sec.PRAttributes.Executable, IsReadOnly: ED->EDAttributes.IsReadOnly,
166 SortKey: Sec.PRAttributes.SortKey, FillByteValue: ED->EDAttributes.FillByteValue,
167 PartName: Sec.getName());
168 MCSectionGOFF *ADA =
169 Sec.getBeginSymbol() != nullptr
170 ? static_cast<MCSymbolGOFF *>(Sec.getBeginSymbol())->getADA()
171 : nullptr;
172 emitXATTR(OS, Name: Sec.getName(), ADA, Linkage: Sec.PRAttributes.Linkage,
173 Executable: Sec.PRAttributes.Executable, BindingScope: Sec.PRAttributes.BindingScope);
174 ED->Emitted = true;
175 Sec.Emitted = true;
176 EmitExternalName();
177 } else
178 OS << ED->getName() << " CATTR PART(" << Sec.getName() << ")\n";
179 break;
180 }
181 default:
182 llvm_unreachable("Wrong section type");
183 }
184}
185