Skip to content

Commit

Permalink
[XCOFF] Enable explicit sections on AIX
Browse files Browse the repository at this point in the history
Implement mechanism to allow explicit sections to be generated on AIX.

Reviewed By: DiggerLin

Differential Revision: https://reviews.llvm.org/D88615
  • Loading branch information
jasonliudev committed Nov 9, 2020
1 parent df30bc0 commit 42d2109
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 40 deletions.
4 changes: 2 additions & 2 deletions llvm/include/llvm/MC/MCContext.h
Expand Up @@ -564,8 +564,8 @@ namespace llvm {

MCSectionXCOFF *getXCOFFSection(StringRef Section,
XCOFF::StorageMappingClass MappingClass,
XCOFF::SymbolType CSectType,
SectionKind K,
XCOFF::SymbolType CSectType, SectionKind K,
bool MultiSymbolsAllowed = false,
const char *BeginSymName = nullptr);

// Create and save a copy of STI and return a reference to the copy.
Expand Down
8 changes: 6 additions & 2 deletions llvm/include/llvm/MC/MCSectionXCOFF.h
Expand Up @@ -36,13 +36,16 @@ class MCSectionXCOFF final : public MCSection {
XCOFF::SymbolType Type;
MCSymbolXCOFF *const QualName;
StringRef SymbolTableName;
bool MultiSymbolsAllowed;
static constexpr unsigned DefaultAlignVal = 4;

MCSectionXCOFF(StringRef Name, XCOFF::StorageMappingClass SMC,
XCOFF::SymbolType ST, SectionKind K, MCSymbolXCOFF *QualName,
MCSymbol *Begin, StringRef SymbolTableName)
MCSymbol *Begin, StringRef SymbolTableName,
bool MultiSymbolsAllowed)
: MCSection(SV_XCOFF, Name, K, Begin), MappingClass(SMC), Type(ST),
QualName(QualName), SymbolTableName(SymbolTableName) {
QualName(QualName), SymbolTableName(SymbolTableName),
MultiSymbolsAllowed(MultiSymbolsAllowed) {
assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM || ST == XCOFF::XTY_ER) &&
"Invalid or unhandled type for csect.");
assert(QualName != nullptr && "QualName is needed.");
Expand Down Expand Up @@ -75,6 +78,7 @@ class MCSectionXCOFF final : public MCSection {
bool UseCodeAlign() const override;
bool isVirtualSection() const override;
StringRef getSymbolTableName() const { return SymbolTableName; }
bool isMultiSymbolsAllowed() const { return MultiSymbolsAllowed; }
};

} // end namespace llvm
Expand Down
48 changes: 33 additions & 15 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Expand Up @@ -2110,7 +2110,8 @@ TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV,
return cast<MCSectionXCOFF>(
getSectionForFunctionDescriptor(cast<Function>(GO), TM))
->getQualNameSymbol();
if (TM.getDataSections() || GOKind.isCommon() || GOKind.isBSSLocal())
if ((TM.getDataSections() && !GO->hasSection()) || GOKind.isCommon() ||
GOKind.isBSSLocal())
return cast<MCSectionXCOFF>(SectionForGlobal(GO, GOKind, TM))
->getQualNameSymbol();
}
Expand All @@ -2121,7 +2122,22 @@ TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV,

MCSection *TargetLoweringObjectFileXCOFF::getExplicitSectionGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
report_fatal_error("XCOFF explicit sections not yet implemented.");
if (!GO->hasSection())
report_fatal_error("#pragma clang section is not yet supported");

StringRef SectionName = GO->getSection();
XCOFF::StorageMappingClass MappingClass;
if (Kind.isText())
MappingClass = XCOFF::XMC_PR;
else if (Kind.isData() || Kind.isReadOnlyWithRel() || Kind.isBSS())
MappingClass = XCOFF::XMC_RW;
else if (Kind.isReadOnly())
MappingClass = XCOFF::XMC_RO;
else
report_fatal_error("XCOFF other section types not yet implemented.");

return getContext().getXCOFFSection(SectionName, MappingClass, XCOFF::XTY_SD,
Kind, /* MultiSymbolsAllowed*/ true);
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForExternalReference(
Expand All @@ -2147,7 +2163,7 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
getNameWithPrefix(Name, GO, TM);
return getContext().getXCOFFSection(
Name, Kind.isBSSLocal() ? XCOFF::XMC_BS : XCOFF::XMC_RW, XCOFF::XTY_CM,
Kind, /* BeginSymbolName */ nullptr);
Kind);
}

if (Kind.isMergeableCString()) {
Expand All @@ -2162,8 +2178,9 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
if (TM.getDataSections())
getNameWithPrefix(Name, GO, TM);

return getContext().getXCOFFSection(Name, XCOFF::XMC_RO, XCOFF::XTY_SD,
Kind, /*BeginSymbolName*/ nullptr);
return getContext().getXCOFFSection(
Name, XCOFF::XMC_RO, XCOFF::XTY_SD, Kind,
/* MultiSymbolsAllowed*/ !TM.getDataSections());
}

if (Kind.isText()) {
Expand Down Expand Up @@ -2290,21 +2307,22 @@ MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol(
isa_and_nonnull<Function>(cast<GlobalAlias>(Func)->getBaseObject()))) &&
"Func must be a function or an alias which has a function as base "
"object.");

SmallString<128> NameStr;
NameStr.push_back('.');
getNameWithPrefix(NameStr, Func, TM);

// When -function-sections is enabled, it's not necessary to emit
// function entry point label any more. We will use function entry
// point csect instead. And for function delcarations, the undefined symbols
// gets treated as csect with XTY_ER property.
if ((TM.getFunctionSections() || Func->isDeclaration()) &&
// When -function-sections is enabled and explicit section is not specified,
// it's not necessary to emit function entry point label any more. We will use
// function entry point csect instead. And for function delcarations, the
// undefined symbols gets treated as csect with XTY_ER property.
if (((TM.getFunctionSections() && !Func->hasSection()) ||
Func->isDeclaration()) &&
isa<Function>(Func)) {
return cast<MCSectionXCOFF>(
getContext().getXCOFFSection(
NameStr, XCOFF::XMC_PR,
Func->isDeclaration() ? XCOFF::XTY_ER : XCOFF::XTY_SD,
SectionKind::getText()))
return getContext()
.getXCOFFSection(NameStr, XCOFF::XMC_PR,
Func->isDeclaration() ? XCOFF::XTY_ER : XCOFF::XTY_SD,
SectionKind::getText())
->getQualNameSymbol();
}

Expand Down
20 changes: 12 additions & 8 deletions llvm/lib/MC/MCContext.cpp
Expand Up @@ -659,17 +659,21 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
return Result;
}

MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
XCOFF::StorageMappingClass SMC,
XCOFF::SymbolType Type,
SectionKind Kind,
const char *BeginSymName) {
MCSectionXCOFF *
MCContext::getXCOFFSection(StringRef Section, XCOFF::StorageMappingClass SMC,
XCOFF::SymbolType Type, SectionKind Kind,
bool MultiSymbolsAllowed, const char *BeginSymName) {
// Do the lookup. If we have a hit, return it.
auto IterBool = XCOFFUniquingMap.insert(
std::make_pair(XCOFFSectionKey{Section.str(), SMC}, nullptr));
auto &Entry = *IterBool.first;
if (!IterBool.second)
return Entry.second;
if (!IterBool.second) {
MCSectionXCOFF *ExistedEntry = Entry.second;
if (ExistedEntry->isMultiSymbolsAllowed() != MultiSymbolsAllowed)
report_fatal_error("section's multiply symbols policy does not match");

return ExistedEntry;
}

// Otherwise, return a new section.
StringRef CachedName = Entry.first.SectionName;
Expand All @@ -684,7 +688,7 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
// CachedName contains invalid character(s) such as '$' for an XCOFF symbol.
MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate())
MCSectionXCOFF(QualName->getUnqualifiedName(), SMC, Type, Kind, QualName,
Begin, CachedName);
Begin, CachedName, MultiSymbolsAllowed);
Entry.second = Result;

auto *F = new MCDataFragment();
Expand Down
18 changes: 9 additions & 9 deletions llvm/lib/MC/MCObjectFileInfo.cpp
Expand Up @@ -864,17 +864,17 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
// get placed into this csect. The choice of csect name is not a property of
// the ABI or object file format. For example, the XL compiler uses an unnamed
// csect for program code.
TextSection =
Ctx->getXCOFFSection(".text", XCOFF::StorageMappingClass::XMC_PR,
XCOFF::XTY_SD, SectionKind::getText());
TextSection = Ctx->getXCOFFSection(
".text", XCOFF::StorageMappingClass::XMC_PR, XCOFF::XTY_SD,
SectionKind::getText(), /* MultiSymbolsAllowed*/ true);

DataSection =
Ctx->getXCOFFSection(".data", XCOFF::StorageMappingClass::XMC_RW,
XCOFF::XTY_SD, SectionKind::getData());
DataSection = Ctx->getXCOFFSection(
".data", XCOFF::StorageMappingClass::XMC_RW, XCOFF::XTY_SD,
SectionKind::getData(), /* MultiSymbolsAllowed*/ true);

ReadOnlySection =
Ctx->getXCOFFSection(".rodata", XCOFF::StorageMappingClass::XMC_RO,
XCOFF::XTY_SD, SectionKind::getReadOnly());
ReadOnlySection = Ctx->getXCOFFSection(
".rodata", XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD,
SectionKind::getReadOnly(), /* MultiSymbolsAllowed*/ true);

TOCBaseSection =
Ctx->getXCOFFSection("TOC", XCOFF::StorageMappingClass::XMC_TC0,
Expand Down
7 changes: 3 additions & 4 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Expand Up @@ -1738,9 +1738,6 @@ void PPCAIXAsmPrinter::ValidateGV(const GlobalVariable *GV) {
if (GV->isThreadLocal())
report_fatal_error("Thread local not yet supported on AIX.");

if (GV->hasSection())
report_fatal_error("Custom section for Data not yet supported.");

if (GV->hasComdat())
report_fatal_error("COMDAT not yet supported by AIX.");
}
Expand Down Expand Up @@ -1811,10 +1808,12 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
MCSymbol *EmittedInitSym = GVSym;
emitLinkage(GV, EmittedInitSym);
emitAlignment(getGVAlignment(GV, DL), GV);

// When -fdata-sections is enabled, every GlobalVariable will
// be put into its own csect; therefore, label is not necessary here.
if (!TM.getDataSections())
if (!TM.getDataSections() || GV->hasSection()) {
OutStreamer->emitLabel(EmittedInitSym);
}

// Emit aliasing label for global variable.
llvm::for_each(GOAliasMap[GV], [this](const GlobalAlias *Alias) {
Expand Down
@@ -0,0 +1,6 @@
; RUN: not --crash llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff \
; RUN: -mcpu=pwr4 -mattr=-altivec < %s 2>&1 | FileCheck %s
; CHECK: LLVM ERROR: section's multiply symbols policy does not match

@a = global i32 3, section "ab", align 4
@ab = global i32 5, align 4

0 comments on commit 42d2109

Please sign in to comment.