Skip to content

Commit c9b5b19

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 4883fc3 commit c9b5b19

File tree

8 files changed

+180
-41
lines changed

8 files changed

+180
-41
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, GOFF::ESD_ALIGN_Fullword,
28032803
0},
2804-
static_cast<MCSectionGOFF *>(TextSection)->getParent());
2804+
static_cast<MCSectionGOFF *>(TextSection)->getParent(),
2805+
/*IsVirtual=*/true);
28052806
return getContext().getGOFFSection(SectionKind::getData(), Name,
28062807
GOFF::PRAttr{true, GOFF::ESD_EXE_DATA,
28072808
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, 0},
2836-
SD);
2837+
SD, /*IsVirtual=*/true);
28372838
return getContext().getGOFFSection(Kind, Symbol->getName(),
28382839
GOFF::PRAttr{false, GOFF::ESD_EXE_DATA,
28392840
GOFF::LINKAGE,

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+
447+
void TextStream::write_impl(const char *Ptr, size_t Size) {
448+
size_t WrittenLength = 0;
449+
450+
// We only have signed 32bits of offset.
451+
if (Offset + Size > std::numeric_limits<int32_t>::max())
452+
report_fatal_error("TXT section too large");
453+
454+
while (WrittenLength < Size) {
455+
size_t ToWriteLength =
456+
std::min(Size - WrittenLength, size_t(GOFF::MaxDataLength));
457+
458+
OS.newRecord(GOFF::RT_TXT);
459+
OS.writebe<uint8_t>(GOFF::Flags(4, 4, RecordStyle)); // Text Record Style
460+
OS.writebe<uint32_t>(EsdId); // Element ESDID
461+
OS.writebe<uint32_t>(0); // Reserved
462+
OS.writebe<uint32_t>(static_cast<uint32_t>(Offset)); // Offset
463+
OS.writebe<uint32_t>(0); // Text Field True Length
464+
OS.writebe<uint16_t>(0); // Text Encoding
465+
OS.writebe<uint16_t>(ToWriteLength); // Data Length
466+
OS.write(Ptr + WrittenLength, ToWriteLength); // Data
467+
468+
WrittenLength += ToWriteLength;
469+
Offset += ToWriteLength;
470+
}
471+
}
472+
} // namespace
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 & 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 & 5 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, 0},
560-
RootSDSection);
560+
RootSDSection, /*IsVirtual=*/true);
561561
ADASection = Ctx->getGOFFSection(SectionKind::getData(), "#S",
562562
GOFF::PRAttr{false, GOFF::ESD_EXE_DATA,
563563
GOFF::ESD_LT_XPLink,
@@ -570,15 +570,14 @@ 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, 0},
573-
RootSDSection);
574-
573+
RootSDSection, /*IsVirtual=*/false);
575574
MCSectionGOFF *PPA2ListEDSection = Ctx->getGOFFSection(
576575
SectionKind::getMetadata(), GOFF::CLASS_PPA2,
577576
GOFF::EDAttr{true, GOFF::RMODE, GOFF::ESD_NS_Parts,
578577
GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
579578
GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
580579
GOFF::ESD_ALIGN_Doubleword, 0},
581-
RootSDSection);
580+
RootSDSection, /*IsVirtual=*/true);
582581
PPA2ListSection = Ctx->getGOFFSection(SectionKind::getData(), ".&ppa2",
583582
GOFF::PRAttr{true, GOFF::ESD_EXE_DATA,
584583
GOFF::ESD_LT_OS,
@@ -591,7 +590,7 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
591590
GOFF::ESD_TS_Structured, GOFF::ESD_BA_Concatenate,
592591
GOFF::ESD_LB_NoLoad, GOFF::ESD_RQ_0,
593592
GOFF::ESD_ALIGN_Doubleword, 0},
594-
RootSDSection);
593+
RootSDSection, /*IsVirtual=*/false);
595594
}
596595

597596
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: 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: 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: 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: 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: 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)