Index: llvm/trunk/include/llvm/BinaryFormat/XCOFF.h =================================================================== --- llvm/trunk/include/llvm/BinaryFormat/XCOFF.h +++ llvm/trunk/include/llvm/BinaryFormat/XCOFF.h @@ -22,6 +22,36 @@ enum { SectionNameSize = 8, SymbolNameSize = 8 }; enum ReservedSectionNum { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 }; +// x_smclas field of x_csect from system header: /usr/include/syms.h +/// Storage Mapping Class definitions. +enum StorageMappingClass { + // READ ONLY CLASSES + XMC_PR = 0, ///< Program Code + XMC_RO = 1, ///< Read Only Constant + XMC_DB = 2, ///< Debug Dictionary Table + XMC_GL = 6, ///< Global Linkage (Interfile Interface Code) + XMC_XO = 7, ///< Extended Operation (Pseudo Machine Instruction) + XMC_SV = 8, ///< Supervisor Call (32-bit process only) + XMC_SV64 = 17, ///< Supervisor Call for 64-bit process + XMC_SV3264 = 18, ///< Supervisor Call for both 32- and 64-bit processes + XMC_TI = 12, ///< Traceback Index csect + XMC_TB = 13, ///< Traceback Table csect + + // READ WRITE CLASSES + XMC_RW = 5, ///< Read Write Data + XMC_TC0 = 15, ///< TOC Anchor for TOC Addressability + XMC_TC = 3, ///< General TOC item + XMC_TD = 16, ///< Scalar data item in the TOC + XMC_DS = 10, ///< Descriptor csect + XMC_UA = 4, ///< Unclassified - Treated as Read Write + XMC_BS = 9, ///< BSS class (uninitialized static internal) + XMC_UC = 11, ///< Un-named Fortran Common + + XMC_TL = 20, ///< Initialized thread-local variable + XMC_UL = 21, ///< Uninitialized thread-local variable + XMC_TE = 22 ///< Symbol mapped at the end of TOC +}; + // Flags for defining the section type. Used for the s_flags field of // the section header structure. Defined in the system header `scnhdr.h`. enum SectionTypeFlags { Index: llvm/trunk/include/llvm/MC/MCAsmInfoXCOFF.h =================================================================== --- llvm/trunk/include/llvm/MC/MCAsmInfoXCOFF.h +++ llvm/trunk/include/llvm/MC/MCAsmInfoXCOFF.h @@ -0,0 +1,25 @@ +//===- MCAsmInfoXCOFF.h - XCOFF asm properties ----------------- *- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFOXCOFF_H +#define LLVM_MC_MCASMINFOXCOFF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + +class MCAsmInfoXCOFF : public MCAsmInfo { + virtual void anchor(); + +protected: + MCAsmInfoXCOFF(); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCASMINFOXCOFF_H Index: llvm/trunk/include/llvm/MC/MCContext.h =================================================================== --- llvm/trunk/include/llvm/MC/MCContext.h +++ llvm/trunk/include/llvm/MC/MCContext.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/BinaryFormat/XCOFF.h" #include "llvm/MC/MCAsmMacro.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -49,6 +50,7 @@ class MCSectionELF; class MCSectionMachO; class MCSectionWasm; + class MCSectionXCOFF; class MCStreamer; class MCSymbol; class MCSymbolELF; @@ -91,6 +93,7 @@ SpecificBumpPtrAllocator ELFAllocator; SpecificBumpPtrAllocator MachOAllocator; SpecificBumpPtrAllocator WasmAllocator; + SpecificBumpPtrAllocator XCOFFAllocator; /// Bindings of names to symbols. SymbolTable Symbols; @@ -246,10 +249,25 @@ } }; + struct XCOFFSectionKey { + std::string SectionName; + XCOFF::StorageMappingClass MappingClass; + + XCOFFSectionKey(StringRef SectionName, + XCOFF::StorageMappingClass MappingClass) + : SectionName(SectionName), MappingClass(MappingClass) {} + + bool operator<(const XCOFFSectionKey &Other) const { + return std::tie(SectionName, MappingClass) < + std::tie(Other.SectionName, Other.MappingClass); + } + }; + StringMap MachOUniquingMap; std::map ELFUniquingMap; std::map COFFUniquingMap; std::map WasmUniquingMap; + std::map XCOFFUniquingMap; StringMap RelSecNames; SpecificBumpPtrAllocator MCSubtargetAllocator; @@ -470,6 +488,11 @@ const MCSymbolWasm *Group, unsigned UniqueID, const char *BeginSymName); + MCSectionXCOFF *getXCOFFSection(StringRef Section, + XCOFF::StorageMappingClass MappingClass, + SectionKind K, + const char *BeginSymName = nullptr); + // Create and save a copy of STI and return a reference to the copy. MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI); Index: llvm/trunk/include/llvm/MC/MCObjectFileInfo.h =================================================================== --- llvm/trunk/include/llvm/MC/MCObjectFileInfo.h +++ llvm/trunk/include/llvm/MC/MCObjectFileInfo.h @@ -400,6 +400,7 @@ void initELFMCObjectFileInfo(const Triple &T, bool Large); void initCOFFMCObjectFileInfo(const Triple &T); void initWasmMCObjectFileInfo(const Triple &T); + void initXCOFFMCObjectFileInfo(const Triple &T); MCSection *getDwarfComdatSection(const char *Name, uint64_t Hash) const; public: Index: llvm/trunk/include/llvm/MC/MCSection.h =================================================================== --- llvm/trunk/include/llvm/MC/MCSection.h +++ llvm/trunk/include/llvm/MC/MCSection.h @@ -37,7 +37,7 @@ /// current translation unit. The MCContext class uniques and creates these. class MCSection { public: - enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm }; + enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm, SV_XCOFF }; /// Express the state of bundle locked groups while emitting code. enum BundleLockStateType { Index: llvm/trunk/include/llvm/MC/MCSectionXCOFF.h =================================================================== --- llvm/trunk/include/llvm/MC/MCSectionXCOFF.h +++ llvm/trunk/include/llvm/MC/MCSectionXCOFF.h @@ -0,0 +1,56 @@ +//===- MCSectionXCOFF.h - XCOFF Machine Code Sections -----------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionXCOFF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONXCOFF_H +#define LLVM_MC_MCSECTIONXCOFF_H + +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/MC/MCSection.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. +class MCSectionXCOFF final : public MCSection { + friend class MCContext; + + StringRef Name; + XCOFF::StorageMappingClass MappingClass; + + MCSectionXCOFF(StringRef Section, XCOFF::StorageMappingClass SMC, + SectionKind K, MCSymbol *Begin) + : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC) {} + +public: + ~MCSectionXCOFF(); + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_XCOFF; + } + + StringRef getSectionName() const { return Name; } + XCOFF::StorageMappingClass getMappingClass() const { return MappingClass; } + + void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; +}; + +} // end namespace llvm + +#endif Index: llvm/trunk/include/llvm/MC/MCXCOFFObjectWriter.h =================================================================== --- llvm/trunk/include/llvm/MC/MCXCOFFObjectWriter.h +++ llvm/trunk/include/llvm/MC/MCXCOFFObjectWriter.h @@ -0,0 +1,41 @@ +//===-- llvm/MC/MCXCOFFObjectWriter.h - XCOFF Object Writer ---------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCXCOFFOBJECTWRITER_H +#define LLVM_MC_MCXCOFFOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" + +namespace llvm { + +class raw_pwrite_stream; + +class MCXCOFFObjectTargetWriter : public MCObjectTargetWriter { +protected: + MCXCOFFObjectTargetWriter(bool Is64Bit); + +public: + ~MCXCOFFObjectTargetWriter() override; + + Triple::ObjectFormatType getFormat() const override { return Triple::XCOFF; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::XCOFF; + } + bool is64Bit() const { return Is64Bit; } + +private: + bool Is64Bit; +}; + +std::unique_ptr +createXCOFFObjectWriter(std::unique_ptr MOTW, + raw_pwrite_stream &OS); + +} // end namespace llvm + +#endif // LLVM_MC_MCXCOFFOBJECTWRITER_H Index: llvm/trunk/include/llvm/MC/MCXCOFFStreamer.h =================================================================== --- llvm/trunk/include/llvm/MC/MCXCOFFStreamer.h +++ llvm/trunk/include/llvm/MC/MCXCOFFStreamer.h @@ -0,0 +1,33 @@ +//===- MCXCOFFObjectStreamer.h - MCStreamer XCOFF Object File Interface ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCXCOFFSTREAMER_H +#define LLVM_MC_MCXCOFFSTREAMER_H + +#include "llvm/MC/MCObjectStreamer.h" + +namespace llvm { + +class MCXCOFFStreamer : public MCObjectStreamer { +public: + MCXCOFFStreamer(MCContext &Context, std::unique_ptr MAB, + std::unique_ptr OW, + std::unique_ptr Emitter); + + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc Loc = SMLoc()) override; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCXCOFFSTREAMER_H Index: llvm/trunk/include/llvm/Support/TargetRegistry.h =================================================================== --- llvm/trunk/include/llvm/Support/TargetRegistry.h +++ llvm/trunk/include/llvm/Support/TargetRegistry.h @@ -100,6 +100,11 @@ std::unique_ptr &&OW, std::unique_ptr &&CE, bool RelaxAll); +MCStreamer *createXCOFFStreamer(MCContext &Ctx, + std::unique_ptr &&TAB, + std::unique_ptr &&OW, + std::unique_ptr &&CE, + bool RelaxAll); MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx); @@ -505,7 +510,9 @@ std::move(Emitter), RelaxAll); break; case Triple::XCOFF: - report_fatal_error("XCOFF MCObjectStreamer not implemented yet."); + S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll); + break; } if (ObjectTargetStreamerCtorFn) ObjectTargetStreamerCtorFn(*S, STI); Index: llvm/trunk/lib/MC/CMakeLists.txt =================================================================== --- llvm/trunk/lib/MC/CMakeLists.txt +++ llvm/trunk/lib/MC/CMakeLists.txt @@ -7,6 +7,7 @@ MCAsmInfoDarwin.cpp MCAsmInfoELF.cpp MCAsmInfoWasm.cpp + MCAsmInfoXCOFF.cpp MCAsmMacro.cpp MCAsmStreamer.cpp MCAssembler.cpp @@ -38,6 +39,7 @@ MCSectionELF.cpp MCSectionMachO.cpp MCSectionWasm.cpp + MCSectionXCOFF.cpp MCStreamer.cpp MCSubtargetInfo.cpp MCSymbol.cpp @@ -49,11 +51,14 @@ MCWin64EH.cpp MCWinCOFFStreamer.cpp MCWinEH.cpp + MCXCOFFObjectTargetWriter.cpp + MCXCOFFStreamer.cpp MachObjectWriter.cpp StringTableBuilder.cpp SubtargetFeature.cpp WasmObjectWriter.cpp WinCOFFObjectWriter.cpp + XCOFFObjectWriter.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/MC Index: llvm/trunk/lib/MC/MCAsmBackend.cpp =================================================================== --- llvm/trunk/lib/MC/MCAsmBackend.cpp +++ llvm/trunk/lib/MC/MCAsmBackend.cpp @@ -16,6 +16,7 @@ #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCWasmObjectWriter.h" #include "llvm/MC/MCWinCOFFObjectWriter.h" +#include "llvm/MC/MCXCOFFObjectWriter.h" #include #include #include @@ -43,6 +44,9 @@ case Triple::Wasm: return createWasmObjectWriter(cast(std::move(TW)), OS); + case Triple::XCOFF: + return createXCOFFObjectWriter( + cast(std::move(TW)), OS); default: llvm_unreachable("unexpected object format"); } Index: llvm/trunk/lib/MC/MCAsmInfoXCOFF.cpp =================================================================== --- llvm/trunk/lib/MC/MCAsmInfoXCOFF.cpp +++ llvm/trunk/lib/MC/MCAsmInfoXCOFF.cpp @@ -0,0 +1,18 @@ +//===- MC/MCAsmInfoXCOFF.cpp - XCOFF asm properties ------------ *- 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/MC/MCAsmInfoXCOFF.h" + +using namespace llvm; + +void MCAsmInfoXCOFF::anchor() {} + +MCAsmInfoXCOFF::MCAsmInfoXCOFF() { + IsLittleEndian = false; + HasDotTypeDotSizeDirective = false; +} Index: llvm/trunk/lib/MC/MCContext.cpp =================================================================== --- llvm/trunk/lib/MC/MCContext.cpp +++ llvm/trunk/lib/MC/MCContext.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCSectionXCOFF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolCOFF.h" @@ -86,6 +87,7 @@ COFFAllocator.DestroyAll(); ELFAllocator.DestroyAll(); MachOAllocator.DestroyAll(); + XCOFFAllocator.DestroyAll(); MCSubtargetAllocator.DestroyAll(); UsedNames.clear(); @@ -107,6 +109,7 @@ ELFUniquingMap.clear(); COFFUniquingMap.clear(); WasmUniquingMap.clear(); + XCOFFUniquingMap.clear(); NextID.clear(); AllowTemporaryLabels = true; @@ -526,6 +529,38 @@ return Result; } +MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section, + XCOFF::StorageMappingClass SMC, + SectionKind Kind, + 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; + + // Otherwise, return a new section. + StringRef CachedName = Entry.first.SectionName; + + MCSymbol *Begin = nullptr; + if (BeginSymName) + Begin = createTempSymbol(BeginSymName, false); + + MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) + MCSectionXCOFF(CachedName, SMC, Kind, Begin); + Entry.second = Result; + + auto *F = new MCDataFragment(); + Result->getFragmentList().insert(Result->begin(), F); + F->setParent(Result); + + if (Begin) + Begin->setFragment(F); + + return Result; +} + MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) { return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI); } Index: llvm/trunk/lib/MC/MCObjectFileInfo.cpp =================================================================== --- llvm/trunk/lib/MC/MCObjectFileInfo.cpp +++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCSectionXCOFF.h" using namespace llvm; @@ -761,6 +762,15 @@ // TODO: Define more sections. } +void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) { + // The default csect for program code. Functions without a specified section + // 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, SectionKind::getText()); +} + void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, MCContext &ctx, bool LargeCodeModel) { @@ -809,8 +819,7 @@ break; case Triple::XCOFF: Env = IsXCOFF; - // TODO: Initialize MCObjectFileInfo for XCOFF format when - // MCSectionXCOFF is ready. + initXCOFFMCObjectFileInfo(TT); break; case Triple::UnknownObjectFormat: report_fatal_error("Cannot initialize MC for unknown object file format."); Index: llvm/trunk/lib/MC/MCSectionXCOFF.cpp =================================================================== --- llvm/trunk/lib/MC/MCSectionXCOFF.cpp +++ llvm/trunk/lib/MC/MCSectionXCOFF.cpp @@ -0,0 +1,33 @@ +//===- lib/MC/MCSectionXCOFF.cpp - XCOFF Code Section Representation ------===// +// +// 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/MC/MCSectionXCOFF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +MCSectionXCOFF::~MCSectionXCOFF() = default; + +void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const { + if (getKind().isText()) { + OS << "\t.csect " << getSectionName() << "[" + << "PR" + << "]" << '\n'; + return; + } + + report_fatal_error("Printing for this SectionKind is unimplemented."); +} + +bool MCSectionXCOFF::UseCodeAlign() const { return getKind().isText(); } + +bool MCSectionXCOFF::isVirtualSection() const { return !getKind().isCommon(); } Index: llvm/trunk/lib/MC/MCXCOFFObjectTargetWriter.cpp =================================================================== --- llvm/trunk/lib/MC/MCXCOFFObjectTargetWriter.cpp +++ llvm/trunk/lib/MC/MCXCOFFObjectTargetWriter.cpp @@ -0,0 +1,16 @@ +//===- MCXCOFFObjectTargetWriter.cpp - XCOFF Target Writer Subclass -------===// +// +// 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/MC/MCXCOFFObjectWriter.h" + +using namespace llvm; + +MCXCOFFObjectTargetWriter::MCXCOFFObjectTargetWriter(bool Is64Bit) + : Is64Bit(Is64Bit) {} + +MCXCOFFObjectTargetWriter::~MCXCOFFObjectTargetWriter() = default; Index: llvm/trunk/lib/MC/MCXCOFFStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCXCOFFStreamer.cpp +++ llvm/trunk/lib/MC/MCXCOFFStreamer.cpp @@ -0,0 +1,59 @@ +//===- lib/MC/MCXCOFFStreamer.cpp - XCOFF Object Output -------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file assembles .s files and emits XCOFF .o object files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCXCOFFStreamer.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context, + std::unique_ptr MAB, + std::unique_ptr OW, + std::unique_ptr Emitter) + : MCObjectStreamer(Context, std::move(MAB), std::move(OW), + std::move(Emitter)) {} + +bool MCXCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { + report_fatal_error("Symbol attributes not implemented for XCOFF."); +} + +void MCXCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + report_fatal_error("Emiting common symbols not implemented for XCOFF."); +} + +void MCXCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment, + SMLoc Loc) { + report_fatal_error("Zero fill not implemented for XCOFF."); +} + +void MCXCOFFStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &) { + report_fatal_error("Instruction emission not implemented for XCOFF."); +} + +MCStreamer *llvm::createXCOFFStreamer(MCContext &Context, + std::unique_ptr &&MAB, + std::unique_ptr &&OW, + std::unique_ptr &&CE, + bool RelaxAll) { + MCXCOFFStreamer *S = new MCXCOFFStreamer(Context, std::move(MAB), + std::move(OW), std::move(CE)); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + return S; +} Index: llvm/trunk/lib/MC/XCOFFObjectWriter.cpp =================================================================== --- llvm/trunk/lib/MC/XCOFFObjectWriter.cpp +++ llvm/trunk/lib/MC/XCOFFObjectWriter.cpp @@ -0,0 +1,94 @@ +//===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements XCOFF object file writer information. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCXCOFFObjectWriter.h" + +using namespace llvm; + +namespace { + +class XCOFFObjectWriter : public MCObjectWriter { + support::endian::Writer W; + std::unique_ptr TargetObjectWriter; + + void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override; + + void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *, + const MCFixup &, MCValue, uint64_t &) override; + + uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override; + +public: + XCOFFObjectWriter(std::unique_ptr MOTW, + raw_pwrite_stream &OS); +}; + +XCOFFObjectWriter::XCOFFObjectWriter( + std::unique_ptr MOTW, raw_pwrite_stream &OS) + : W(OS, support::big), TargetObjectWriter(std::move(MOTW)) {} + +void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &, + const MCAsmLayout &) { + // TODO Implement once we have sections and symbols to handle. +} + +void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &, + const MCFragment *, const MCFixup &, + MCValue, uint64_t &) { + report_fatal_error("XCOFF relocations not supported."); +} + +uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &) { + // We always emit a timestamp of 0 for reproducibility, so ensure incremental + // linking is not enabled, in case, like with Windows COFF, such a timestamp + // is incompatible with incremental linking of XCOFF. + if (Asm.isIncrementalLinkerCompatible()) + report_fatal_error("Incremental linking not supported for XCOFF."); + + if (TargetObjectWriter->is64Bit()) + report_fatal_error("64-bit XCOFF object files are not supported yet."); + + uint64_t StartOffset = W.OS.tell(); + + // TODO FIXME Assign section numbers/finalize sections. + + // TODO FIXME Finalize symbols. + + // Magic. + W.write(0x01df); + // Number of sections. + W.write(0); + // Timestamp field. For reproducible output we write a 0, which represents no + // timestamp. + W.write(0); + // Byte Offset to the start of the symbol table. + W.write(0); + // Number of entries in the symbol table. + W.write(0); + // Size of the optional header. + W.write(0); + // Flags. + W.write(0); + + return W.OS.tell() - StartOffset; +} + +} // end anonymous namespace + +std::unique_ptr +llvm::createXCOFFObjectWriter(std::unique_ptr MOTW, + raw_pwrite_stream &OS) { + return make_unique(std::move(MOTW), OS); +} Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt @@ -8,4 +8,5 @@ PPCPredicates.cpp PPCMachObjectWriter.cpp PPCELFObjectWriter.cpp + PPCXCOFFObjectWriter.cpp ) Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -229,6 +229,17 @@ Optional getFixupKind(StringRef Name) const override; }; +class XCOFFPPCAsmBackend : public PPCAsmBackend { +public: + XCOFFPPCAsmBackend(const Target &T, const Triple &TT) + : PPCAsmBackend(T, TT) {} + + std::unique_ptr + createObjectTargetWriter() const override { + return createPPCXCOFFObjectWriter(TT.isArch64Bit()); + } +}; + } // end anonymous namespace Optional ELFPPCAsmBackend::getFixupKind(StringRef Name) const { @@ -250,5 +261,8 @@ if (TT.isOSDarwin()) return new DarwinPPCAsmBackend(T, TT); + if (TT.isOSBinFormatXCOFF()) + return new XCOFFPPCAsmBackend(T, TT); + return new ELFPPCAsmBackend(T, TT); } Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file contains the declaration of the MCAsmInfoDarwin class. +// This file contains the declarations of the PowerPC MCAsmInfo classes. // //===----------------------------------------------------------------------===// @@ -15,6 +15,7 @@ #include "llvm/MC/MCAsmInfoDarwin.h" #include "llvm/MC/MCAsmInfoELF.h" +#include "llvm/MC/MCAsmInfoXCOFF.h" namespace llvm { class Triple; @@ -33,6 +34,13 @@ explicit PPCELFMCAsmInfo(bool is64Bit, const Triple &); }; +class PPCXCOFFMCAsmInfo : public MCAsmInfoXCOFF { + virtual void anchor(); + +public: + explicit PPCXCOFFMCAsmInfo(bool is64Bit, const Triple &); +}; + } // namespace llvm #endif Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -81,3 +81,9 @@ UseIntegratedAssembler = true; } +void PPCXCOFFMCAsmInfo::anchor() {} + +PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) { + assert(!IsLittleEndian && "Little-endian XCOFF not supported."); + CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4; +} Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -51,6 +51,9 @@ std::unique_ptr createPPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype); +/// Construct a PPC XCOFF object writer. +std::unique_ptr createPPCXCOFFObjectWriter(bool Is64Bit); + /// Returns true iff Val consists of one contiguous run of 1s with any number of /// 0s on either side. The 1s are allowed to wrap from LSB to MSB, so /// 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is not, Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -83,6 +83,8 @@ MCAsmInfo *MAI; if (TheTriple.isOSDarwin()) MAI = new PPCMCAsmInfoDarwin(isPPC64, TheTriple); + else if (TheTriple.isOSBinFormatXCOFF()) + MAI = new PPCXCOFFMCAsmInfo(isPPC64, TheTriple); else MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple); @@ -235,6 +237,27 @@ } }; +class PPCTargetXCOFFStreamer : public PPCTargetStreamer { +public: + PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {} + + void emitTCEntry(const MCSymbol &S) override { + report_fatal_error("TOC entries not supported yet."); + } + + void emitMachine(StringRef CPU) override { + llvm_unreachable("Machine pseudo-ops are invalid for XCOFF."); + } + + void emitAbiVersion(int AbiVersion) override { + llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF."); + } + + void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override { + llvm_unreachable("Local-entry pseudo-ops are invalid for XCOFF."); + } +}; + } // end anonymous namespace static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S, @@ -249,6 +272,8 @@ const Triple &TT = STI.getTargetTriple(); if (TT.isOSBinFormatELF()) return new PPCTargetELFStreamer(S); + if (TT.isOSBinFormatXCOFF()) + return new PPCTargetXCOFFStreamer(S); return new PPCTargetMachOStreamer(S); } Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp @@ -0,0 +1,29 @@ +//===-- PPCXCOFFObjectWriter.cpp - PowerPC XCOFF Writer -------------------===// +// +// +// 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 "PPCMCTargetDesc.h" +#include "llvm/MC/MCXCOFFObjectWriter.h" + +using namespace llvm; + +namespace { +class PPCXCOFFObjectWriter : public MCXCOFFObjectTargetWriter { + +public: + PPCXCOFFObjectWriter(bool Is64Bit); +}; +} // end anonymous namespace + +PPCXCOFFObjectWriter::PPCXCOFFObjectWriter(bool Is64Bit) + : MCXCOFFObjectTargetWriter(Is64Bit) {} + +std::unique_ptr +llvm::createPPCXCOFFObjectWriter(bool Is64Bit) { + return llvm::make_unique(Is64Bit); +} Index: llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ llvm/trunk/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -158,6 +158,14 @@ void EmitStartOfAsmFile(Module &M) override; }; +class PPCAIXAsmPrinter : public PPCAsmPrinter { +public: + PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) + : PPCAsmPrinter(TM, std::move(Streamer)) {} + + StringRef getPassName() const override { return "AIX PPC Assembly Printer"; } +}; + } // end anonymous namespace void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO, @@ -1644,6 +1652,9 @@ std::unique_ptr &&Streamer) { if (tm.getTargetTriple().isMacOSX()) return new PPCDarwinAsmPrinter(tm, std::move(Streamer)); + if (tm.getTargetTriple().isOSAIX()) + return new PPCAIXAsmPrinter(tm, std::move(Streamer)); + return new PPCLinuxAsmPrinter(tm, std::move(Streamer)); } Index: llvm/trunk/test/CodeGen/PowerPC/aix-xcoff-basic.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/aix-xcoff-basic.ll +++ llvm/trunk/test/CodeGen/PowerPC/aix-xcoff-basic.ll @@ -0,0 +1,37 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --file-headers %t.o | FileCheck %s + +; RUN: not llc -mtriple powerpc64-ibm-aix-xcoff -filetype=obj < %s 2>&1 | \ +; RUN: FileCheck --check-prefix=64BIT %s + +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | \ +; RUN: FileCheck --check-prefix=ASM %s + +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \ +; RUN: FileCheck --check-prefix=ASM %s + +target datalayout = "E-m:e-p:32:32-i64:64-n32" +target triple = "powerpc-unknown-aix" + +; NOTE: The object file output and the assembly file output do not describe the +; same abstract XCOFF content due to the limited amount of functionality +; implemented. + +; CHECK: Format: aixcoff-rs6000 +; CHECK-NEXT: Arch: powerpc +; CHECK-NEXT: AddressSize: 32bit +; CHECK-NEXT: FileHeader { +; CHECK-NEXT: Magic: 0x1DF +; CHECK-NEXT: NumberOfSections: 0 +; CHECK-NEXT: TimeStamp: None (0x0) +; CHECK-NEXT: SymbolTableOffset: 0x0 +; CHECK-NEXT: SymbolTableEntries: 0 +; CHECK-NEXT: OptionalHeaderSize: 0x0 +; CHECK-NEXT: Flags: 0x0 +; CHECK-NEXT: } + +; 64BIT: LLVM ERROR: 64-bit XCOFF object files are not supported yet. + +; The csect does not need to be present, but LLVM's default behavior when +; emitting asm is to start the file with the .text section. +; ASM: .csect .text[PR]