Skip to content

Commit 78356cd

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 e880cf7 commit 78356cd

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)