diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -284,6 +284,17 @@ const TargetMachine &TM) const override; }; +class TargetLoweringObjectFileGOFF : public TargetLoweringObjectFile { +public: + TargetLoweringObjectFileGOFF(); + ~TargetLoweringObjectFileGOFF() override = default; + + MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; +}; + } // end namespace llvm #endif // LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -52,6 +52,7 @@ class MCSection; class MCSectionCOFF; class MCSectionELF; + class MCSectionGOFF; class MCSectionMachO; class MCSectionWasm; class MCSectionXCOFF; @@ -74,7 +75,7 @@ using DiagHandlerTy = std::function &)>; - enum Environment { IsMachO, IsELF, IsCOFF, IsWasm, IsXCOFF }; + enum Environment { IsMachO, IsELF, IsGOFF, IsCOFF, IsWasm, IsXCOFF }; private: Environment Env; @@ -114,6 +115,7 @@ SpecificBumpPtrAllocator COFFAllocator; SpecificBumpPtrAllocator ELFAllocator; SpecificBumpPtrAllocator MachOAllocator; + SpecificBumpPtrAllocator GOFFAllocator; SpecificBumpPtrAllocator WasmAllocator; SpecificBumpPtrAllocator XCOFFAllocator; SpecificBumpPtrAllocator MCInstAllocator; @@ -323,6 +325,7 @@ StringMap MachOUniquingMap; std::map ELFUniquingMap; std::map COFFUniquingMap; + std::map GOFFUniquingMap; std::map WasmUniquingMap; std::map XCOFFUniquingMap; StringMap RelSecNames; @@ -595,6 +598,8 @@ unsigned Flags, unsigned EntrySize); + MCSectionGOFF *getGOFFSection(StringRef Section, SectionKind Kind); + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, int Selection, diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h --- a/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -426,6 +426,7 @@ void initMachOMCObjectFileInfo(const Triple &T); void initELFMCObjectFileInfo(const Triple &T, bool Large); + void initGOFFMCObjectFileInfo(const Triple &T); void initCOFFMCObjectFileInfo(const Triple &T); void initWasmMCObjectFileInfo(const Triple &T); void initXCOFFMCObjectFileInfo(const Triple &T); diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -40,7 +40,14 @@ public: static constexpr unsigned NonUniqueID = ~0U; - enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm, SV_XCOFF }; + enum SectionVariant { + SV_COFF = 0, + SV_ELF, + SV_GOFF, + SV_MachO, + SV_Wasm, + SV_XCOFF + }; /// Express the state of bundle locked groups while emitting code. enum BundleLockStateType { diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/MC/MCSectionGOFF.h @@ -0,0 +1,46 @@ +//===-- llvm/MC/MCSectionGOFF.h - GOFF 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file declares the MCSectionGOFF class, which contains all of the +/// necessary machine code sections for the GOFF file format. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONGOFF_H +#define LLVM_MC_MCSECTIONGOFF_H + +#include "llvm/MC/MCSection.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class MCExpr; + +class MCSectionGOFF final : public MCSection { +private: + friend class MCContext; + MCSectionGOFF(StringRef Name, SectionKind K) + : MCSection(SV_GOFF, Name, K, nullptr) {} + +public: + void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const override { + OS << "\t.section\t\"" << getName() << "\"\n"; + } + + bool UseCodeAlign() const override { return false; } + + bool isVirtualSection() const override { return false; } + + static bool classof(const MCSection *S) { return S->getVariant() == SV_GOFF; } +}; +} // end namespace llvm + +#endif diff --git a/llvm/include/llvm/MC/MCSymbol.h b/llvm/include/llvm/MC/MCSymbol.h --- a/llvm/include/llvm/MC/MCSymbol.h +++ b/llvm/include/llvm/MC/MCSymbol.h @@ -46,6 +46,7 @@ SymbolKindUnset, SymbolKindCOFF, SymbolKindELF, + SymbolKindGOFF, SymbolKindMachO, SymbolKindWasm, SymbolKindXCOFF, @@ -276,6 +277,8 @@ bool isCOFF() const { return Kind == SymbolKindCOFF; } + bool isGOFF() const { return Kind == SymbolKindGOFF; } + bool isMachO() const { return Kind == SymbolKindMachO; } bool isWasm() const { return Kind == SymbolKindWasm; } diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/MC/MCSymbolGOFF.h @@ -0,0 +1,28 @@ +//===-- llvm/MC/MCSymbolGOFF.h - GOFF Machine Code Symbols ------*- 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the MCSymbolGOFF class +/// +//===----------------------------------------------------------------------===// +#ifndef LLVM_MC_MCSYMBOLGOFF_H +#define LLVM_MC_MCSYMBOLGOFF_H + +#include "llvm/MC/MCSymbol.h" + +namespace llvm { + +class MCSymbolGOFF : public MCSymbol { +public: + MCSymbolGOFF(const StringMapEntry *Name, bool IsTemporary) + : MCSymbol(SymbolKindGOFF, Name, IsTemporary) {} + static bool classof(const MCSymbol *S) { return S->isGOFF(); } +}; +} // end namespace llvm + +#endif diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -48,6 +48,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionGOFF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSectionXCOFF.h" @@ -2521,3 +2522,24 @@ TM.getCodeModel() == CodeModel::Large ? XCOFF::XMC_TE : XCOFF::XMC_TC, XCOFF::XTY_SD)); } + +//===----------------------------------------------------------------------===// +// GOFF +//===----------------------------------------------------------------------===// +TargetLoweringObjectFileGOFF::TargetLoweringObjectFileGOFF() + : TargetLoweringObjectFile() {} + +MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal( + const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { + return SelectSectionForGlobal(GO, Kind, TM); +} + +MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal( + const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { + auto *Symbol = TM.getSymbol(GO); + if (Kind.isBSS()) + return getContext().getGOFFSection(Symbol->getName(), + SectionKind::getBSS()); + + return getContext().getObjectFileInfo()->getTextSection(); +} diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -25,6 +25,7 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionGOFF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSectionXCOFF.h" @@ -32,6 +33,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolCOFF.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCSymbolGOFF.h" #include "llvm/MC/MCSymbolMachO.h" #include "llvm/MC/MCSymbolWasm.h" #include "llvm/MC/MCSymbolXCOFF.h" @@ -99,7 +101,7 @@ Env = IsXCOFF; break; case Triple::GOFF: - report_fatal_error("Cannot initialize MC for GOFF object file format"); + Env = IsGOFF; break; case Triple::UnknownObjectFormat: report_fatal_error("Cannot initialize MC for unknown object file format."); @@ -133,6 +135,7 @@ // Call the destructors so the fragments are freed COFFAllocator.DestroyAll(); ELFAllocator.DestroyAll(); + GOFFAllocator.DestroyAll(); MachOAllocator.DestroyAll(); XCOFFAllocator.DestroyAll(); MCInstAllocator.DestroyAll(); @@ -156,6 +159,7 @@ MachOUniquingMap.clear(); ELFUniquingMap.clear(); + GOFFUniquingMap.clear(); COFFUniquingMap.clear(); WasmUniquingMap.clear(); XCOFFUniquingMap.clear(); @@ -231,6 +235,8 @@ return new (Name, *this) MCSymbolCOFF(Name, IsTemporary); case MCContext::IsELF: return new (Name, *this) MCSymbolELF(Name, IsTemporary); + case MCContext::IsGOFF: + return new (Name, *this) MCSymbolGOFF(Name, IsTemporary); case MCContext::IsMachO: return new (Name, *this) MCSymbolMachO(Name, IsTemporary); case MCContext::IsWasm: @@ -610,6 +616,15 @@ return (I != ELFEntrySizeMap.end()) ? Optional(I->second) : None; } +MCSectionGOFF *MCContext::getGOFFSection(StringRef Section, SectionKind Kind) { + // Do the lookup. If we don't have a hit, return a new section. + auto &GOFFSection = GOFFUniquingMap[Section.str()]; + if (!GOFFSection) + GOFFSection = new (GOFFAllocator.Allocate()) MCSectionGOFF(Section, Kind); + + return GOFFSection; +} + MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -17,6 +17,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionGOFF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSectionXCOFF.h" @@ -504,6 +505,11 @@ Ctx->getELFSection(".pseudo_probe_desc", DebugSecType, 0); } +void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) { + TextSection = Ctx->getGOFFSection(".text", SectionKind::getText()); + BSSSection = Ctx->getGOFFSection(".bss", SectionKind::getBSS()); +} + void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { EHFrameSection = Ctx->getCOFFSection(".eh_frame", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -995,6 +1001,9 @@ case MCContext::IsELF: initELFMCObjectFileInfo(TheTriple, LargeCodeModel); break; + case MCContext::IsGOFF: + initGOFFMCObjectFileInfo(TheTriple); + break; case MCContext::IsWasm: initWasmMCObjectFileInfo(TheTriple); break; diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -782,6 +782,8 @@ case MCContext::IsELF: PlatformParser.reset(createELFAsmParser()); break; + case MCContext::IsGOFF: + report_fatal_error("GOFFAsmParser support not implemented yet"); case MCContext::IsWasm: PlatformParser.reset(createWasmAsmParser()); break; diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -6369,6 +6369,7 @@ case MCContext::IsWasm: CurrentFormat = WASM; break; + case MCContext::IsGOFF: case MCContext::IsXCOFF: llvm_unreachable("unexpected object format"); break; diff --git a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp --- a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -97,6 +97,15 @@ return Ret; } +static std::unique_ptr createTLOF(const Triple &TT) { + if (TT.isOSzOS()) + return std::make_unique(); + + // Note: Some times run with -triple s390x-unknown. + // In this case, default to ELF unless z/OS specifically provided. + return std::make_unique(); +} + static Reloc::Model getEffectiveRelocModel(Optional RM) { // Static code is suitable for use in a dynamic executable; there is no // separate DynamicNoPIC model. @@ -160,7 +169,7 @@ getEffectiveRelocModel(RM), getEffectiveSystemZCodeModel(CM, getEffectiveRelocModel(RM), JIT), OL), - TLOF(std::make_unique()) { + TLOF(createTLOF(getTargetTriple())) { initAsmInfo(); } diff --git a/llvm/test/CodeGen/SystemZ/zos-simple-test.ll b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/zos-simple-test.ll @@ -0,0 +1,13 @@ +; A simple, barebones test to check whether assembly can be emitted +; for the z/OS target +; RUN: llc < %s -mtriple=s390x-ibm-zos | FileCheck %s + +@a = global i32 0, align 4 + +define signext i32 @main() { +; CHECK: .section ".text" +; CHECK: main: +; CHECK: .section "a" +entry: + ret i32 0 +}