Skip to content

Commit 0e5c36a

Browse files
committed
[GOFF] Add writing of text records
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 ba1223a commit 0e5c36a

File tree

8 files changed

+180
-40
lines changed

8 files changed

+180
-40
lines changed

llvm/include/llvm/MC/MCContext.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ class MCContext {
366366

367367
template <typename TAttr>
368368
MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
369-
TAttr SDAttributes, MCSection *Parent);
369+
TAttr SDAttributes, MCSection *Parent,
370+
bool IsVirtual);
370371

371372
/// Map of currently defined macros.
372373
StringMap<MCAsmMacro> MacroMap;
@@ -607,7 +608,8 @@ class MCContext {
607608
MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
608609
GOFF::SDAttr SDAttributes);
609610
MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
610-
GOFF::EDAttr EDAttributes, MCSection *Parent);
611+
GOFF::EDAttr EDAttributes, MCSection *Parent,
612+
bool IsVirtual);
611613
MCSectionGOFF *getGOFFSection(SectionKind Kind, StringRef Name,
612614
GOFF::PRAttr PRAttributes, MCSection *Parent);
613615

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/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,7 +2801,8 @@ MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
28012801
GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
28022802
GOFF::LOADBEHAVIOR, GOFF::ESD_RQ_0,
28032803
GOFF::ESD_ALIGN_Doubleword},
2804-
static_cast<MCSectionGOFF *>(TextSection)->getParent());
2804+
static_cast<MCSectionGOFF *>(TextSection)->getParent(),
2805+
/*IsVirtual=*/true);
28052806
return getContext().getGOFFSection(
28062807
SectionKind::getData(), Name,
28072808
GOFF::PRAttr{true, false, GOFF::ESD_EXE_DATA, GOFF::LINKAGE,
@@ -2833,7 +2834,7 @@ MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
28332834
GOFF::EDAttr{false, GOFF::RMODE, GOFF::ESD_NS_Parts,
28342835
GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
28352836
GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_0, Align},
2836-
SD);
2837+
SD, /*IsVirtual=*/true);
28372838
return getContext().getGOFFSection(
28382839
Kind, Symbol->getName(),
28392840
GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::LINKAGE,

llvm/lib/MC/GOFFObjectWriter.cpp

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

277277
void writeHeader();
278278
void writeSymbol(const GOFFSymbol &Symbol);
279+
void writeText(const MCSectionGOFF *MC);
279280
void writeEnd();
280281

281282
void defineSectionSymbols(const MCSectionGOFF &Section);
@@ -407,6 +408,80 @@ void GOFFWriter::writeSymbol(const GOFFSymbol &Symbol) {
407408
OS.write(Name.data(), NameLength); // Name
408409
}
409410

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

431506
defineSymbols();
432507

508+
for (const MCSection &Section : Asm)
509+
writeText(static_cast<const MCSectionGOFF*>(&Section));
510+
433511
writeEnd();
434512

435513
// Make sure all records are written.

llvm/lib/MC/MCContext.cpp

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

675675
template <typename TAttr>
676676
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
677-
TAttr Attributes, MCSection *Parent) {
677+
TAttr Attributes, MCSection *Parent,
678+
bool IsVirtual) {
678679
std::string UniqueName(Name);
679680
if (Parent) {
680681
UniqueName.append("/").append(Parent->getName());
@@ -688,28 +689,32 @@ MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
688689
return Iter->second;
689690

690691
StringRef CachedName = StringRef(Iter->first.c_str(), Name.size());
691-
MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate()) MCSectionGOFF(
692-
CachedName, Kind, Attributes, static_cast<MCSectionGOFF *>(Parent));
692+
MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate())
693+
MCSectionGOFF(CachedName, Kind, IsVirtual, Attributes,
694+
static_cast<MCSectionGOFF *>(Parent));
693695
Iter->second = GOFFSection;
694696
allocInitialFragment(*GOFFSection);
695697
return GOFFSection;
696698
}
697699

698700
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
699701
GOFF::SDAttr SDAttributes) {
700-
return getGOFFSection<GOFF::SDAttr>(Kind, Name, SDAttributes, nullptr);
702+
return getGOFFSection<GOFF::SDAttr>(Kind, Name, SDAttributes, nullptr,
703+
/*IsVirtual=*/true);
701704
}
702705

703706
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
704707
GOFF::EDAttr EDAttributes,
705-
MCSection *Parent) {
706-
return getGOFFSection<GOFF::EDAttr>(Kind, Name, EDAttributes, Parent);
708+
MCSection *Parent, bool IsVirtual) {
709+
return getGOFFSection<GOFF::EDAttr>(Kind, Name, EDAttributes, Parent,
710+
IsVirtual);
707711
}
708712

709713
MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
710714
GOFF::PRAttr PRAttributes,
711715
MCSection *Parent) {
712-
return getGOFFSection<GOFF::PRAttr>(Kind, Name, PRAttributes, Parent);
716+
return getGOFFSection<GOFF::PRAttr>(Kind, Name, PRAttributes, Parent,
717+
/*IsVirtual=*/false);
713718
}
714719

715720
MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
557557
GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
558558
GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_1,
559559
GOFF::ESD_ALIGN_Quadword},
560-
RootSDSection);
560+
RootSDSection, /*IsVirtual=*/true);
561561
ADASection = Ctx->getGOFFSection(
562562
SectionKind::getData(), "#S",
563563
GOFF::PRAttr{false, false, GOFF::ESD_EXE_DATA, GOFF::ESD_LT_XPLink,
@@ -570,15 +570,15 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
570570
GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Concatenate,
571571
GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
572572
GOFF::ESD_ALIGN_Doubleword},
573-
RootSDSection);
573+
RootSDSection, /*IsVirtual=*/false);
574574

575575
MCSectionGOFF *PPA2ListEDSection = Ctx->getGOFFSection(
576576
SectionKind::getMetadata(), GOFF::CLASS_PPA2,
577577
GOFF::EDAttr{true, GOFF::RMODE, GOFF::ESD_NS_Parts,
578578
GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
579579
GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
580580
GOFF::ESD_ALIGN_Doubleword},
581-
RootSDSection);
581+
RootSDSection, /*IsVirtual=*/true);
582582
PPA2ListSection = Ctx->getGOFFSection(
583583
SectionKind::getData(), ".&ppa2",
584584
GOFF::PRAttr{true, false, GOFF::ESD_EXE_DATA, GOFF::ESD_LT_OS,
@@ -591,7 +591,7 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
591591
GOFF::ESD_TS_Structured, GOFF::ESD_BA_Concatenate,
592592
GOFF::ESD_LB_NoLoad, GOFF::ESD_RQ_0,
593593
GOFF::ESD_ALIGN_Doubleword},
594-
RootSDSection);
594+
RootSDSection, /*IsVirtual=*/false);
595595
}
596596

597597
void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {

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: 0000300 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
105105
; CHECK-NEXT: 0000310 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: 0000320 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
110+
; CHECK-NEXT: 0000330 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: 00003c0 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
114+
; CHECK-NEXT: 00003d0 00 00 00 00 00 00 00 {{..}} {{.*}}
115+
116+
; Text record for the ADA section test#S.
117+
; CHECK: 0000410 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
118+
; CHECK-NEXT: 0000420 00 00 00 00 00 00 00 {{..}} {{.*}}
119+
120+
; Text record for the section B_IDRL.
121+
; CHECK: 0000460 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
122+
; CHECK-NEXT: 0000470 00 00 00 00 00 00 00 {{..}} {{.*}}
123+
107124
; End record.
108-
; CHECK-NEXT: 0000320 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
109-
; CHECK-NEXT: 0000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
110-
; CHECK-NEXT: 0000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
111-
; CHECK-NEXT: 0000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
112-
; CHECK-NEXT: 0000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
125+
; CHECK: 00004b0 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
126+
; CHECK-NEXT: 00004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
127+
; CHECK-NEXT: 00004d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
128+
; CHECK-NEXT: 00004e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
129+
; CHECK-NEXT: 00004f0 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: 00004e0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
148148
; CHECK-NEXT: 00004f0 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: 0000500 03 10 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
153+
; CHECK-NEXT: 0000510 00 00 00 00 00 00 00 {{..}} {{.*}}
154+
155+
; Text record for the section .&ppa2.
156+
; CHECK: 0000550 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
157+
; CHECK-NEXT: 0000560 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: 00005a0 03 10 00 00 [[DATA_PR]] 00 00 00 00 00 00 00 00
162+
; CHECK-NEXT: 00005b0 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: 00005f0 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
168+
; CHECK-NEXT: 0000600 00 00 00 00 00 00 00 {{..}} {{.*}}
169+
150170
; End record.
151-
; CHECK-NEXT: 0000500 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
152-
; CHECK-NEXT: 0000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
153-
; CHECK-NEXT: 0000520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
154-
; CHECK-NEXT: 0000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
155-
; CHECK-NEXT: 0000540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
171+
; CHECK: 0000640 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
172+
; CHECK-NEXT: 0000650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
173+
; CHECK-NEXT: 0000660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
174+
; CHECK-NEXT: 0000670 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
175+
; CHECK-NEXT: 0000680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0 commit comments

Comments
 (0)