namespace XCOFF {
// Constants used in the XCOFF definition.
-enum { FileNamePadSize = 6, NameSize = 8, SymbolTableEntrySize = 18 };
+enum {
+ FileNamePadSize = 6,
+ NameSize = 8,
+ SymbolTableEntrySize = 18,
+ RelocationSerializationSize32 = 10
+};
enum ReservedSectionNum { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 };
}
bool is64Bit() const { return Is64Bit; }
+ // Returns relocation info such as type, sign and size.
+ // First element of the pair contains type,
+ // second element contains sign and size.
+ virtual std::pair<uint8_t, uint8_t>
+ getRelocTypeAndSignSize(const MCValue &Target, const MCFixup &Fixup,
+ bool IsPCRel) const = 0;
+
private:
bool Is64Bit;
};
raw_svector_ostream VecOS(Code);
Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
- // TODO: Handle Fixups later
-
+ // Add the fixups and data.
MCDataFragment *DF = getOrCreateDataFragment(&STI);
+ const size_t ContentsSize = DF->getContents().size();
+ auto &DataFragmentFixups = DF->getFixups();
+ for (auto &Fixup : Fixups) {
+ Fixup.setOffset(Fixup.getOffset() + ContentsSize);
+ DataFragmentFixups.push_back(Fixup);
+ }
+
DF->setHasInstructions(STI);
DF->getContents().append(Code.begin(), Code.end());
}
//===----------------------------------------------------------------------===//
#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCSymbolXCOFF.h"
// Packs the csect's alignment and type into a byte.
uint8_t getEncodedType(const MCSectionXCOFF *);
+struct XCOFFRelocation {
+ uint32_t SymbolTableIndex;
+ uint32_t FixupOffsetInCsect;
+ uint8_t SignAndSize;
+ uint8_t Type;
+};
+
// Wrapper around an MCSymbolXCOFF.
struct Symbol {
const MCSymbolXCOFF *const MCSym;
uint32_t Size;
SmallVector<Symbol, 1> Syms;
+ SmallVector<XCOFFRelocation, 1> Relocations;
StringRef getName() const { return MCCsect->getSectionName(); }
ControlSection(const MCSectionXCOFF *MCSec)
: MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
// with a storage mapping class of `xmc_pr` will get placed into the same
// container.
using CsectGroup = std::deque<ControlSection>;
-
using CsectGroups = std::deque<CsectGroup *>;
// Represents the data related to a section excluding the csects that make up
uint32_t SymbolTableEntryCount = 0;
uint32_t SymbolTableOffset = 0;
uint16_t SectionCount = 0;
+ uint32_t RelocationEntryOffset = 0;
support::endian::Writer W;
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
StringTableBuilder Strings;
+ // Maps the MCSection representation to its corresponding ControlSection
+ // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
+ // from its containing MCSectionXCOFF.
+ DenseMap<const MCSectionXCOFF *, ControlSection *> SectionMap;
+
+ // Maps the MCSymbol representation to its corrresponding symbol table index.
+ // Needed for relocation.
+ DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
+
// 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.
void writeSectionHeaderTable();
void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
void writeSymbolTable(const MCAsmLayout &Layout);
+ void writeRelocations();
+ void writeRelocation(XCOFFRelocation Reloc, const ControlSection &CSection);
// Called after all the csects and symbols have been processed by
// `executePostLayoutBinding`, this function handles building up the majority
// *) Builds up the section header table by adding any non-empty sections to
// `Sections`.
void assignAddressesAndIndices(const MCAsmLayout &);
+ void finalizeSectionInfo();
bool
needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
CsectGroups{&BSSCsects}) {}
void XCOFFObjectWriter::reset() {
- UndefinedCsects.clear();
+ // Clear the mappings we created.
+ SymbolIndexMap.clear();
+ SectionMap.clear();
+ UndefinedCsects.clear();
// Reset any sections we have written to, and empty the section header table.
for (auto *Sec : Sections)
Sec->reset();
- // Reset the symbol table and string table.
+ // Reset states in XCOFFObjectWriter.
SymbolTableEntryCount = 0;
SymbolTableOffset = 0;
SectionCount = 0;
+ RelocationEntryOffset = 0;
Strings.clear();
MCObjectWriter::reset();
if (TargetObjectWriter->is64Bit())
report_fatal_error("64-bit XCOFF object files are not supported yet.");
- // Maps the MC Section representation to its corresponding ControlSection
- // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
- // from its containing MCSectionXCOFF.
- DenseMap<const MCSectionXCOFF *, ControlSection *> WrapperMap;
-
for (const auto &S : Asm) {
const auto *MCSec = cast<const MCSectionXCOFF>(&S);
- assert(WrapperMap.find(MCSec) == WrapperMap.end() &&
+ assert(SectionMap.find(MCSec) == SectionMap.end() &&
"Cannot add a csect twice.");
assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
"An undefined csect should not get registered.");
CsectGroup &Group = getCsectGroup(MCSec);
Group.emplace_back(MCSec);
- WrapperMap[MCSec] = &Group.back();
+ SectionMap[MCSec] = &Group.back();
}
for (const MCSymbol &S : Asm.symbols()) {
// Handle undefined symbol.
if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
UndefinedCsects.emplace_back(ContainingCsect);
+ SectionMap[ContainingCsect] = &UndefinedCsects.back();
continue;
}
if (XSym == ContainingCsect->getQualNameSymbol())
continue;
- assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
+ assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
"Expected containing csect to exist in map");
// Lookup the containing csect and add the symbol to it.
- WrapperMap[ContainingCsect]->Syms.emplace_back(XSym);
+ SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
// If the name does not fit in the storage provided in the symbol table
// entry, add it to the string table.
assignAddressesAndIndices(Layout);
}
-void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
- const MCFragment *, const MCFixup &,
- MCValue, uint64_t &) {
- // TODO: recordRelocation is not yet implemented.
+void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ uint64_t &FixedValue) {
+
+ if (Target.getSymB())
+ report_fatal_error("Handling Target.SymB for relocation is unimplemented.");
+
+ const MCSymbol &SymA = Target.getSymA()->getSymbol();
+
+ MCAsmBackend &Backend = Asm.getBackend();
+ bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel;
+
+ uint8_t Type;
+ uint8_t SignAndSize;
+ std::tie(Type, SignAndSize) =
+ TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
+
+ const MCSectionXCOFF *SymASec =
+ cast<MCSymbolXCOFF>(SymA).getContainingCsect();
+ assert(SectionMap.find(SymASec) != SectionMap.end() &&
+ "Expected containing csect to exist in map.");
+
+ // If we could not find SymA directly in SymbolIndexMap, this symbol could
+ // either be a temporary symbol or an undefined symbol. In this case, we
+ // would need to have the relocation reference its csect instead.
+ uint32_t Index = SymbolIndexMap.find(&SymA) != SymbolIndexMap.end()
+ ? SymbolIndexMap[&SymA]
+ : SymbolIndexMap[SymASec->getQualNameSymbol()];
+
+ if (Type == XCOFF::RelocationType::R_POS)
+ // The FixedValue should be symbol's virtual address in this object file
+ // plus any constant value that we might get.
+ // Notice that SymA.isDefined() could return false, but SymASec could still
+ // be a defined csect. One of the example is the TOC-base symbol.
+ FixedValue = SectionMap[SymASec]->Address +
+ (SymA.isDefined() ? Layout.getSymbolOffset(SymA) : 0) +
+ Target.getConstant();
+ else if (Type == XCOFF::RelocationType::R_TOC)
+ // The FixedValue should be the TC entry offset from TOC-base.
+ FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
+
+ assert(
+ (TargetObjectWriter->is64Bit() ||
+ Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
+ "Fragment offset + fixup offset is overflowed in 32-bit mode.");
+ uint32_t FixupOffsetInCsect =
+ Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+
+ XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
+ MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
+ assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
+ "Expected containing csect to exist in map.");
+ SectionMap[RelocationSec]->Relocations.push_back(Reloc);
}
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
if (TargetObjectWriter->is64Bit())
report_fatal_error("64-bit XCOFF object files are not supported yet.");
+ finalizeSectionInfo();
uint64_t StartOffset = W.OS.tell();
writeFileHeader();
writeSectionHeaderTable();
writeSections(Asm, Layout);
- // TODO writeRelocations();
+ writeRelocations();
writeSymbolTable(Layout);
// Write the string table.
W.write<uint32_t>(Sec->Size);
W.write<uint32_t>(Sec->FileOffsetToData);
+ W.write<uint32_t>(Sec->FileOffsetToRelocations);
- // Relocation pointer and Lineno pointer. Not supported yet.
- W.write<uint32_t>(0);
+ // Line number pointer. Not supported yet.
W.write<uint32_t>(0);
- // Relocation and line-number counts. Not supported yet.
- W.write<uint16_t>(0);
+ W.write<uint16_t>(Sec->RelocationCount);
+
+ // Line number counts. Not supported yet.
W.write<uint16_t>(0);
W.write<int32_t>(Sec->Flags);
}
}
+void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
+ const ControlSection &CSection) {
+ W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
+ W.write<uint32_t>(Reloc.SymbolTableIndex);
+ W.write<uint8_t>(Reloc.SignAndSize);
+ W.write<uint8_t>(Reloc.Type);
+}
+
+void XCOFFObjectWriter::writeRelocations() {
+ for (const auto *Section : Sections) {
+ if (Section->Index == Section::UninitializedIndex)
+ // Nothing to write for this Section.
+ continue;
+
+ for (const auto *Group : Section->Groups) {
+ if (Group->empty())
+ continue;
+
+ for (const auto &Csect : *Group) {
+ for (const auto Reloc : Csect.Relocations)
+ writeRelocation(Reloc, Csect);
+ }
+ }
+ }
+}
+
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
for (const auto &Csect : UndefinedCsects) {
writeSymbolTableEntryForControlSection(
}
for (const auto *Section : Sections) {
- // Nothing to write for this Section.
if (Section->Index == Section::UninitializedIndex)
+ // Nothing to write for this Section.
continue;
for (const auto *Group : Section->Groups) {
}
}
+void XCOFFObjectWriter::finalizeSectionInfo() {
+ for (auto *Section : Sections) {
+ if (Section->Index == Section::UninitializedIndex)
+ // Nothing to record for this Section.
+ continue;
+
+ for (const auto *Group : Section->Groups) {
+ if (Group->empty())
+ continue;
+
+ for (auto &Csect : *Group)
+ Section->RelocationCount += Csect.Relocations.size();
+ }
+ }
+
+ // Calculate the file offset to the relocation entries.
+ uint64_t RawPointer = RelocationEntryOffset;
+ for (auto Sec : Sections) {
+ if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount)
+ continue;
+
+ Sec->FileOffsetToRelocations = RawPointer;
+ const uint32_t RelocationSizeInSec =
+ Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
+ RawPointer += RelocationSizeInSec;
+ if (RawPointer > UINT32_MAX)
+ report_fatal_error("Relocation data overflowed this object file.");
+ }
+
+ // TODO Error check that the number of symbol table entries fits in 32-bits
+ // signed ...
+ if (SymbolTableEntryCount)
+ SymbolTableOffset = RawPointer;
+}
+
void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
// The first symbol table entry is for the file name. We are not emitting it
// yet, so start at index 0.
Csect.Size = 0;
Csect.Address = 0;
Csect.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for each contained symbol.
SymbolTableIndex += 2;
}
Csect.Size = Layout.getSectionAddressSize(MCSec);
Address = Csect.Address + Csect.Size;
Csect.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for the csect.
SymbolTableIndex += 2;
for (auto &Sym : Csect.Syms) {
Sym.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for each contained
// symbol.
SymbolTableIndex += 2;
Sec->FileOffsetToData = RawPointer;
RawPointer += Sec->Size;
+ if (RawPointer > UINT32_MAX)
+ report_fatal_error("Section raw data overflowed this object file.");
}
- // TODO Add in Relocation storage to the RawPointer Calculation.
- // TODO What to align the SymbolTable to?
- // TODO Error check that the number of symbol table entries fits in 32-bits
- // signed ...
- if (SymbolTableEntryCount)
- SymbolTableOffset = RawPointer;
+ RelocationEntryOffset = RawPointer;
}
// Takes the log base 2 of the alignment and shifts the result into the 5 most
uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
+ assert(sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32);
auto RelocationOrErr =
getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr),
NumRelocEntries * sizeof(XCOFFRelocation32));
//
//===----------------------------------------------------------------------===//
-#include "PPCMCTargetDesc.h"
+#include "MCTargetDesc/PPCFixupKinds.h"
+#include "MCTargetDesc/PPCMCTargetDesc.h"
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCXCOFFObjectWriter.h"
using namespace llvm;
namespace {
class PPCXCOFFObjectWriter : public MCXCOFFObjectTargetWriter {
+ static constexpr uint8_t SignBitMask = 0x80;
public:
PPCXCOFFObjectWriter(bool Is64Bit);
+
+ std::pair<uint8_t, uint8_t>
+ getRelocTypeAndSignSize(const MCValue &Target, const MCFixup &Fixup,
+ bool IsPCRel) const override;
};
} // end anonymous namespace
llvm::createPPCXCOFFObjectWriter(bool Is64Bit) {
return std::make_unique<PPCXCOFFObjectWriter>(Is64Bit);
}
+
+std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
+ const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const {
+ const MCSymbolRefExpr::VariantKind Modifier =
+ Target.isAbsolute() ? MCSymbolRefExpr::VK_None
+ : Target.getSymA()->getKind();
+ // People from AIX OS team says AIX link editor does not care about
+ // the sign bit in the relocation entry "most" of the time.
+ // The system assembler seems to set the sign bit on relocation entry
+ // based on similar property of IsPCRel. So we will do the same here.
+ // TODO: More investigation on how assembler decides to set the sign
+ // bit, and we might want to match that.
+ const uint8_t EncodedSignednessIndicator = IsPCRel ? SignBitMask : 0u;
+
+ // The magic number we use in SignAndSize has a strong relationship with
+ // the corresponding MCFixupKind. In most cases, it's the MCFixupKind
+ // number - 1, because SignAndSize encodes the bit length being
+ // relocated minus 1.
+ switch ((unsigned)Fixup.getKind()) {
+ default:
+ report_fatal_error("Unimplemented fixup kind.");
+ case PPC::fixup_ppc_half16:
+ switch (Modifier) {
+ default:
+ report_fatal_error("Unsupported modifier for half16 fixup.");
+ case MCSymbolRefExpr::VK_None:
+ return {XCOFF::RelocationType::R_TOC, EncodedSignednessIndicator | 15};
+ }
+ break;
+ case PPC::fixup_ppc_br24:
+ // Branches are 4 byte aligned, so the 24 bits we encode in
+ // the instruction actually represents a 26 bit offset.
+ return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25};
+ case FK_Data_4:
+ return {XCOFF::RelocationType::R_POS, EncodedSignednessIndicator | 31};
+ }
+}
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>(
; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck \
; RUN: --check-prefix=32-REL %s
+; RUN: llvm-objdump -D %t.o | FileCheck --check-prefix=32-DIS %s
+
; RUN: not llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \
; RUN: -mcpu=pwr4 -mattr=-altivec -filetype=obj < %s 2>&1 | FileCheck \
; RUN: --check-prefix=64-CHECK %s
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1)
-; TODO: This test should preferably check the symbol table for .o file and
-; the relocation associated with the call.
+; This test check
+; 1. The symbol table for .o file to verify .memcpy is a defined external label.
+; 2. There is no relocation associated with the call, since callee is defined.
+; 3. Branch instruction in raw data is branching back to the right callee location.
; 32-SYM: Symbol {{[{][[:space:]] *}}Index: [[#Index:]]{{[[:space:]] *}}Name: .memcpy
; 32-SYM-NEXT: Value (RelocatableAddress): 0x0
; 32-SYM-NOT: .memcpy
-; We are expecting to have the test fail when the support for relocations land.
-; 32-REL-NOT: Relocation{{[[:space:]]}}
+; 32-REL: Relocations [
+; 32-REL-NEXT: Section (index: 2) .data {
+; 32-REL-NEXT: Relocation {
+; 32-REL-NEXT: Virtual Address: 0x34
+; 32-REL-NEXT: Symbol: .memcpy (2)
+; 32-REL-NEXT: IsSigned: No
+; 32-REL-NEXT: FixupBitValue: 0
+; 32-REL-NEXT: Length: 32
+; 32-REL-NEXT: Type: R_POS (0x0)
+; 32-REL-NEXT: }
+; 32-REL-NEXT: Relocation {
+; 32-REL-NEXT: Virtual Address: 0x38
+; 32-REL-NEXT: Symbol: TOC (14)
+; 32-REL-NEXT: IsSigned: No
+; 32-REL-NEXT: FixupBitValue: 0
+; 32-REL-NEXT: Length: 32
+; 32-REL-NEXT: Type: R_POS (0x0)
+; 32-REL-NEXT: }
+; 32-REL-NEXT: Relocation {
+; 32-REL-NEXT: Virtual Address: 0x40
+; 32-REL-NEXT: Symbol: .call_memcpy (4)
+; 32-REL-NEXT: IsSigned: No
+; 32-REL-NEXT: FixupBitValue: 0
+; 32-REL-NEXT: Length: 32
+; 32-REL-NEXT: Type: R_POS (0x0)
+; 32-REL-NEXT: }
+; 32-REL-NEXT: Relocation {
+; 32-REL-NEXT: Virtual Address: 0x44
+; 32-REL-NEXT: Symbol: TOC (14)
+; 32-REL-NEXT: IsSigned: No
+; 32-REL-NEXT: FixupBitValue: 0
+; 32-REL-NEXT: Length: 32
+; 32-REL-NEXT: Type: R_POS (0x0)
+; 32-REL-NEXT: }
+; 32-REL-NEXT: }
+; 32-REL-NEXT: ]
+
+; 32-REL-NOT: Type: R_RBR (0x1A)
+
+; 32-DIS: Disassembly of section .text:
+; 32-DIS: 00000000 .text:
+; 32-DIS-NEXT: 0: 38 60 00 03 li 3, 3
+; 32-DIS-NEXT: 4: 4e 80 00 20 blr
+; 32-DIS-NEXT: 8: 60 00 00 00 nop
+; 32-DIS-NEXT: c: 60 00 00 00 nop
+; 32-DIS: 00000010 .call_memcpy:
+; 32-DIS-NEXT: 10: 7c 08 02 a6 mflr 0
+; 32-DIS-NEXT: 14: 90 01 00 08 stw 0, 8(1)
+; 32-DIS-NEXT: 18: 94 21 ff c0 stwu 1, -64(1)
+; 32-DIS-NEXT: 1c: 4b ff ff e5 bl .-28
+; 32-DIS-NEXT: 20: 60 00 00 00 nop
+; 32-DIS-NEXT: 24: 38 21 00 40 addi 1, 1, 64
+; 32-DIS-NEXT: 28: 80 01 00 08 lwz 0, 8(1)
+; 32-DIS-NEXT: 2c: 7c 08 03 a6 mtlr 0
+; 32-DIS-NEXT: 30: 4e 80 00 20 blr
; 64-CHECK: LLVM ERROR: 64-bit XCOFF object files are not supported yet.
--- /dev/null
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff -mattr=-altivec -filetype=obj -o %t.o < %s
+; RUN: llvm-readobj --section-headers --file-header %t.o | \
+; RUN: FileCheck --check-prefix=OBJ %s
+; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck --check-prefix=RELOC %s
+; RUN: llvm-readobj -t %t.o | FileCheck --check-prefix=SYM %s
+; RUN: llvm-objdump -D %t.o | FileCheck --check-prefix=DIS %s
+
+; RUN: not llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc64-ibm-aix-xcoff -mattr=-altivec -filetype=obj < %s 2>&1 | \
+; RUN: FileCheck --check-prefix=XCOFF64 %s
+; XCOFF64: LLVM ERROR: 64-bit XCOFF object files are not supported yet.
+
+@globalA = global i32 1, align 4
+@globalB = global i32 2, align 4
+@arr = global <{ i32, [9 x i32] }> <{ i32 3, [9 x i32] zeroinitializer }>, align 4
+@p = global i32* bitcast (i8* getelementptr (i8, i8* bitcast (<{ i32, [9 x i32] }>* @arr to i8*), i64 16) to i32*), align 4
+
+define i32 @foo() {
+entry:
+ %call = call i32 @bar(i32 1)
+ %0 = load i32, i32* @globalA, align 4
+ %add = add nsw i32 %call, %0
+ %1 = load i32, i32* @globalB, align 4
+ %add1 = add nsw i32 %add, %1
+ ret i32 %add1
+}
+
+declare i32 @bar(i32)
+
+; OBJ: File: {{.*}}aix-xcoff-reloc.ll.tmp.o
+; OBJ-NEXT: Format: aixcoff-rs6000
+; OBJ-NEXT: Arch: powerpc
+; OBJ-NEXT: AddressSize: 32bit
+; OBJ-NEXT: FileHeader {
+; OBJ-NEXT: Magic: 0x1DF
+; OBJ-NEXT: NumberOfSections: 2
+; OBJ-NEXT: TimeStamp: None (0x0)
+; OBJ-NEXT: SymbolTableOffset: 0x13C
+; OBJ-NEXT: SymbolTableEntries: 26
+; OBJ-NEXT: OptionalHeaderSize: 0x0
+; OBJ-NEXT: Flags: 0x0
+; OBJ-NEXT: }
+; OBJ-NEXT: Sections [
+; OBJ-NEXT: Section {
+; OBJ-NEXT: Index: 1
+; OBJ-NEXT: Name: .text
+; OBJ-NEXT: PhysicalAddress: 0x0
+; OBJ-NEXT: VirtualAddress: 0x0
+; OBJ-NEXT: Size: 0x40
+; OBJ-NEXT: RawDataOffset: 0x64
+; OBJ-NEXT: RelocationPointer: 0xEC
+; OBJ-NEXT: LineNumberPointer: 0x0
+; OBJ-NEXT: NumberOfRelocations: 3
+; OBJ-NEXT: NumberOfLineNumbers: 0
+; OBJ-NEXT: Type: STYP_TEXT (0x20)
+; OBJ-NEXT: }
+; OBJ-NEXT: Section {
+; OBJ-NEXT: Index: 2
+; OBJ-NEXT: Name: .data
+; OBJ-NEXT: PhysicalAddress: 0x40
+; OBJ-NEXT: VirtualAddress: 0x40
+; OBJ-NEXT: Size: 0x48
+; OBJ-NEXT: RawDataOffset: 0xA4
+; OBJ-NEXT: RelocationPointer: 0x10A
+; OBJ-NEXT: LineNumberPointer: 0x0
+; OBJ-NEXT: NumberOfRelocations: 5
+; OBJ-NEXT: NumberOfLineNumbers: 0
+; OBJ-NEXT: Type: STYP_DATA (0x40)
+; OBJ-NEXT: }
+; OBJ-NEXT: ]
+
+
+; RELOC: File: {{.*}}aix-xcoff-reloc.ll.tmp.o
+; RELOC-NEXT: Format: aixcoff-rs6000
+; RELOC-NEXT: Arch: powerpc
+; RELOC-NEXT: AddressSize: 32bit
+; RELOC-NEXT: Relocations [
+; RELOC-NEXT: Section (index: 1) .text {
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x10
+; RELOC-NEXT: Symbol: .bar (0)
+; RELOC-NEXT: IsSigned: Yes
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 26
+; RELOC-NEXT: Type: R_RBR (0x1A)
+; RELOC-NEXT: }
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x1A
+; RELOC-NEXT: Symbol: globalA (22)
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 16
+; RELOC-NEXT: Type: R_TOC (0x3)
+; RELOC-NEXT: }
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x1E
+; RELOC-NEXT: Symbol: globalB (24)
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 16
+; RELOC-NEXT: Type: R_TOC (0x3)
+; RELOC-NEXT: }
+; RELOC-NEXT: }
+; RELOC-NEXT: Section (index: 2) .data {
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x70
+; RELOC-NEXT: Symbol: arr (12)
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 32
+; RELOC-NEXT: Type: R_POS (0x0)
+; RELOC-NEXT: }
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x74
+; RELOC-NEXT: Symbol: .foo (4)
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 32
+; RELOC-NEXT: Type: R_POS (0x0)
+; RELOC-NEXT: }
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x78
+; RELOC-NEXT: Symbol: TOC (20)
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 32
+; RELOC-NEXT: Type: R_POS (0x0)
+; RELOC-NEXT: }
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x80
+; RELOC-NEXT: Symbol: globalA (8)
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 32
+; RELOC-NEXT: Type: R_POS (0x0)
+; RELOC-NEXT: }
+; RELOC-NEXT: Relocation {
+; RELOC-NEXT: Virtual Address: 0x84
+; RELOC-NEXT: Symbol: globalB (10)
+; RELOC-NEXT: IsSigned: No
+; RELOC-NEXT: FixupBitValue: 0
+; RELOC-NEXT: Length: 32
+; RELOC-NEXT: Type: R_POS (0x0)
+; RELOC-NEXT: }
+; RELOC-NEXT: }
+; RELOC-NEXT: ]
+
+; SYM: Symbols [
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 0
+; SYM-NEXT: Name: .bar
+; SYM-NEXT: Value (RelocatableAddress): 0x0
+; SYM-NEXT: Section: N_UNDEF
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 1
+; SYM-NEXT: SectionLen: 0
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_ER (0x0)
+; SYM-NEXT: StorageMappingClass: XMC_PR (0x0)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 2
+; SYM-NEXT: Name: .text
+; SYM-NEXT: Value (RelocatableAddress): 0x0
+; SYM-NEXT: Section: .text
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_HIDEXT (0x6B)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 3
+; SYM-NEXT: SectionLen: 64
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 4
+; SYM-NEXT: SymbolType: XTY_SD (0x1)
+; SYM-NEXT: StorageMappingClass: XMC_PR (0x0)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 4
+; SYM-NEXT: Name: .foo
+; SYM-NEXT: Value (RelocatableAddress): 0x0
+; SYM-NEXT: Section: .text
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 5
+; SYM-NEXT: ContainingCsectSymbolIndex: 2
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_LD (0x2)
+; SYM-NEXT: StorageMappingClass: XMC_PR (0x0)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 6
+; SYM-NEXT: Name: .data
+; SYM-NEXT: Value (RelocatableAddress): 0x40
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_HIDEXT (0x6B)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 7
+; SYM-NEXT: SectionLen: 52
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 2
+; SYM-NEXT: SymbolType: XTY_SD (0x1)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 8
+; SYM-NEXT: Name: globalA
+; SYM-NEXT: Value (RelocatableAddress): 0x40
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 9
+; SYM-NEXT: ContainingCsectSymbolIndex: 6
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_LD (0x2)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 10
+; SYM-NEXT: Name: globalB
+; SYM-NEXT: Value (RelocatableAddress): 0x44
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 11
+; SYM-NEXT: ContainingCsectSymbolIndex: 6
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_LD (0x2)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 12
+; SYM-NEXT: Name: arr
+; SYM-NEXT: Value (RelocatableAddress): 0x48
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 13
+; SYM-NEXT: ContainingCsectSymbolIndex: 6
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_LD (0x2)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 14
+; SYM-NEXT: Name: p
+; SYM-NEXT: Value (RelocatableAddress): 0x70
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 15
+; SYM-NEXT: ContainingCsectSymbolIndex: 6
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_LD (0x2)
+; SYM-NEXT: StorageMappingClass: XMC_RW (0x5)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 16
+; SYM-NEXT: Name: foo
+; SYM-NEXT: Value (RelocatableAddress): 0x74
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_HIDEXT (0x6B)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 17
+; SYM-NEXT: SectionLen: 12
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_SD (0x1)
+; SYM-NEXT: StorageMappingClass: XMC_DS (0xA)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 18
+; SYM-NEXT: Name: foo
+; SYM-NEXT: Value (RelocatableAddress): 0x74
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_EXT (0x2)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 19
+; SYM-NEXT: ContainingCsectSymbolIndex: 16
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 0
+; SYM-NEXT: SymbolType: XTY_LD (0x2)
+; SYM-NEXT: StorageMappingClass: XMC_DS (0xA)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 20
+; SYM-NEXT: Name: TOC
+; SYM-NEXT: Value (RelocatableAddress): 0x80
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_HIDEXT (0x6B)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 21
+; SYM-NEXT: SectionLen: 0
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 2
+; SYM-NEXT: SymbolType: XTY_SD (0x1)
+; SYM-NEXT: StorageMappingClass: XMC_TC0 (0xF)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 22
+; SYM-NEXT: Name: globalA
+; SYM-NEXT: Value (RelocatableAddress): 0x80
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_HIDEXT (0x6B)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 23
+; SYM-NEXT: SectionLen: 4
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 2
+; SYM-NEXT: SymbolType: XTY_SD (0x1)
+; SYM-NEXT: StorageMappingClass: XMC_TC (0x3)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: Symbol {
+; SYM-NEXT: Index: 24
+; SYM-NEXT: Name: globalB
+; SYM-NEXT: Value (RelocatableAddress): 0x84
+; SYM-NEXT: Section: .data
+; SYM-NEXT: Type: 0x0
+; SYM-NEXT: StorageClass: C_HIDEXT (0x6B)
+; SYM-NEXT: NumberOfAuxEntries: 1
+; SYM-NEXT: CSECT Auxiliary Entry {
+; SYM-NEXT: Index: 25
+; SYM-NEXT: SectionLen: 4
+; SYM-NEXT: ParameterHashIndex: 0x0
+; SYM-NEXT: TypeChkSectNum: 0x0
+; SYM-NEXT: SymbolAlignmentLog2: 2
+; SYM-NEXT: SymbolType: XTY_SD (0x1)
+; SYM-NEXT: StorageMappingClass: XMC_TC (0x3)
+; SYM-NEXT: StabInfoIndex: 0x0
+; SYM-NEXT: StabSectNum: 0x0
+; SYM-NEXT: }
+; SYM-NEXT: }
+; SYM-NEXT: ]
+
+
+; DIS: {{.*}}aix-xcoff-reloc.ll.tmp.o: file format aixcoff-rs6000
+; DIS: Disassembly of section .text:
+; DIS: 00000000 .text:
+; DIS-NEXT: 0: 7c 08 02 a6 mflr 0
+; DIS-NEXT: 4: 90 01 00 08 stw 0, 8(1)
+; DIS-NEXT: 8: 94 21 ff c0 stwu 1, -64(1)
+; DIS-NEXT: c: 38 60 00 01 li 3, 1
+; DIS-NEXT: 10: 4b ff ff f1 bl .-16
+; DIS-NEXT: 14: 60 00 00 00 nop
+; DIS-NEXT: 18: 80 82 00 00 lwz 4, 0(2)
+; DIS-NEXT: 1c: 80 a2 00 04 lwz 5, 4(2)
+; DIS-NEXT: 20: 80 84 00 00 lwz 4, 0(4)
+; DIS-NEXT: 24: 80 a5 00 00 lwz 5, 0(5)
+; DIS-NEXT: 28: 7c 63 22 14 add 3, 3, 4
+; DIS-NEXT: 2c: 7c 63 2a 14 add 3, 3, 5
+; DIS-NEXT: 30: 38 21 00 40 addi 1, 1, 64
+; DIS-NEXT: 34: 80 01 00 08 lwz 0, 8(1)
+; DIS-NEXT: 38: 7c 08 03 a6 mtlr 0
+; DIS-NEXT: 3c: 4e 80 00 20 blr
+
+; DIS: Disassembly of section .data:
+; DIS: 00000040 globalA:
+; DIS-NEXT: 40: 00 00 00 01 <unknown>
+; DIS: 00000044 globalB:
+; DIS-NEXT: 44: 00 00 00 02 <unknown>
+; DIS: 00000048 arr:
+; DIS-NEXT: 48: 00 00 00 03 <unknown>
+; DIS-NEXT: ...
+; DIS: 00000070 p:
+; DIS-NEXT: 70: 00 00 00 58 <unknown>
+; DIS: 00000074 foo:
+; DIS-NEXT: 74: 00 00 00 00 <unknown>
+; DIS-NEXT: 78: 00 00 00 80 <unknown>
+; DIS-NEXT: 7c: 00 00 00 00 <unknown>
+; DIS: 00000080 globalA:
+; DIS-NEXT: 80: 00 00 00 40 <unknown>
+; DIS: 00000084 globalB:
+; DIS-NEXT: 84: 00 00 00 44 <unknown>