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 *);
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(
}
}
#endif
+
+ auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,
+ ptrdiff_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.
+ ptrdiff_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 ptrdiff_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;
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;
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;
}
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>(
--- /dev/null
+# 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]
if not 'PowerPC' in config.root.targets:
config.unsupported = True
+
+config.suffixes.add('.py')