[llvm] 9868ea7 - [XCOFF][AIX] Handle TOC entries that could not be reached by positive range in small code model
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 06:43:06 PDT 2020
Author: jasonliu
Date: 2020-09-14T13:41:34Z
New Revision: 9868ea764f31b0fd4ec250867807aa0ad7958abf
URL: https://github.com/llvm/llvm-project/commit/9868ea764f31b0fd4ec250867807aa0ad7958abf
DIFF: https://github.com/llvm/llvm-project/commit/9868ea764f31b0fd4ec250867807aa0ad7958abf.diff
LOG: [XCOFF][AIX] Handle TOC entries that could not be reached by positive range in small code model
Summary:
In small code model, AIX assembler could not deal with labels that
could not be reached within the [-0x8000, 0x8000) range from TOC base.
So when generating the assembly, we would need to help the assembler
by subtracting an offset from the label to keep the actual value
within [-0x8000, 0x8000).
Reviewed By: hubert.reinterpretcast, Xiangling_L
Differential Revision: https://reviews.llvm.org/D86879
Added:
llvm/test/CodeGen/PowerPC/aix-overflow-toc.py
Modified:
llvm/lib/MC/XCOFFObjectWriter.cpp
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
llvm/test/CodeGen/PowerPC/lit.local.cfg
Removed:
################################################################################
diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 5047b5041aa7..d6cee3bb59bb 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -49,7 +49,6 @@ namespace {
constexpr unsigned DefaultSectionAlign = 4;
constexpr int16_t MaxSectionIndex = INT16_MAX;
-constexpr uint16_t MaxTOCSizeInARegion = UINT16_MAX;
// Packs the csect's alignment and type into a byte.
uint8_t getEncodedType(const MCSectionXCOFF *);
@@ -431,12 +430,15 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
else if (Type == XCOFF::RelocationType::R_TOC ||
Type == XCOFF::RelocationType::R_TOCL) {
- // The FixedValue should be the TC entry offset from TOC-base.
- FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
- if (FixedValue >= MaxTOCSizeInARegion)
- report_fatal_error(
- "handling of TOC entries could not fit in the initial TOC "
- "entry region is not yet supported");
+ // The FixedValue should be the TOC entry offset from the TOC-base plus any
+ // constant offset value.
+ const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
+ TOCCsects.front().Address +
+ Target.getConstant();
+ if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
+ report_fatal_error("TOCEntryOffset overflows in small code model mode");
+
+ FixedValue = TOCEntryOffset;
}
assert(
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 8f1477012bfd..f950e748158f 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -579,6 +579,38 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
}
}
#endif
+
+ auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,
+ ptr
diff _t OriginalOffset) {
+ // Apply an offset to the TOC-based expression such that the adjusted
+ // notional offset from the TOC base (to be encoded into the instruction's D
+ // or DS field) is the signed 16-bit truncation of the original notional
+ // offset from the TOC base.
+ // This is consistent with the treatment used both by XL C/C++ and
+ // by AIX ld -r.
+ ptr
diff _t Adjustment =
+ OriginalOffset - llvm::SignExtend32<16>(OriginalOffset);
+ return MCBinaryExpr::createAdd(
+ Expr, MCConstantExpr::create(-Adjustment, OutContext), OutContext);
+ };
+
+ auto getTOCEntryLoadingExprForXCOFF =
+ [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
+ this](const MCSymbol *MOSymbol, const MCExpr *Expr) -> const MCExpr * {
+ const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
+ const auto TOCEntryIter = TOC.find(MOSymbol);
+ assert(TOCEntryIter != TOC.end() &&
+ "Could not find the TOC entry for this symbol.");
+ const ptr
diff _t EntryDistanceFromTOCBase =
+ (TOCEntryIter - TOC.begin()) * EntryByteSize;
+ constexpr int16_t PositiveTOCRange = INT16_MAX;
+
+ if (EntryDistanceFromTOCBase > PositiveTOCRange)
+ return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
+
+ return Expr;
+ };
+
// Lower multi-instruction pseudo operations.
switch (MI->getOpcode()) {
default: break;
@@ -725,6 +757,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
assert(
TM.getCodeModel() == CodeModel::Small &&
"This pseudo should only be selected for 32-bit small code model.");
+ Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp);
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
return;
@@ -753,17 +786,20 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
"Invalid operand!");
+ // Map the operand to its corresponding MCSymbol.
+ const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+
// Map the machine operand to its corresponding MCSymbol, then map the
// global address operand to be a reference to the TOC entry we will
// synthesize later.
- MCSymbol *TOCEntry =
- lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO, *this));
+ MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
const MCSymbolRefExpr::VariantKind VK =
IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
const MCExpr *Exp =
MCSymbolRefExpr::create(TOCEntry, VK, OutContext);
- TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
+ TmpInst.getOperand(1) = MCOperand::createExpr(
+ IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp) : Exp);
EmitToStreamer(*OutStreamer, TmpInst);
return;
}
@@ -1821,16 +1857,6 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
PPCTargetStreamer *TS =
static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
- const unsigned EntryByteSize = Subtarget->isPPC64() ? 8 : 4;
- const unsigned TOCEntriesByteSize = TOC.size() * EntryByteSize;
- // TODO: If TOC entries' size is larger than 32768, then we run out of
- // positive displacement to reach the TOC entry. We need to decide how to
- // handle entries' size larger than that later.
- if (TOCEntriesByteSize > 32767) {
- report_fatal_error("Handling of TOC entry displacement larger than 32767 "
- "is not yet implemented.");
- }
-
for (auto &I : TOC) {
// Setup the csect for the current TC entry.
MCSectionXCOFF *TCEntry = cast<MCSectionXCOFF>(
diff --git a/llvm/test/CodeGen/PowerPC/aix-overflow-toc.py b/llvm/test/CodeGen/PowerPC/aix-overflow-toc.py
new file mode 100644
index 000000000000..5e56b6f9fa25
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-overflow-toc.py
@@ -0,0 +1,66 @@
+# RUN: python %s > %t.ll
+# RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=small -mcpu=pwr4 -mattr=-altivec -O0 < %t.ll | \
+# RUN: FileCheck --check-prefix=ASM32 %s
+
+# RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=small -mcpu=pwr4 -mattr=-altivec -O0 < %t.ll | \
+# RUN: FileCheck --check-prefix=ASM64 %s
+
+# RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=small -mcpu=pwr4 -mattr=-altivec -O0 \
+# RUN: -filetype=obj -o %t.o < %t.ll
+# RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS32 %s
+
+# RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff \
+# RUN: -mcpu=pwr4 -mattr=-altivec -filetype=obj -o %t.o 2>&1 < %t.ll | \
+# RUN: FileCheck --check-prefix=XCOFF64 %s
+# XCOFF64: LLVM ERROR: 64-bit XCOFF object files are not supported yet.
+
+numentries = 12290
+for x in range(0, numentries):
+ print("@a%d = global i32 0, align 4" % (x))
+
+print("define void @foo() {")
+print("entry:")
+for x in range(0, numentries):
+ print("store i32 1, i32* @a%d, align 4" % (x))
+print("ret void")
+print("}")
+
+# 32-bit assembly check
+# ASM32: lwz 3, L..C0(2)
+# ASM32: lwz 3, L..C1(2)
+
+# ASM32: lwz 3, L..C8191(2)
+# ASM32: lwz 3, L..C8192-65536(2)
+# ASM32: lwz 3, L..C8193-65536(2)
+
+# ASM32: lwz 3, L..C12288-65536(2)
+# ASM32: lwz 3, L..C12289-65536(2)
+
+# 64-bit assembly check
+# ASM64: ld 3, L..C0(2)
+# ASM64: ld 3, L..C1(2)
+
+# ASM64: ld 3, L..C4095(2)
+# ASM64: ld 3, L..C4096-65536(2)
+# ASM64: ld 3, L..C4097-65536(2)
+
+# ASM64: ld 3, L..C12287-65536(2)
+# ASM64: ld 3, L..C12288-131072(2)
+# ASM64: ld 3, L..C12289-131072(2)
+
+# DIS32: 0: 80 62 00 00 lwz 3, 0(2)
+# DIS32: 00000002: R_TOC (idx: 24590) a0[TC]
+# DIS32: c: 80 62 00 04 lwz 3, 4(2)
+# DIS32: 0000000e: R_TOC (idx: 24592) a1[TC]
+
+# DIS32: fffc: 80 62 7f fc lwz 3, 32764(2)
+# DIS32: 0000fffe: R_TOC (idx: 40972) a8191[TC]
+# DIS32: 10004: 80 62 80 00 lwz 3, -32768(2)
+# DIS32: 00010006: R_TOC (idx: 40974) a8192[TC]
+# DIS32: 1000c: 80 62 80 04 lwz 3, -32764(2)
+# DIS32: 0001000e: R_TOC (idx: 40976) a8193[TC]
+
+# DIS32: 18004: 80 62 c0 00 lwz 3, -16384(2)
+# DIS32: 00018006: R_TOC (idx: 49166) a12288[TC]
+# DIS32: 1800c: 80 62 c0 04 lwz 3, -16380(2)
+# DIS32: 0001800e: R_TOC (idx: 49168) a12289[TC]
diff --git a/llvm/test/CodeGen/PowerPC/lit.local.cfg b/llvm/test/CodeGen/PowerPC/lit.local.cfg
index 091332439b18..1dbbf92fcf5e 100644
--- a/llvm/test/CodeGen/PowerPC/lit.local.cfg
+++ b/llvm/test/CodeGen/PowerPC/lit.local.cfg
@@ -1,2 +1,4 @@
if not 'PowerPC' in config.root.targets:
config.unsupported = True
+
+config.suffixes.add('.py')
More information about the llvm-commits
mailing list