Skip to content

Commit 655d048

Browse files
authored
[GOFF] Add writing of text records (#137235)
Sections which are not allowed to carry data are marked as virtual. Only complication when writing out the text is that it must be written in chunks of 32k-1 bytes, which is done by having a wrapper stream writing those records. Data of BSS sections is not written, since the contents is known to be zero. Instead, the fill byte value is used.
1 parent e880cf7 commit 655d048

File tree

6 files changed

+171
-32
lines changed

6 files changed

+171
-32
lines changed

llvm/include/llvm/MC/MCContext.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,8 @@ class MCContext {
359359

360360
template <typename TAttr>
361361
MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
362-
TAttr SDAttributes, MCSection *Parent);
362+
TAttr SDAttributes, MCSection *Parent,
363+
bool IsVirtual);
363364

364365
/// Map of currently defined macros.
365366
StringMap<MCAsmMacro> MacroMap;

llvm/include/llvm/MC/MCSectionGOFF.h

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class MCSectionGOFF final : public MCSection {
3939
// The type of this section.
4040
GOFF::ESDSymbolType SymbolType;
4141

42+
// This section is a BSS section.
43+
unsigned IsBSS : 1;
44+
4245
// Indicates that the PR symbol needs to set the length of the section to a
4346
// non-zero value. This is only a problem with the ADA PR - the binder will
4447
// generate an error in this case.
@@ -50,26 +53,26 @@ class MCSectionGOFF final : public MCSection {
5053
friend class MCContext;
5154
friend class MCSymbolGOFF;
5255

53-
MCSectionGOFF(StringRef Name, SectionKind K, GOFF::SDAttr SDAttributes,
54-
MCSectionGOFF *Parent)
55-
: MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
56+
MCSectionGOFF(StringRef Name, SectionKind K, bool IsVirtual,
57+
GOFF::SDAttr SDAttributes, MCSectionGOFF *Parent)
58+
: MCSection(SV_GOFF, Name, K.isText(), IsVirtual, nullptr),
5659
Parent(Parent), SDAttributes(SDAttributes),
57-
SymbolType(GOFF::ESD_ST_SectionDefinition), RequiresNonZeroLength(0),
58-
Emitted(0) {}
60+
SymbolType(GOFF::ESD_ST_SectionDefinition), IsBSS(K.isBSS()),
61+
RequiresNonZeroLength(0), Emitted(0) {}
5962

60-
MCSectionGOFF(StringRef Name, SectionKind K, GOFF::EDAttr EDAttributes,
61-
MCSectionGOFF *Parent)
62-
: MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
63+
MCSectionGOFF(StringRef Name, SectionKind K, bool IsVirtual,
64+
GOFF::EDAttr EDAttributes, MCSectionGOFF *Parent)
65+
: MCSection(SV_GOFF, Name, K.isText(), IsVirtual, nullptr),
6366
Parent(Parent), EDAttributes(EDAttributes),
64-
SymbolType(GOFF::ESD_ST_ElementDefinition), RequiresNonZeroLength(0),
65-
Emitted(0) {}
67+
SymbolType(GOFF::ESD_ST_ElementDefinition), IsBSS(K.isBSS()),
68+
RequiresNonZeroLength(0), Emitted(0) {}
6669

67-
MCSectionGOFF(StringRef Name, SectionKind K, GOFF::PRAttr PRAttributes,
68-
MCSectionGOFF *Parent)
69-
: MCSection(SV_GOFF, Name, K.isText(), /*IsVirtual=*/false, nullptr),
70+
MCSectionGOFF(StringRef Name, SectionKind K, bool IsVirtual,
71+
GOFF::PRAttr PRAttributes, MCSectionGOFF *Parent)
72+
: MCSection(SV_GOFF, Name, K.isText(), IsVirtual, nullptr),
7073
Parent(Parent), PRAttributes(PRAttributes),
71-
SymbolType(GOFF::ESD_ST_PartReference), RequiresNonZeroLength(0),
72-
Emitted(0) {}
74+
SymbolType(GOFF::ESD_ST_PartReference), IsBSS(K.isBSS()),
75+
RequiresNonZeroLength(0), Emitted(0) {}
7376

7477
public:
7578
void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
@@ -81,6 +84,9 @@ class MCSectionGOFF final : public MCSection {
8184
// Return the parent section.
8285
MCSectionGOFF *getParent() const { return Parent; }
8386

87+
// Returns true if this is a BSS section.
88+
bool isBSS() const { return IsBSS; }
89+
8490
// Returns the type of this section.
8591
GOFF::ESDSymbolType getSymbolType() const { return SymbolType; }
8692

@@ -102,6 +108,17 @@ class MCSectionGOFF final : public MCSection {
102108
return PRAttributes;
103109
}
104110

111+
// Returns the text style for a section. Only defined for ED and PR sections.
112+
GOFF::ESDTextStyle getTextStyle() const {
113+
assert(isED() || isPR() || isVirtualSection() && "Expect ED or PR section");
114+
if (isED())
115+
return EDAttributes.TextStyle;
116+
if (isPR())
117+
return getParent()->getEDAttributes().TextStyle;
118+
// Virtual sections have no data, so byte orientation is fine.
119+
return GOFF::ESD_TS_ByteOriented;
120+
}
121+
105122
bool requiresNonZeroLength() const { return RequiresNonZeroLength; }
106123

107124
void setName(StringRef SectionName) { Name = SectionName; }

llvm/lib/MC/GOFFObjectWriter.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ class GOFFWriter {
275275

276276
void writeHeader();
277277
void writeSymbol(const GOFFSymbol &Symbol);
278+
void writeText(const MCSectionGOFF *MC);
278279
void writeEnd();
279280

280281
void defineSectionSymbols(const MCSectionGOFF &Section);
@@ -405,6 +406,80 @@ void GOFFWriter::writeSymbol(const GOFFSymbol &Symbol) {
405406
OS.write(Name.data(), NameLength); // Name
406407
}
407408

409+
namespace {
410+
/// Adapter stream to write a text section.
411+
class TextStream : public raw_ostream {
412+
/// The underlying GOFFOstream.
413+
GOFFOstream &OS;
414+
415+
/// The buffer size is the maximum number of bytes in a TXT section.
416+
static constexpr size_t BufferSize = GOFF::MaxDataLength;
417+
418+
/// Static allocated buffer for the stream, used by the raw_ostream class. The
419+
/// buffer is sized to hold the payload of a logical TXT record.
420+
char Buffer[BufferSize];
421+
422+
/// The offset for the next TXT record. This is equal to the number of bytes
423+
/// written.
424+
size_t Offset;
425+
426+
/// The Esdid of the GOFF section.
427+
const uint32_t EsdId;
428+
429+
/// The record style.
430+
const GOFF::ESDTextStyle RecordStyle;
431+
432+
/// See raw_ostream::write_impl.
433+
void write_impl(const char *Ptr, size_t Size) override;
434+
435+
uint64_t current_pos() const override { return Offset; }
436+
437+
public:
438+
explicit TextStream(GOFFOstream &OS, uint32_t EsdId,
439+
GOFF::ESDTextStyle RecordStyle)
440+
: OS(OS), Offset(0), EsdId(EsdId), RecordStyle(RecordStyle) {
441+
SetBuffer(Buffer, sizeof(Buffer));
442+
}
443+
444+
~TextStream() { flush(); }
445+
};
446+
} // namespace
447+
448+
void TextStream::write_impl(const char *Ptr, size_t Size) {
449+
size_t WrittenLength = 0;
450+
451+
// We only have signed 32bits of offset.
452+
if (Offset + Size > std::numeric_limits<int32_t>::max())
453+
report_fatal_error("TXT section too large");
454+
455+
while (WrittenLength < Size) {
456+
size_t ToWriteLength =
457+
std::min(Size - WrittenLength, size_t(GOFF::MaxDataLength));
458+
459+
OS.newRecord(GOFF::RT_TXT);
460+
OS.writebe<uint8_t>(GOFF::Flags(4, 4, RecordStyle)); // Text Record Style
461+
OS.writebe<uint32_t>(EsdId); // Element ESDID
462+
OS.writebe<uint32_t>(0); // Reserved
463+
OS.writebe<uint32_t>(static_cast<uint32_t>(Offset)); // Offset
464+
OS.writebe<uint32_t>(0); // Text Field True Length
465+
OS.writebe<uint16_t>(0); // Text Encoding
466+
OS.writebe<uint16_t>(ToWriteLength); // Data Length
467+
OS.write(Ptr + WrittenLength, ToWriteLength); // Data
468+
469+
WrittenLength += ToWriteLength;
470+
Offset += ToWriteLength;
471+
}
472+
}
473+
474+
void GOFFWriter::writeText(const MCSectionGOFF *Section) {
475+
// A BSS section contains only zeros, no need to write this.
476+
if (Section->isBSS())
477+
return;
478+
479+
TextStream S(OS, Section->getOrdinal(), Section->getTextStyle());
480+
Asm.writeSectionData(S, Section);
481+
}
482+
408483
void GOFFWriter::writeEnd() {
409484
uint8_t F = GOFF::END_EPR_None;
410485
uint8_t AMODE = 0;
@@ -428,6 +503,9 @@ uint64_t GOFFWriter::writeObject() {
428503

429504
defineSymbols();
430505

506+
for (const MCSection &Section : Asm)
507+
writeText(static_cast<const MCSectionGOFF *>(&Section));
508+
431509
writeEnd();
432510

433511
// Make sure all records are written.

llvm/lib/MC/MCContext.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,8 @@ MCContext::getELFUniqueIDForEntsize(StringRef SectionName, unsigned Flags,
723723

724724
template <typename TAttr>
725725
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
726-
TAttr Attributes, MCSection *Parent) {
726+
TAttr Attributes, MCSection *Parent,
727+
bool IsVirtual) {
727728
std::string UniqueName(Name);
728729
if (Parent) {
729730
UniqueName.append("/").append(Parent->getName());
@@ -737,28 +738,33 @@ MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
737738
return Iter->second;
738739

739740
StringRef CachedName = StringRef(Iter->first.c_str(), Name.size());
740-
MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate()) MCSectionGOFF(
741-
CachedName, Kind, Attributes, static_cast<MCSectionGOFF *>(Parent));
741+
MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate())
742+
MCSectionGOFF(CachedName, Kind, IsVirtual, Attributes,
743+
static_cast<MCSectionGOFF *>(Parent));
742744
Iter->second = GOFFSection;
743745
allocInitialFragment(*GOFFSection);
744746
return GOFFSection;
745747
}
746748

747749
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
748750
GOFF::SDAttr SDAttributes) {
749-
return getGOFFSection<GOFF::SDAttr>(Kind, Name, SDAttributes, nullptr);
751+
return getGOFFSection<GOFF::SDAttr>(Kind, Name, SDAttributes, nullptr,
752+
/*IsVirtual=*/true);
750753
}
751754

752755
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
753756
GOFF::EDAttr EDAttributes,
754757
MCSection *Parent) {
755-
return getGOFFSection<GOFF::EDAttr>(Kind, Name, EDAttributes, Parent);
758+
return getGOFFSection<GOFF::EDAttr>(
759+
Kind, Name, EDAttributes, Parent,
760+
/*IsVirtual=*/EDAttributes.BindAlgorithm == GOFF::ESD_BA_Merge);
756761
}
757762

758763
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
759764
GOFF::PRAttr PRAttributes,
760765
MCSection *Parent) {
761-
return getGOFFSection<GOFF::PRAttr>(Kind, Name, PRAttributes, Parent);
766+
return getGOFFSection<GOFF::PRAttr>(Kind, Name, PRAttributes, Parent,
767+
/*IsVirtual=*/false);
762768
}
763769

764770
MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,

llvm/test/CodeGen/SystemZ/zos-section-1.ll

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,26 @@ entry:
104104
; CHECK-NEXT: 000300 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
105105
; CHECK-NEXT: 000310 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
106106

107+
; Text record for the code section C_CODE64.
108+
; The regular expression matches the lower byte of the length.
109+
; CHECK-NEXT: 000320 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
110+
; CHECK-NEXT: 000330 00 00 00 00 00 00 00 {{..}} 00 c3 00 c5 00 c5 00 f1
111+
112+
; Text record for the section .&ppa2.
113+
; CHECK: 0003c0 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
114+
; CHECK-NEXT: 0003d0 00 00 00 00 00 00 00 {{..}} {{.*}}
115+
116+
; Text record for the ADA section test#S.
117+
; CHECK: 000410 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
118+
; CHECK-NEXT: 000420 00 00 00 00 00 00 00 {{..}} {{.*}}
119+
120+
; Text record for the section B_IDRL.
121+
; CHECK: 000460 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
122+
; CHECK-NEXT: 000470 00 00 00 00 00 00 00 {{..}} {{.*}}
123+
107124
; End record.
108-
; CHECK-NEXT: 000320 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
109-
; CHECK-NEXT: 000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
110-
; CHECK-NEXT: 000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
111-
; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
112-
; CHECK-NEXT: 000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
125+
; CHECK: 0004b0 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
126+
; CHECK-NEXT: 0004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
127+
; CHECK-NEXT: 0004d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
128+
; CHECK-NEXT: 0004e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
129+
; CHECK-NEXT: 0004f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

llvm/test/CodeGen/SystemZ/zos-section-2.ll

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,29 @@ source_filename = "test.ll"
147147
; CHECK-NEXT: 0004e0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
148148
; CHECK-NEXT: 0004f0 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
149149

150+
; Text record for the code section C_CODE64.
151+
; The regular expression matches the lower byte of the length.
152+
; CHECK-NEXT: 000500 03 10 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
153+
; CHECK-NEXT: 000510 00 00 00 00 00 00 00 {{..}} {{.*}}
154+
155+
; Text record for the section .&ppa2.
156+
; CHECK: 000550 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
157+
; CHECK-NEXT: 000560 00 00 00 00 00 00 00 {{..}} {{.*}}
158+
159+
; Text record for the section data.
160+
; Length is 4, and the content is 0x2a = 42.
161+
; CHECK: 0005a0 03 10 00 00 [[DATA_PR]] 00 00 00 00 00 00 00 00
162+
; CHECK-NEXT: 0005b0 00 00 00 00 00 00 00 04 00 00 00 2a 00 00 00 00
163+
164+
; There is no text record for section bss!
165+
166+
; Text record for the section B_IDRL.
167+
; CHECK: 0005f0 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
168+
; CHECK-NEXT: 000600 00 00 00 00 00 00 00 {{..}} {{.*}}
169+
150170
; End record.
151-
; CHECK-NEXT: 000500 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
152-
; CHECK-NEXT: 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
153-
; CHECK-NEXT: 000520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
154-
; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
155-
; CHECK-NEXT: 000540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
171+
; CHECK: 000640 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
172+
; CHECK-NEXT: 000650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
173+
; CHECK-NEXT: 000660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
174+
; CHECK-NEXT: 000670 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
175+
; CHECK-NEXT: 000680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0 commit comments

Comments
 (0)