[XCOFF][AIX] Differentiate usage of label symbol and csect symbol

Summary:
 We are using symbols to represent label and csect interchangeably before, and that could be a problem.
There are cases we would need to add storage mapping class to the symbol if that symbol is actually the name of a csect, but it's hard for us to figure out whether that symbol is a label or csect.

This patch intend to do the following:
    1. Construct a QualName (A name include the storage mapping class)
       MCSymbolXCOFF for every MCSectionXCOFF.
    2. Keep a pointer to that QualName inside of MCSectionXCOFF.
    3. Use that QualName whenever we need a symbol refers to that
       MCSectionXCOFF.
    4. Adapt the snowball effect from the above changes in
       XCOFFObjectWriter.cpp.

Reviewers: xingxue, DiggerLin, sfertile, daltenty, hubert.reinterpretcast

Reviewed By: DiggerLin, daltenty

Subscribers: wuzish, nemanjai, mgorny, hiraditya, kbarton, jsji, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69633
This commit is contained in:
Jason Liu 2019-11-08 09:26:28 -05:00 committed by David Tenty
parent e25bc5e024
commit 0dc0572b48
19 changed files with 117 additions and 96 deletions

View File

@ -13,6 +13,7 @@
#ifndef LLVM_BINARYFORMAT_XCOFF_H
#define LLVM_BINARYFORMAT_XCOFF_H
#include "llvm/ADT/StringRef.h"
#include <cstdint>
namespace llvm {
@ -251,6 +252,8 @@ enum CFileCpuId : uint8_t {
TCPU_970 = 19 ///< PPC970 - PowerPC 64-bit architecture.
};
StringRef getMappingClassString(XCOFF::StorageMappingClass SMC);
} // end namespace XCOFF
} // end namespace llvm

View File

@ -454,6 +454,9 @@ public:
unsigned Encoding,
MCStreamer &Streamer) const;
/// Return true if C is an acceptable character inside a symbol name.
virtual bool isAcceptableChar(char C) const;
/// Return true if the identifier \p Name does not need quotes to be
/// syntactically correct.
virtual bool isValidUnquotedName(StringRef Name) const;

View File

@ -20,9 +20,9 @@ protected:
MCAsmInfoXCOFF();
public:
// Return true only when the identifier Name does not need quotes to be
// syntactically correct for XCOFF.
bool isValidUnquotedName(StringRef Name) const override;
// Return true only when C is an acceptable character inside a
// MCSymbolXCOFF.
bool isAcceptableChar(char C) const override;
};
} // end namespace llvm

View File

@ -16,11 +16,10 @@
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbolXCOFF.h"
namespace llvm {
class MCSymbol;
// This class represents an XCOFF `Control Section`, more commonly referred to
// as a csect. A csect represents the smallest possible unit of data/code which
// will be relocated as a single block. A csect can either be:
@ -38,14 +37,18 @@ class MCSectionXCOFF final : public MCSection {
XCOFF::StorageMappingClass MappingClass;
XCOFF::SymbolType Type;
XCOFF::StorageClass StorageClass;
MCSymbolXCOFF *const QualName;
MCSectionXCOFF(StringRef Section, XCOFF::StorageMappingClass SMC,
XCOFF::SymbolType ST, XCOFF::StorageClass SC, SectionKind K,
MCSymbol *Begin)
MCSymbolXCOFF *QualName, MCSymbol *Begin)
: MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC),
Type(ST), StorageClass(SC) {
Type(ST), StorageClass(SC), QualName(QualName) {
assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM) &&
"Invalid or unhandled type for csect.");
assert(QualName != nullptr && "QualName is needed.");
QualName->setStorageClass(SC);
QualName->setContainingCsect(this);
}
public:
@ -59,6 +62,7 @@ public:
XCOFF::StorageMappingClass getMappingClass() const { return MappingClass; }
XCOFF::StorageClass getStorageClass() const { return StorageClass; }
XCOFF::SymbolType getCSectType() const { return Type; }
MCSymbolXCOFF *getQualNameSymbol() const { return QualName; }
void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,

View File

@ -546,11 +546,13 @@ public:
/// Emits an lcomm directive with XCOFF csect information.
///
/// \param Symbol - The symbol we are emiting.
/// \param LabelSym - Label on the block of storage.
/// \param Size - The size of the block of storage.
/// \param ByteAlignment - The alignment of the symbol in bytes. Must be a power
/// of 2.
virtual void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
/// \param CsectSym - Csect name for the block of storage.
/// \param ByteAlignment - The alignment of the symbol in bytes. Must be a
/// power of 2.
virtual void EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlignment);
/// Emit an ELF .size directive.

View File

@ -26,7 +26,8 @@ public:
uint64_t Size = 0, unsigned ByteAlignment = 0,
SMLoc Loc = SMLoc()) override;
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
void EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) override;
};

View File

@ -8,6 +8,7 @@ add_llvm_library(LLVMBinaryFormat
MsgPackReader.cpp
MsgPackWriter.cpp
Wasm.cpp
XCOFF.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/BinaryFormat

View File

@ -0,0 +1,28 @@
//===-- llvm/BinaryFormat/XCOFF.cpp - The XCOFF file format -----*- C++/-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/BinaryFormat/XCOFF.h"
using namespace llvm;
StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) {
switch (SMC) {
case XCOFF::XMC_DS:
return "DS";
case XCOFF::XMC_RW:
return "RW";
case XCOFF::XMC_PR:
return "PR";
case XCOFF::XMC_TC0:
return "TC0";
case XCOFF::XMC_BS:
return "BS";
default:
report_fatal_error("Unhandled storage-mapping class.");
}
}

View File

@ -100,7 +100,7 @@ MCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
return MCBinaryExpr::createSub(Res, PC, Context);
}
static bool isAcceptableChar(char C) {
bool MCAsmInfo::isAcceptableChar(char C) const {
return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
(C >= '0' && C <= '9') || C == '_' || C == '$' || C == '.' || C == '@';
}

View File

@ -26,10 +26,11 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
SupportsQuotedNames = false;
}
bool MCAsmInfoXCOFF::isValidUnquotedName(StringRef Name) const {
// FIXME: Remove this function when we stop using "TOC[TC0]" as a symbol name.
if (Name.equals("TOC[TC0]"))
bool MCAsmInfoXCOFF::isAcceptableChar(char C) const {
// QualName is allowed for a MCSymbolXCOFF, and
// QualName contains '[' and ']'.
if (C == '[' || C == ']')
return true;
return MCAsmInfo::isValidUnquotedName(Name);
return MCAsmInfo::isAcceptableChar(C);
}

View File

@ -164,7 +164,8 @@ public:
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
void EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) override;
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@ -765,16 +766,18 @@ void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
// We need an XCOFF-specific version of this directive as the AIX syntax
// requires a QualName argument identifying the csect name and storage mapping
// class to appear before the alignment if we are specifying it.
void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlignment) {
assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
"We only support writing log base-2 alignment format with XCOFF.");
assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.");
OS << "\t.lcomm\t";
Symbol->print(OS, MAI);
OS << ',' << Size;
OS << ',' << Symbol->getName();
LabelSym->print(OS, MAI);
OS << ',' << Size << ',';
CsectSym->print(OS, MAI);
OS << ',' << Log2_32(ByteAlignment);
EmitEOL();

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCDwarf.h"
@ -550,13 +551,15 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
// Otherwise, return a new section.
StringRef CachedName = Entry.first.SectionName;
MCSymbol *QualName = getOrCreateSymbol(
CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]");
MCSymbol *Begin = nullptr;
if (BeginSymName)
Begin = createTempSymbol(BeginSymName, false);
MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate())
MCSectionXCOFF(CachedName, SMC, Type, SC, Kind, Begin);
MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) MCSectionXCOFF(
CachedName, SMC, Type, SC, Kind, cast<MCSymbolXCOFF>(QualName), Begin);
Entry.second = Result;
auto *F = new MCDataFragment();

View File

@ -15,18 +15,6 @@ using namespace llvm;
MCSectionXCOFF::~MCSectionXCOFF() = default;
static StringRef getMappingClassString(XCOFF::StorageMappingClass SMC) {
switch (SMC) {
case XCOFF::XMC_DS:
return "DS";
case XCOFF::XMC_RW:
return "RW";
case XCOFF::XMC_PR:
return "PR";
default:
report_fatal_error("Unhandled storage-mapping class.");
}
}
void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
@ -35,9 +23,7 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
if (getMappingClass() != XCOFF::XMC_PR)
report_fatal_error("Unhandled storage-mapping class for .text csect");
OS << "\t.csect " << getSectionName() << "["
<< getMappingClassString(getMappingClass())
<< "]" << '\n';
OS << "\t.csect " << QualName->getName() << '\n';
return;
}
@ -45,8 +31,7 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
switch (getMappingClass()) {
case XCOFF::XMC_RW:
case XCOFF::XMC_DS:
OS << "\t.csect " << getSectionName() << "["
<< getMappingClassString(getMappingClass()) << "]" << '\n';
OS << "\t.csect " << QualName->getName() << '\n';
break;
case XCOFF::XMC_TC0:
OS << "\t.toc\n";

View File

@ -1063,7 +1063,8 @@ void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
void MCStreamer::EmitCOFFSymbolType(int Type) {
llvm_unreachable("this directive only supported on COFF targets");
}
void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) {
llvm_unreachable("this directive only supported on XCOFF targets");
}

View File

@ -94,8 +94,9 @@ MCStreamer *llvm::createXCOFFStreamer(MCContext &Context,
return S;
}
void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol,
void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlignment) {
EmitCommonSymbol(Symbol, Size, ByteAlignment);
EmitCommonSymbol(CsectSym, Size, ByteAlignment);
}

View File

@ -78,15 +78,7 @@ struct ControlSection {
// (approximately) the same storage mapping class. For example all the csects
// with a storage mapping class of `xmc_pr` will get placed into the same
// container.
struct CsectGroup {
enum LabelDefinitionSupport : bool {
LabelDefSupported = true,
LabelDefUnsupported = false
};
const LabelDefinitionSupport SupportLabelDef;
std::deque<ControlSection> Csects;
};
using CsectGroup = std::deque<ControlSection>;
using CsectGroups = std::deque<CsectGroup *>;
@ -132,7 +124,7 @@ struct Section {
Index = UninitializedIndex;
// Clear any csects we have stored.
for (auto *Group : Groups)
Group->Csects.clear();
Group->clear();
}
Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
@ -157,9 +149,9 @@ class XCOFFObjectWriter : public MCObjectWriter {
// CsectGroups. These store the csects which make up different parts of
// the sections. Should have one for each set of csects that get mapped into
// the same section and get handled in a 'similar' way.
CsectGroup ProgramCodeCsects{CsectGroup::LabelDefSupported, {}};
CsectGroup DataCsects{CsectGroup::LabelDefSupported, {}};
CsectGroup BSSCsects{CsectGroup::LabelDefUnsupported, {}};
CsectGroup ProgramCodeCsects;
CsectGroup DataCsects;
CsectGroup BSSCsects;
// The Predefined sections.
Section Text;
@ -294,8 +286,8 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
continue;
CsectGroup &Group = getCsectGroup(MCSec);
Group.Csects.emplace_back(MCSec);
WrapperMap[MCSec] = &Group.Csects.back();
Group.emplace_back(MCSec);
WrapperMap[MCSec] = &Group.back();
}
for (const MCSymbol &S : Asm.symbols()) {
@ -309,6 +301,11 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
"Expected containing csect to exist in map");
// If the symbol is the Csect itself, we don't need to put the symbol
// into Csect's Syms.
if (XSym == ContainingCsect->getQualNameSymbol())
continue;
// Lookup the containing csect and add the symbol to it.
WrapperMap[ContainingCsect]->Syms.emplace_back(XSym);
@ -339,7 +336,7 @@ void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
assert(CurrentAddressLocation == Section->Address &&
"We should have no padding between sections.");
for (const auto *Group : Section->Groups) {
for (const auto &Csect : Group->Csects) {
for (const auto &Csect : *Group) {
if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
W.OS.write_zeros(PaddingSize);
Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
@ -527,20 +524,14 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
continue;
for (const auto *Group : Section->Groups) {
if (Group->Csects.empty())
if (Group->empty())
continue;
const bool SupportLabelDef = Group->SupportLabelDef;
const int16_t SectionIndex = Section->Index;
for (const auto &Csect : Group->Csects) {
for (const auto &Csect : *Group) {
// Write out the control section first and then each symbol in it.
writeSymbolTableEntryForControlSection(
Csect, SectionIndex, Csect.MCCsect->getStorageClass());
if (!SupportLabelDef) {
assert(Csect.Syms.size() == 1 && "Csect should only contain 1 symbol "
"which is its label definition.");
continue;
}
for (const auto Sym : Csect.Syms)
writeSymbolTableEntryForCsectMemberLabel(
@ -563,9 +554,8 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
for (auto *Section : Sections) {
const bool IsEmpty =
llvm::all_of(Section->Groups, [](const CsectGroup *Group) {
return Group->Csects.empty();
});
llvm::all_of(Section->Groups,
[](const CsectGroup *Group) { return Group->empty(); });
if (IsEmpty)
continue;
@ -576,11 +566,10 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
bool SectionAddressSet = false;
for (auto *Group : Section->Groups) {
if (Group->Csects.empty())
if (Group->empty())
continue;
const bool SupportLabelDef = Group->SupportLabelDef;
for (auto &Csect : Group->Csects) {
for (auto &Csect : *Group) {
const MCSectionXCOFF *MCSec = Csect.MCCsect;
Csect.Address = alignTo(Address, MCSec->getAlignment());
Csect.Size = Layout.getSectionAddressSize(MCSec);
@ -588,10 +577,7 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Csect.SymbolTableIndex = SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for the csect.
SymbolTableIndex += 2;
if (!SupportLabelDef)
continue;
for (auto &Sym : Csect.Syms) {
Sym.SymbolTableIndex = SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for each contained
@ -601,7 +587,7 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
}
if (!SectionAddressSet) {
Section->Address = Group->Csects.front().Address;
Section->Address = Group->front().Address;
SectionAddressSet = true;
}
}

View File

@ -1752,15 +1752,15 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
"not supported yet.");
// Create the containing csect and switch to it.
MCSectionXCOFF *CSect = cast<MCSectionXCOFF>(
MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
OutStreamer->SwitchSection(CSect);
OutStreamer->SwitchSection(Csect);
// Create the symbol, set its storage class, and emit it.
MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV));
GVSym->setStorageClass(
TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
GVSym->setContainingCsect(CSect);
GVSym->setContainingCsect(Csect);
const DataLayout &DL = GV->getParent()->getDataLayout();
@ -1771,9 +1771,10 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
if (GVKind.isBSSLocal())
OutStreamer->EmitXCOFFLocalCommonSymbol(GVSym, Size, Align);
OutStreamer->EmitXCOFFLocalCommonSymbol(
GVSym, Size, Csect->getQualNameSymbol(), Align);
else
OutStreamer->EmitCommonSymbol(GVSym, Size, Align);
OutStreamer->EmitCommonSymbol(Csect->getQualNameSymbol(), Size, Align);
return;
}
@ -1813,11 +1814,9 @@ void PPCAIXAsmPrinter::EmitEndOfAsmFile(Module &M) {
return;
// Emit TOC base.
MCSymbol *TOCBaseSym = OutContext.getOrCreateSymbol(StringRef("TOC[TC0]"));
MCSectionXCOFF *TOCBaseSection = OutStreamer->getContext().getXCOFFSection(
StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT,
SectionKind::getData());
cast<MCSymbolXCOFF>(TOCBaseSym)->setContainingCsect(TOCBaseSection);
// Switch to section to emit TOC base.
OutStreamer->SwitchSection(TOCBaseSection);
}

View File

@ -84,13 +84,13 @@
; CHECK-NEXT: .llong 4613937818241073152
; CHECK-NEXT: .llong 4616189618054758400
; CHECK-NEXT: .comm a,4,2
; CHECK-NEXT: .comm b,8,3
; CHECK-NEXT: .comm c,2,1
; CHECK-NEXT: .comm d,8,3
; CHECK-NEXT: .comm f,4,2
; CHECK-NEXT: .comm over_aligned_comm,8,5
; CHECK-NEXT: .comm array,33,0
; CHECK-NEXT: .comm a[RW],4,2
; CHECK-NEXT: .comm b[RW],8,3
; CHECK-NEXT: .comm c[RW],2,1
; CHECK-NEXT: .comm d[RW],8,3
; CHECK-NEXT: .comm f[RW],4,2
; CHECK-NEXT: .comm over_aligned_comm[RW],8,5
; CHECK-NEXT: .comm array[RW],33,0
; OBJ: File: {{.*}}aix-xcoff-data.ll.tmp.o
; OBJ-NEXT: Format: aixcoff-rs6000

View File

@ -14,9 +14,9 @@
@b = internal global i64 0, align 8
@c = internal global i16 0, align 2
; CHECK: .lcomm a,4,a,2
; CHECK-NEXT: .lcomm b,8,b,3
; CHECK-NEXT: .lcomm c,2,c,1
; CHECK: .lcomm a,4,a[BS],2
; CHECK-NEXT: .lcomm b,8,b[BS],3
; CHECK-NEXT: .lcomm c,2,c[BS],1
; OBJ: File: {{.*}}aix-xcoff-lcomm.ll.tmp.o
; OBJ-NEXT: Format: aixcoff-rs6000