From 2b967460b466e3aec55c43d96ce846aedc2e752f Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Tue, 27 Jul 2021 11:26:00 -0400 Subject: [PATCH] [SystemZ][z/OS] Initial code to generate assembly files on z/OS - This patch consists of the bare basic code needed in order to generate some assembly for the z/OS target. - Only the .text and the .bss sections are added for now. - The relevant MCSectionGOFF/Symbol interfaces have been added. This enables us to print out the GOFF machine code sections. - This patch enables us to add simple lit tests wherever possible, and contribute to the testing coverage for the z/OS target - Further improvements and additions will be made in future patches. Reviewed By: tmatheson Differential Revision: https://reviews.llvm.org/D106380 --- .../CodeGen/TargetLoweringObjectFileImpl.h | 11 +++++ include/llvm/MC/MCContext.h | 7 ++- include/llvm/MC/MCObjectFileInfo.h | 1 + include/llvm/MC/MCSection.h | 9 +++- include/llvm/MC/MCSectionGOFF.h | 46 +++++++++++++++++++ include/llvm/MC/MCSymbol.h | 3 ++ include/llvm/MC/MCSymbolGOFF.h | 28 +++++++++++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 22 +++++++++ lib/MC/MCContext.cpp | 17 ++++++- lib/MC/MCObjectFileInfo.cpp | 9 ++++ lib/MC/MCParser/AsmParser.cpp | 2 + lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1 + lib/Target/SystemZ/SystemZTargetMachine.cpp | 11 ++++- test/CodeGen/SystemZ/zos-simple-test.ll | 13 ++++++ 14 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 include/llvm/MC/MCSectionGOFF.h create mode 100644 include/llvm/MC/MCSymbolGOFF.h create mode 100644 test/CodeGen/SystemZ/zos-simple-test.ll diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 690a3f21114..2c8b17807f7 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -284,6 +284,17 @@ public: 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/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index d0edad8f02c..877b2dc4ac9 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -52,6 +52,7 @@ namespace llvm { class MCSection; class MCSectionCOFF; class MCSectionELF; + class MCSectionGOFF; class MCSectionMachO; class MCSectionWasm; class MCSectionXCOFF; @@ -74,7 +75,7 @@ namespace llvm { 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 @@ namespace llvm { SpecificBumpPtrAllocator COFFAllocator; SpecificBumpPtrAllocator ELFAllocator; SpecificBumpPtrAllocator MachOAllocator; + SpecificBumpPtrAllocator GOFFAllocator; SpecificBumpPtrAllocator WasmAllocator; SpecificBumpPtrAllocator XCOFFAllocator; SpecificBumpPtrAllocator MCInstAllocator; @@ -323,6 +325,7 @@ namespace llvm { StringMap MachOUniquingMap; std::map ELFUniquingMap; std::map COFFUniquingMap; + std::map GOFFUniquingMap; std::map WasmUniquingMap; std::map XCOFFUniquingMap; StringMap RelSecNames; @@ -595,6 +598,8 @@ namespace llvm { 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/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index a97cdc39700..8ae86ef2a57 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -426,6 +426,7 @@ private: 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/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index a68e06e661b..4335092f092 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -40,7 +40,14 @@ class MCSection { 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/include/llvm/MC/MCSectionGOFF.h b/include/llvm/MC/MCSectionGOFF.h new file mode 100644 index 00000000000..4ba7f79f969 --- /dev/null +++ b/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/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index a83781f5c58..d8fc4505d44 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -46,6 +46,7 @@ protected: SymbolKindUnset, SymbolKindCOFF, SymbolKindELF, + SymbolKindGOFF, SymbolKindMachO, SymbolKindWasm, SymbolKindXCOFF, @@ -276,6 +277,8 @@ public: 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/include/llvm/MC/MCSymbolGOFF.h b/include/llvm/MC/MCSymbolGOFF.h new file mode 100644 index 00000000000..cc4e2bbe246 --- /dev/null +++ b/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/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 8d8838f81c7..add34eccc1f 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/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 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry( 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/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index af2546cb0a8..aa4051aa240 100644 --- a/lib/MC/MCContext.cpp +++ b/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 @@ MCContext::MCContext(const Triple &TheTriple, const MCAsmInfo *mai, 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 @@ void MCContext::reset() { // Call the destructors so the fragments are freed COFFAllocator.DestroyAll(); ELFAllocator.DestroyAll(); + GOFFAllocator.DestroyAll(); MachOAllocator.DestroyAll(); XCOFFAllocator.DestroyAll(); MCInstAllocator.DestroyAll(); @@ -156,6 +159,7 @@ void MCContext::reset() { MachOUniquingMap.clear(); ELFUniquingMap.clear(); + GOFFUniquingMap.clear(); COFFUniquingMap.clear(); WasmUniquingMap.clear(); XCOFFUniquingMap.clear(); @@ -231,6 +235,8 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry *Name, 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 @@ Optional MCContext::getELFUniqueIDForEntsize(StringRef SectionName, 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/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 1a448f040b3..7ea1106068b 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/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 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { 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 @@ void MCObjectFileInfo::initMCObjectFileInfo(MCContext &MCCtx, bool PIC, case MCContext::IsELF: initELFMCObjectFileInfo(TheTriple, LargeCodeModel); break; + case MCContext::IsGOFF: + initGOFFMCObjectFileInfo(TheTriple); + break; case MCContext::IsWasm: initWasmMCObjectFileInfo(TheTriple); break; diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 45e6dfee4ca..d3cb5ca59bf 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -782,6 +782,8 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 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/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 1ddbe944ec0..e410fe0aeff 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -6369,6 +6369,7 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { case MCContext::IsWasm: CurrentFormat = WASM; break; + case MCContext::IsGOFF: case MCContext::IsXCOFF: llvm_unreachable("unexpected object format"); break; diff --git a/lib/Target/SystemZ/SystemZTargetMachine.cpp b/lib/Target/SystemZ/SystemZTargetMachine.cpp index ebb8ed97bb5..a886f9b9d81 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -97,6 +97,15 @@ static std::string computeDataLayout(const Triple &TT, StringRef CPU, 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 @@ SystemZTargetMachine::SystemZTargetMachine(const Target &T, const Triple &TT, getEffectiveRelocModel(RM), getEffectiveSystemZCodeModel(CM, getEffectiveRelocModel(RM), JIT), OL), - TLOF(std::make_unique()) { + TLOF(createTLOF(getTargetTriple())) { initAsmInfo(); } diff --git a/test/CodeGen/SystemZ/zos-simple-test.ll b/test/CodeGen/SystemZ/zos-simple-test.ll new file mode 100644 index 00000000000..a46079818b1 --- /dev/null +++ b/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 +}